基本canvas语法

第一节

1、利用document.getElementById('canvas') 获取指向canvas的引用
2、在canvas对象上调用getContext('2d')方法,获取绘图环境变量
3、font设置字体、fillStyle用来填充fillText设置的字符, strokeStyle用来给strokeText的字符来进行描边。
4、fillStyle,strokeStyle可以是颜色,渐变色,或者图案

code

var canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.font = '38pt Arial';
context.fillStyle = 'cornflowerblue';
context.strokeStyle = 'blue';
context.fillText('Hello Canvas', canvas.width / 2 - 150, canvas.height / 2 + 15);
context.strokeText('Hello Canvas', canvas.width / 2 - 150,     canvas.height / 2 + 15);

QQ20181023-222218@2x.png
第二节 canvas状态的保存和恢复

1、canvas API 提供了两个API save() 和 restore()两个方法
2、save 讲当前canvas的状态推送到一个保存canvas状态的堆栈顶部、restore()将原来保存在栈顶的那一组状态,弹出后,就被设置成canvas当前的状态了,在save和restore之间设置状态,只会持续至restore()方法被调用之前。

第三节 基本的绘制操作

demo 绘制一个时钟

code

1、先画一个圆圈
function drawCirCle () {
    context.beginPath();
    context.arc(canvas.width / 2, canvas.height / 2, RADIUS, 0, Math.PI * 2, true);
    context.stroke();
}

其中 beiginPath 是开始一个新路径
arc是描绘一个圆圈 arc里面的参数有
context.arc(x,y,r,sAngle,eAngle,counterclockwise);

参数 描述
x 圆的中心的 x 坐标。
y 圆的中心的 y 坐标。
r 圆的半径。
sAngle 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle 结束角,以弧度计。
counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。

stroke 是对线条进行描绘

2、画一个实心小点
function drawCenter () {
    context.beginPath();
    context.arc(canvas.width / 2, canvas.height / 2, 5, 0, Math.PI * 2, true);
    context.fill();
}

fill 是实心填充,区分stroke

3、将数字时钟渲染至画面
function drawNumerals () {
    var numerals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    var angle = 0;
    var numeralsWidth = 0;
    numerals.forEach(function (numeral) {
        angle = Math.PI / 6 * (numeral - 3);
        numeralsWidth = context.measureText(numeral).width;
        context.fillText(numeral,
            canvas.width / 2 + Math.cos(angle) * HAND_RADIUS - numeralsWidth / 2,
            canvas.height / 2 + Math.sin(angle) * (HAND_RADIUS) + FONT_HEIGHT / 3
        );
    });
}

mearsureText 用来获取指定文本的宽度
fillText用来渲染在画面上被填充的文本
context.fillText(text,x,y,maxWidth);

参数 描述
text 规定在画布上输出的文本。
x 开始绘制文本的 x 坐标位置(相对于画布)。
y 开始绘制文本的 y 坐标位置(相对于画布)。
maxWidth 可选。允许的最大文本宽度,以像素计。

回想一下高中数学,我们知道了半径以后,分成四个象限的圆,怎么获取每一个角度的坐标轴 就是用sin 和 cos

第四步,画时钟,分钟,秒钟
function drawHand (loc, isHour) {
    var angle = (Math.PI * 2) * (loc / 60) - (Math.PI / 2);
    var handRadius = isHour ? RADIUS - HAND_TRUNCATION - HOUR_HAND_TRUNCATION
                        : RADIUS - HAND_TRUNCATION;
    context.moveTo(canvas.width / 2, canvas.height / 2);
    context.lineTo(
        canvas.width / 2 + Math.cos(angle) * handRadius,
        canvas.height / 2 + Math.sin(angle) * handRadius
    );
    context.stroke();
}

function drawHands () {
    var date = new Date;
    var hour = date.getHours();
    hour = hour > 12 ? hour - 12 : hour;
    drawHand(hour * 5 + (date.getMinutes() / 60) * 5, true, 0.5);
    drawHand(date.getMinutes(), false, 0.5);
    drawHand(date.getSeconds(), false, 0.2);
}

moveTo lineTo 一起用, moveTo 两个参数,表示线开始的起点坐标轴,图中就是以圆心为起点,lineTo是移动到终点的位置的坐标轴
图中区分了一个时针和其他的长度

最后一步 就是设置一个定时器
// initialization

context.font = FONT_HEIGHT + 'px Arial';
loop = setInterval(drawClock, 1000);

第四节 事件处理

鼠标事件 监听鼠标事件可以这样写

canvas.onmousedown = function (e) {
// code
}
也可以这样写
canvas.addEventListener('mousedown', function (e) {
// code
})

将鼠标坐标转换成Canvas坐标

很多时候开发者需要知道鼠标事件的点相对于canvas的位置,而不是在整个窗口中的位置,所以必须进行坐标转换

function windowToCanvas (canvas, x, y) {
        var bbox = canvas.getBoundingClientRect();
        return {
                x: (x - bbox.left) * (canvas.width / bbox.width),
                y: (y - bbox.top) * (canvas.height / bbox.height)
        }
}
canvas.onmousemove = function (e) {
        var loc = windowToCanvas(canvas, e.clientX, e.clientY);
}
code 精灵表坐标查看器
WX20181027-223312.png
var canvas = document.getElementById('canvas');
var readout = document.getElementById('readout');
var context = canvas.getContext('2d');
var spriteSheet = new Image();

var drawSpriteSheet = function () {
    context.drawImage(spriteSheet, 0, 0);
}

var drawBackground = function () {
    var VERTICAL_LINE_SPACING = 12;
    var i = context.canvas.height;

    context.clearRect(0, 0, canvas.width, canvas.height);
    context.strokeStyle = 'lightgrey';
    context.lineWidth = 0.5;

    while (i > VERTICAL_LINE_SPACING * 4) {
        context.beginPath();
        context.moveTo(0, i);
        context.lineTo(context.canvas.width, i);
        context.stroke();
        i -= VERTICAL_LINE_SPACING;
    }
}

function windowToCanvas (canvas, x, y) {
    var bbox = canvas.getBoundingClientRect();
    return {
            x: (x - bbox.left) * (canvas.width / bbox.width),
            y: (y - bbox.top) * (canvas.height / bbox.height)
    }
}

function drawGuideLines(x, y)  {
    context.strokeStyle = 'rgba(0, 0, 230, 0.8)';
    context.lineWidth = 0.5;
    drawVerticalLine(x);
    drawHorizontalLine(y);
}

function drawVerticalLine (x) {
    context.beginPath();
    context.moveTo(x + 0.5, 0);
    context.lineTo(x + 0.5, context.canvas.height);
    context.stroke();
}

function drawHorizontalLine (y) {
    context.beginPath();
    context.moveTo(0, y + 0.5);
    context.lineTo(context.canvas.width, y + 0.5);
    context.stroke();
}

function updateReadout (x, y) {
    readout.innerText = '(' + x + ',' + y + ')';
}

// event handlers
canvas.onmousemove = function (e) {
    var loc = windowToCanvas(canvas, e.clientX, e.clientY);
    drawBackground();
    drawSpriteSheet();
    drawGuideLines(loc.x, loc.y);
    updateReadout(loc.x.toFixed(0), loc.y.toFixed(0));
}

// initial
spriteSheet.src = 'running-sprite-sheet.png';
spriteSheet.onload = function () {
    drawSpriteSheet();
}

drawBackground();

代码中通过canvas.onmouseover来监听鼠标滑入滑出的,通过e来传递该鼠标的位置,转换成相对于canvas的位置,context.drawImage 对canvas画布中插入图片

键盘事件

keydown
keyup
keypress

第五节 绘制表面的保存与恢复

canvas绘制环境对象的另外一个关键功能就是可以对绘图表面自身进行保存和恢复,这种绘制表面的保存与恢复功能,可以让开发者在绘图表面上进行一些临时性的绘制动作。
使用getImageData() 和 putImageData() 方法来保存于恢复绘图环境的绘图表面

第二章 绘制

2.1 坐标系统

以canvas的左上角为原点,X坐标向右方增长,Y坐标向下方增长
canvas的坐标系并不固定的,可以对坐标系统进行平移以及旋转:
平移
旋转
缩放
创建自定义的变换方式,比如切变(错切)

2.2 canvas的绘制模型

1)将图形或图像绘制到一个无限大的透明位图中,在绘制时遵从当前的填充模式,描边模式以及线条样式
2)将图形或图像的阴影绘制到另一幅位图中,在绘制时使用当前绘图环境的阴影设定
3)将阴影中每一个像素的alpha分量乘以绘图环境对象的globalAlpha属性值
4)将绘有阴影的位图与经过剪辑区域剪切过的canvas进行图像合成,在操作时使用当前的合成模式参数
5)将图形和图像的每一个像素颜色分量,乘以绘图环境对象的globalAlpha属性值
6)将绘有图形或图像的位图,合成到当前经过剪辑区域剪切过的canvas位图之上,在操作时使用当前的合成操作符

2.3 矩形的绘制

canvas的API提供了如下三个方法,分别用于矩形的清除,描边,以及填充
clearRect(double x, double y, double w, double h)
strokeRect(double x, double y, double w, double h)
fillRect(double x, double y, double w, double h)

strokeRect 要考虑两个属性
context.lineJoin = 'round' // 矩形边的连接处的样式, round表示圆角矩形
context.lineWidth = 30 // 矩形边的宽度

2.4颜色和透明度

通过strokeStyle 和 fillStyle可以设置颜色与透明度
如: context.fillStyle = 'rgba(0, 0, 255, 0.5)'
css3颜色规范中说道,之所以要增加对HSL格式的支持,是因为RGB方式来指定颜色有两个缺陷
1、它以硬件为导向的,这种表述颜色的形式,是基于“阴极射线管”的
2、它不直观
HSL也有三个分量,表示 色相、饱和度、亮度

2.5 渐变色和图案

2.5.1 渐变色
通过调用createLinearGradient()方法来创建线性渐变
通过传入两点坐标x, y后,返回一个CanvasGradient实例,最后应用程序将该渐变色进行填充,知道将填充属性设置成其他值为止。
创建好渐变色后,该段代码通过调用canvasGradient之中唯一的方法addColorStop()来向渐变色中增加5个“颜色停止点”,该方法接受两个参数: 一个是位于0 ~1.0之间的double值,代表颜色停止点在渐变线上的位置,另一个是DOMSTRING类型的CSS颜色字串值

code
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var gradient = context.createLinearGradient(0, 0, canvas.width, canvas.height);

gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.25, 'white');
gradient.addColorStop(0.5, 'purple');
gradient.addColorStop(0.75, 'red');
gradient.addColorStop(1, 'yellow');

context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
WX20181028-230418.png
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var gradient = context.createLinearGradient(0, 0, 0, canvas.height);

gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.25, 'white');
gradient.addColorStop(0.5, 'purple');
gradient.addColorStop(0.75, 'red');
gradient.addColorStop(1, 'yellow');

context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
WX20181028-230548.png
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var gradient = context.createLinearGradient(0, 0, canvas.width, 0);

gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.25, 'white');
gradient.addColorStop(0.5, 'purple');
gradient.addColorStop(0.75, 'red');
gradient.addColorStop(1, 'yellow');

context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
WX20181028-230746.png
2.5.2 放射线

通过createRadialGradient方法生成一个放射线的gradient
context.createRadialGradient(canvas.width / 2, canvas.height, 10
, canvas.width / 2, 0, 100)
渐变色与放射线区别在于
createRadialGradient 要比 createLinearGradient多传入两个参数,代表起始位置和终点位置的半径

2.5.3图案

通过createPattern 创建一个CanvasPattern对象,这个对象是可以生成在canvas中对图形和文本进行描边和填充的图案,他可以是image元素,canvas元素,或者video元素
createPattern(canvas | image | video, DOMString repetition)
DOMString repetition 可以为 repeat, repeat-x, repeat-y, no-repeat

var patten = context.createPattern(image, repeatString);
...
context.fillStyle = pattern;
2.6 阴影

在canvas中可以通过修改绘图环境中的如下4个属性值来指定阴影效果
shadowColor CSS3格式的颜色
shadowOffsetX 从图形或文本到阴影的水平像素偏移
shadowOffsetY 从图形或文本到阴影的垂直像素偏移
shadowBlur 一个与像素无关的值,该值被用于高斯模糊方程之中,以便对阴影进行模糊化处理

2.7 路径填充描边
2.7.1 路径与子路径

用beginPath 开始一段新路径,该方法会清楚上一次调用rect()方法时创建的子路径
绘制多个途径的时候,如果下一个途径不使用beginPath清空,会使上一个途径被重绘

2.7.2 剪纸效果

非零环绕规则:
对于路径中的任意给定区域,从该区域内部画一条足够长的线,使此线段的终点完全落在路径范围之外,先设置一个计时器,先置为0, 如果是与路径顺时针相交,则加1,如果是与路径的逆时针部分相交,则减1,如果计数器最终值不为0,那么此区域就在路径里面,调用fill()时候会对其进行填充,否则,不会进行填充。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,660评论 2 32
  • 1 Canvas接口元素定义 1.1 getContext()方法 为了在canvas上绘制,你必须先得到一个画布...
    Kevin_Junbaozi阅读 1,281评论 1 2
  •   HTML5 添加的最受欢迎的功能就是 元素。这个元素负责在页面中设定一个区域,然后就可以通过 JavaScri...
    霜天晓阅读 2,989评论 0 2
  • 书中代码示例效果展示:Core HTML5 Canvas Examples 基础知识 canvas元素 canva...
    szu_bee阅读 2,798评论 2 28
  • canvas元素的基础知识 在页面上放置一个canvas元素,就相当于在页面上放置了一块画布,可以在其中进行图形的...
    oWSQo阅读 10,268评论 0 19