HTML5 Canvas绘图笔记(1)

<canvas>是一个可以使用脚本(通常为JavaScript)在其中绘制图形的 HTML 元素.它可以用于制作照片集或者制作简单的动画.

Canvas标签:

canvas标签添加
要使用canvas,首先要在body中添加上canvas标签
canvas标签是一块默认300150大小的画布

*画布宽高设置:

使用canvas标签的属性,width及height直接在行间设置
<canvas id="canvas1" width="800" height="500"></canvas>
此处注意:不要用css样式去改画布大小,这个会导致画布中的图像被拉伸

画布css样式
画布的其他css样式可以正常设置

canvas标签中的内容
canvas标签中的内容是(包括标签)只有在不支持此效果的低版本浏览器中才会显示的;在高版本浏览器中不会显示出来

1
2
3
<canvas id="canvas" width="800" height="500">
只是一个canvas标签,然而你看不到
</canvas>

canvas渲染上下文(The rendering context)

<canvas>元素创造了一个固定大小的画布,它公开了一个或多个渲染上下文,其可以用来绘制和处理要展示的内容。
canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。<canvas>元素有一个做 getContext() 的方法,这个方法是用来获得渲染上下文和它的绘画功能。getContext()只有一个参数,上下文的格式。

1
2
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

代码的第一行通过使用 document.getElementById() 方法来为 <canvas> 元素得到DOM对象。一旦有了元素对象,你可以通过使用它的getContext() 方法来访问绘画上下文。

画布栅格(canvas grid)以及坐标空间。

canvas元素默认被网格所覆盖。
通常来说网格中的一个单元相当于canvas元素中的一像素。栅格的起点为左上角(坐标为(0,0))。所有元素的位置都相对于原点定位。
1

Canvas样式设置

边框设置:context.strokeStyle
填充设置:context.fillStyle
线宽设置:context.lineWidth

1
2
3
context.strokeStyle = "red";
context.lineWidth = 2;
context.fillStyle = 'yellow';

透明度设置:

通过设置 globalAlpha 属性或者使用一个半透明颜色作为轮廓或填充的样式。
globalAlpha = transparency value
这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
globalAlpha 属性在需要绘制大量拥有相同透明度的图形时候相当高效。
透明度设置,也可使用strokeStyle/fillStyle的CSS3颜色值,如:
ctx.strokeStyle = "rgba(255,0,0,0.5)";

Canvas 绘制图形

绘制矩形

不同于SVG,HTML中的元素canvas只支持一种原生的图形绘制:矩形。
canvas提供了三种方法绘制矩形:

  • fillRect(x, y, width, height):绘制一个填充的矩形
  • strokeRect(x, y, width, height):绘制一个矩形的边框
  • clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明。
    – x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。width和height设置矩形的尺寸。
    1
    2
    context.fillStyle = 'yellow';
    context.fillRect(150,150,200,100);

绘制路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。

  • 首先,你需要创建路径起始点。
  • 然后你使用画图命令去画出路径。
  • 之后你把路径封闭。
  • 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

绘制命令:

  • beginPath(): 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
  • closePath(): 闭合路径之后图形绘制命令又重新指向到上下文中。
    这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。
    
  • stroke(): 通过线条来绘制图形轮廓,绘制边框。
  • fill(): 通过填充路径的内容区域生成实心的图形。
    当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
    
  • moveTo(x, y):将笔触移动到指定的坐标x以及y上。
    当canvas初始化或者beginPath()调用后,你通常会使用moveTo()函数设置起点。我们也能够使用moveTo()绘制一些不连续的路径。
    

绘制直线:

绘制直线,需要用到的方法lineTo()。
lineTo(x, y): 绘制一条从当前位置到指定x以及y位置的直线。
设置画笔开始位置:context.moveTo(x,y)
设置画笔结束位置:context.lineTo(x,y)
线段两边圆角:context.lineCap = "round"

1
2
3
4
5
context.strokeStyle = "red";
context.lineWidth = 2;
context.moveTo(100,100);
context.lineTo(500,100);
context.stroke();

绘制三角:

方法就是绘制3条直线.
绘制多条连续线段时,不必每次重新定义起始点,画笔会停在上一段线段的终点,并默认为下一次绘制的起始点.

1
2
3
4
5
6
7
8
context.strokeStyle = "red";
context.lineWidth = 2;

context.moveTo(10,10);
context.lineTo(10,110);
context.lineTo(110,110);
context.lineTo(10,10);
context.stroke();

用绘制直线的方法,进行图形的绘制时;直线封闭处会出现瑕疵,不会完全闭合.因此需要使用context.closePath()命令,这个方法会自动将起点与末点相连。

1
2
3
4
5
6
7
8
9
context.strokeStyle = "red";
context.lineWidth = 2;

context.beginPath();
context.moveTo(10,10);
context.lineTo(10,110);
context.lineTo(110,110);
context.closePath(); //封闭路径后最后一个点就不用定义了
context.stroke();

矩形

除了直接在画布上绘制矩形的三个额外方法,也有rect()方法,将一个矩形路径增加到当前路径上。
rect(x, y, width, height)

1
2
3
4
5
6
context.fillStyle = 'yellow';
context.rect(150,150,200,100);
context.fill();
//上面是定义矩形,等价于下面的绘制矩形
context.fillStyle = 'yellow';
context.fillRect(150,150,200,100);

圆弧

绘制圆弧或者圆,我们使用arc()方法。当然可以使用arcTo().

  • arc(x, y, radius, startAngle, endAngle, anticlockwise)
    画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。
  • arcTo(x1, y1, x2, y2, radius)
    根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
    该方法有五个参数:
  • x:圆心的x坐标
  • y:圆心的y坐标
  • straAngle:开始角度
  • endAngle:结束角度
  • anticlockwise:是否逆时针(true)为逆时针,(false)为顺时针.默认为false,顺时针。

弧度
arc()函数中的角度单位是弧度,不是度数。
角度与弧度的js表达式:radians=(Math.PI/180)degrees。因此,180弧度为:Math.PI;360弧度为:Math.PI2;
弧度说明:不管是顺时针,还是逆时针,弧度都是固定的。
8
2

贝塞尔(bezier)以及二次贝塞尔

二次以及三次贝塞尔曲线都十分有用,一般用来绘制复杂有规律的图形。
3
quadraticCurveTo(cp1x, cp1y, x, y)
绘制二次贝塞尔曲线,x,y为结束点,cp1x,cp1y为控制点。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
绘制三次贝塞尔曲线,x,y为结束点,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二。

二次贝塞尔曲线有一个开始、结束点(蓝色)以及一个控制点(红色),而三次贝塞尔曲线使用两个控制点。
参数x、y在这两个方法中都是结束点坐标。cp1x,cp1y为坐标中的第一个控制点,cp2x,cp2y为坐标中的第二个控制点。

绘制文字

渲染文本:

canvas 提供了两种方法来渲染文本:

  • fillText(text, x, y [, maxWidth])
    在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.
  • strokeText(text, x, y [, maxWidth])
    在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.
    • “text”:中文字内容
    • x:起始x坐标
    • y:起始y坐标

文本样式:

  • font = value: 绘制文本的样式. 这个字符串使用和 CSS font 属性相同的语法. 默认的字体是 10px sans-serif.
  • textAlign = value: 文本对齐选项. 可选的值包括: start, end, left, right or center. 默认值是 start.
  • textBaseline = value: 基线对齐选项. 可选的值包括: top, hanging, middle, alphabetic, ideographic, bottom. 默认值是 alphabetic.
  • direction = value: 文本方向. 可能的值包括: ltr, rtl, inherit. 默认值是 inherit.

下图展示了textBaseline属性支持的不同的基线情况。
4

1
2
3
4
context.lineWidth = 1;
context.strokeStyle = "green";
context.font = "italic 150px arial"
context.strokeText("我是文字",50,200);

渐变样式

1、线性渐变:createLinearGradient(x1,y1,x2,y2)

  • x1/y1:渐变起始位置坐标
  • x2/y2:渐变结束位置坐标

2、径向渐变:createRadiusGradient(x1,y1,r1,x2,y2,r2)

  • x1/y1:渐变起始圆的圆心位置坐标
  • r1:渐变起始圆半径
  • x2/y2:渐变结束圆的圆心位置坐标
  • r2:渐变结束圆半径

3、渐变颜色设置:addColorStop(%,"color");

  • %:渐变进度,用[0,1]之间的数字表示
  • “color”:每个渐变阶段的颜色
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var linearGradient = context.createLinearGradient(10,30,200,200);

    linearGradient.addColorStop(0,"red");
    linearGradient.addColorStop(0.4,"yellow");
    linearGradient.addColorStop(0.8,"green");
    linearGradient.addColorStop(1,"blue");

    context.fillStyle = linearGradient;
    context.fillRect(10,10,200,200)

绘制阴影

阴影颜色:shadowColor = “color”;
阴影模糊度:shadowblur = number;
阴影偏移X:shadowOffsetX = number;
阴影偏移Y:shadowOffsetY = number;

1
2
3
4
5
6
context.shadowColor = "black";
context.shadowBlur = 20;
context.shadowOffsetX = 10;
context.shadowOffsetY = 5;

context.strokeRect(100,100,100,100);

变形 Transformations

状态的保存和恢复

开始绘制复杂图形就必不可少的方法:

  • save()
  • restore()
    save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

Canvas 状态是以堆(stack)的方式保存的,每一次调用 save 方法,当前的状态就会被推入堆中保存起来。这种状态包括:

  • 当前应用的变形(即移动,旋转和缩放等)
  • 当前的裁切路径
    你可以调用任意多次 save 方法。每一次调用 restore 方法,上一个保存的状态就从堆中弹出,所有设定都恢复。

移动 Translating

translate 方法,它用来移动 canvas 和它的原点到一个不同的位置。
translate(x, y)
translate 方法接受两个参数。x 是左右偏移量,y 是上下偏移量,如图所示。
5

旋转 Rotating

rotate 方法,它用于以原点为中心旋转 canvas。
rotate(angle)
这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate 方法。
6

缩放 Scaling

我们用它来增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。
scale(x, y)
scale 方法接受两个参数。x,y 分别是横轴和纵轴的缩放因子,它们都必须是正值。值比 1.0 小表示缩小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。
默认情况下,canvas 的 1 单位就是 1 个像素。
举例说,如果我们设置缩放因子是 0.5,1 个单位就变成对应 0.5 个像素,这样绘制出来的形状就会是原先的一半。同理,设置为 2.0 时,1 个单位就对应变成了 2 像素,绘制的结果就是图形放大了 2 倍。

变形 Transforms

这个方法允许直接对变形矩阵作修改。
transform(m11, m12, m21, m22, dx, dy)
这个方法必须将当前的变形矩阵乘上下面的矩阵:
m11 m21 dx
m12 m22 dy
0 0 1
如果任意一个参数是无限大,变形矩阵也必须被标记为无限大,否则会抛出异常。

setTransform(m11, m12, m21, m22, dx, dy)
这个方法必须重置当前的变形矩阵为单位矩阵,然后以相同的参数调用 transform 方法。如果任意一个参数是无限大,那么变形矩阵也必须被标记为无限大,否则会抛出异常。

context.translate(x,y) 等同于context.transform (1,0,0,1,x,y)或context.transform(0,1,1,0.x,y)
context.scale(x,y)等同于context.transform(x,0,0,y,0,0)或context.transform (0,y,x,0, 0,0);
context.rotate(θ)等同于context.transform(Math.cos(θMath.PI/180),Math.sin(θMath.PI/180),-Math.sin(θMath.PI/180),Math.cos(θMath.PI/180),0,0)或 context.transform(-Math.sin(θMath.PI/180),Math.cos(θMath.PI/180),Math.cos(θMath.PI/180),Math.sin(θMath.PI/180), 0,0)

参考资源:

  1. canvas学习(二) http://www.jianshu.com/p/65de47ef33d2
  2. 玩转html5<canvas>画图 http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html#10
  3. Canvas教程 https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial
坚持原创技术分享,您的支持将鼓励我继续创作!