Canvas 基础汇总
语法
getContext() 用来获得渲染上下文和它的绘画功能(只有一个参数)
检测浏览器是否支持Canvas
1 var canvas = document.getElementById('tutorial'); 2 3 if (canvas.getContext){ 4 var ctx = canvas.getContext('2d'); 5 // drawing code here 6 } else { 7 // canvas-unsupported code here 8 }
绘制矩形
fillRect(x, y, width, height)
绘制一个填充的矩形strokeRect(x, y, width, height)
绘制一个矩形的边框clearRect(x, y, width, height)
清除指定矩形区域,让清除部分完全透明。
绘制路径
beginPath()
新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。closePath()
闭合路径之后图形绘制命令又重新指向到上下文中。stroke()
通过线条来绘制图形轮廓。fill()
通过填充路径的内容区域生成实心的图形。
- 生成路径的第一步叫做beginPath()。本质上,路径是由很多子路径构成,这些子路径都是在一个列表中,所有的子路径(线、弧形、等等)构成图形。而每次这个方法调用之后,列表清空重置,然后我们就可以重新绘制新的图形。
- 第二步就是调用函数指定绘制路径
- 第三,就是闭合路径closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。
注意:当前路径为空,即调用beginPath()之后,或者canvas刚建的时候,第一条路径构造命令通常被视为是moveTo(),无论实际上是什么。出于这个原因,你几乎总是要在设置路径之后专门指定你的起始位置。
注意:当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
移动笔触
moveTo(x, y)
将笔触移动到指定的坐标x以及y上。
当canvas初始化或者beginPath()
调用后,通常会使用moveTo()
函数设置起点。也能够使用moveTo()
绘制一些不连续的路径。
线
lineTo(x, y)
绘制一条从当前位置到指定x以及y位置的直线。
圆弧
arc(x, y, radius, startAngle, endAngle, anticlockwise)
画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
注意:arc()
函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:
弧度 = (Math.PI / 180) * 角度。
二次贝塞尔曲线及三次贝塞尔曲线
quadraticCurveTo(cp1x, cp1y, x, y)
绘制二次贝塞尔曲线,cp1x,cp1y
为一个控制点,x,y为
结束点。bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
绘制三次贝塞尔曲线,cp1x,cp1y
为控制点一,cp2x,cp2y
为控制点二,x,y
为结束点。
右边的图能够很好的描述两者的关系,二次贝塞尔曲线有一个开始点(蓝色)、一个结束点(蓝色)以及一个控制点(红色),而三次贝塞尔曲线有两个控制点。
参数x、y在这两个方法中都是结束点坐标。cp1x,cp1y
为坐标中的第一个控制点,cp2x,cp2y
为坐标中的第二个控制点。
矩形
rect(x, y, width, height)
绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。
Path2D 对象
作用:用来缓存或记录绘画命令,这样你将能快速地回顾路径。
创建对象:
Path2D()
Path2D()
会返回一个新初始化的Path2D对象(可能将某一个路径作为变量——创建一个它的副本,或者将一个包含SVG path数据的字符串作为变量)。
1 new Path2D(); // 空的Path对象 2 new Path2D(path); // 克隆Path对象 3 new Path2D(d); // 从SVG建立Path对象
注意: 所有的路径方法比如 moveTo
, rect
, arc
或quadraticCurveTo
等,都可以在Path2D中使用。
Path2D API 添加了 addPath
作为将path
结合起来的方法。当你想要从几个元素中来创建对象时,这将会很实用。
比如:Path2D.addPath(path [, transform])
- 添加了一条路径到当前路径(可能添加了一个变换矩阵)。
Path2D 示例
1 function draw() { 2 var canvas = document.getElementById('canvas'); 3 if (canvas.getContext){ 4 var ctx = canvas.getContext('2d'); 5 6 var rectangle = new Path2D(); // 创建实例 7 rectangle.rect(10, 10, 50, 50); // 创建矩形 8 9 var circle = new Path2D(); // 创建实例 10 circle.moveTo(125, 35); // 规定画笔起始点 11 circle.arc(100, 35, 25, 0, 2 * Math.PI); // 创建圆 12 13 ctx.stroke(rectangle); // 生成边框图像 14 ctx.fill(circle); // 生成实心图像 15 } 16 }
使用 SVG paths
这条路径将先移动到点 (M10 10)
然后再水平移动80个单位(h 80)
,然后下移80个单位 (v 80)
,接着左移80个单位 (h -80)
,再回到起点处 (z
)。你可以在Path2D constructor 查看这个例子。
1 var p = new Path2D("M10 10 h 80 v 80 h -80 Z");
色彩 Colors
fillStyle = color
设置图形的填充颜色。strokeStyle = color
设置图形轮廓的颜色。
注意:一旦设置了 strokeStyle
或者 fillStyle
的值,那么这个新值就会成为新绘制的图形的默认值。如果要给每个图形上不同的颜色,需要重新设置 fillStyle
或 strokeStyle
的值。
透明度 Transparency
globalAlpha = transparencyValue
这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。- 也可以用 strokeStyle fillStyle 来设置 globalAlpha 的透明度
-
1 // 指定透明颜色,用于描边和填充样式 2 ctx.strokeStyle = "rgba(255,0,0,0.5)"; 3 ctx.fillStyle = "rgba(255,0,0,0.5)";
线型 Line styles
lineWidth = value
设置线条宽度。
lineCap = type
设置线条末端样式。
lineJoin = type
设定线条与线条间接合处的样式。
miterLimit = value
限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
getLineDash()
返回一个包含当前虚线样式,长度为非负偶数的数组。
setLineDash(segments)
设置当前虚线样式。
lineDashOffset = value
设置虚线样式的起始偏移量。
lineCap
属性的例子
- 属性
lineCap
的值决定了线段端点显示的样子。它可以为下面的三种的其中之一:butt
,round
和square
。默认是butt。
lineJoin
属性的例子
lineJoin
的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round
,bevel
和miter。
默认是miter
。
使用虚线
- 用
setLineDash
方法和lineDashOffset
属性来制定虚线样式.setLineDash
方法接受一个数组,来指定线段与间隙的交替;lineDashOffset
属性设置起始偏移量.
渐变 Gradients
createLinearGradient(x1, y1, x2, y2)
createLinearGradient 方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)createRadialGradient(x1, y1, r1, x2, y2, r2)
createRadialGradient 方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。-
1 var lineargradient = ctx.createLinearGradient(0,0,150,150); 2 var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);
gradient.addColorStop(position, color)
addColorStop 方法接受 2 个参数,position
参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color
参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。-
1 var lineargradient = ctx.createLinearGradient(0,0,150,150); 2 lineargradient.addColorStop(0,'white'); 3 lineargradient.addColorStop(1,'black');
图案样式 Patterns
createPattern(image, type)
该方法接受两个参数。Image 可以是一个Image
对象的引用,或者另一个 canvas 对象。Type
必须是下面的字符串值之一:repeat
,repeat-x
,repeat-y
和no-repeat
。
注意: 用 canvas 对象作为 Image
参数在 Firefox 1.5 (Gecko 1.8) 中是无效的
图案的应用跟渐变很类似的,创建出一个 pattern 之后,赋给 fillStyle
或 strokeStyle
属性即可。
1 var img = new Image(); 2 img.src = 'someimage.png'; 3 var ptrn = ctx.createPattern(img,'repeat');
注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。
阴影 Shadows
shadowOffsetX = float
shadowOffsetX
和shadowOffsetY
用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为0
。
shadowOffsetY = float
shadowOffsetX 和shadowOffsetY
用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为0
。shadowBlur = float
shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为0
shadowColor = color
shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
文字阴影的例子
1 function draw() { 2 var ctx = document.getElementById('canvas').getContext('2d'); 3 4 ctx.shadowOffsetX = 2; 5 ctx.shadowOffsetY = 2; 6 ctx.shadowBlur = 2; 7 ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; 8 9 ctx.font = "20px Times New Roman"; 10 ctx.fillStyle = "Black"; 11 ctx.fillText("Sample String", 5, 30); 12 }
Canvas 填充规则
当我们用到 fill
(或者 clip
和isPointinPath
)你可以选择一个填充规则,该填充规则根据某处在路径的外面或者里面来决定该处是否被填充,这对于自己与自己路径相交或者路径被嵌套的时候是有用的。
两个可能的值:
-
"nonzero
": non-zero winding rule, 默认值. "evenodd"
: even-odd winding rule. (偶数规律来填充)
绘制文本
fillText(text, x, y [, maxWidth])
在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.strokeText(text, x, y [, maxWidth])
在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.
有样式的文本
font = value
当前我们用来绘制文本的样式. 这个字符串使用和 CSSfont
属性相同的语法. 默认的字体是10px sans-serif
textAlign = value
文本对齐选项. 可选的值包括:start
,end
,left
,right
orcenter
. 默认值是start
。textBaseline = value
基线对齐选项. 可选的值包括:top
,hanging
,middle
,alphabetic
,ideographic
,bottom
。默认值是alphabetic。
direction = value
文本方向。可能的值包括:ltr
,rtl
,inherit
。默认值是inherit。
-
1 ctx.font = "48px serif"; 2 ctx.textBaseline = "hanging"; 3 ctx.strokeText("Hello world", 0, 100);
预测量文本宽度
measureText()
将返回一个TextMetrics
对象的宽度、所在像素,这些体现文本特性的属性。
示例:
function draw() { var ctx = document.getElementById('canvas').getContext('2d'); var text = ctx.measureText("foo"); // TextMetrics object text.width; // 16; }
获得需要绘制的图片
HTMLImageElement
这些图片是由Image()函数构造出来的,或者任何的
<img>
元素HTMLVideoElement
用一个HTML的<video>
元素作为你的图片源,可以从视频中抓取当前帧作为一个图像HTMLCanvasElement
可以使用另一个<canvas>
元素作为你的图片源。ImageBitmap
这是一个高性能的位图,可以低延迟地绘制,它可以从上述的所有源以及其它几种源中生成。
绘制图片
drawImage(image, x, y)
其中image
是 image 或者 canvas 对象,x
和y 是其在目标 canvas 里的起始坐标。
缩放 Scaling
drawImage(image, x, y, width, height)
这个方法多了2个参数:width
和height,
这两个参数用来控制 当向canvas画入时应该缩放的大小
切片 Slicing
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
相框例子
1 function draw() { 2 var canvas = document.getElementById('canvas'); 3 var ctx = canvas.getContext('2d'); 4 5 // Draw slice 6 ctx.drawImage(document.getElementById('source'), 7 33,71,104,124,21,20,87,104); 8 9 // Draw frame 10 ctx.drawImage(document.getElementById('frame'),0,0); 11 }
状态的保存和恢复 Saving and restoring state
save()
保存画布(canvas)的所有状态restore()
save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
Canvas状态存储在栈中,每当save()
方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:
- 当前应用的变形(即移动,旋转和缩放,见下)
strokeStyle
,fillStyle
,globalAlpha
,lineWidth
,lineCap
,lineJoin
,miterLimit
,shadowOffsetX
,shadowOffsetY
,shadowBlur
,shadowColor
,globalCompositeOperation 的值
- 当前的裁切路径(clipping path),会在下一节介绍
移动 Translating
translate(x, y)
translate
方法接受两个参数。x 是左右偏移量,y 是上下偏移量,如右图所示。
旋转 Rotating
rotate(angle)
这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate
方法。
缩放 Scaling
scale(x, y)
scale
方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比1小,会比缩放图形, 如果比1大会放大图形。默认值为1, 为实际大小。
画布初始情况下, 是以左上角坐标为原点的第一象限。如果参数为负实数, 相当于以x 或 y轴作为对称轴镜像反转 (例如, 使用translate(0,canvas.height); scale(1,-1);
以y轴作为对称轴镜像反转, 就可得到著名的笛卡尔坐标系,左下角为原点)。
注: 画图的方法的长度单位并不是1个像素点。
例如 fillRect(0,0,100,100)
,表示长为100 * canvas默认单位长度,宽为100 * canvas默认单位长度。(canvas默认单位长度为1px)。
变形 Transforms
transform(m11, m12, m21, m22, dx, dy)
这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵,在这里我们用下面的矩阵:-
1 m11 m21 dx 2 m12 m22 dy 3 0 0 1
如果任意一个参数是无限大,变形矩阵也必须被标记为无限大,否则会抛出异常。
这个函数的参数各自代表如下:
m11:水平方向的缩放
m12:水平方向的倾斜偏移
m21:竖直方向的倾斜偏移
m22:竖直方向的缩放
dx:水平方向的移动
dy:竖直方向的移动
resetTransform()
重置当前变形为单位矩阵,它和调用以下语句
是一样的:
1 ctx.setTransform(1, 0, 0, 1, 0, 0);
globalCompositeOperation
我们不仅可以在已有图形后面再画新图形,还可以用来遮盖指定区域,清除画布中的某些部分(清除区域不仅限于矩形,像clearRect()
方法做的那样)以及更多其他操作。
globalCompositeOperation = type
这个属性设定了在画新图形时采用的遮盖策略,其值是一个标识12种遮盖方式的字符串。
裁切路径
clip()
将当前正在构建的路径转换为当前的裁剪路径。
我们使用 clip()
方法来创建一个新的裁切路径。
默认情况下,canvas 有一个与它自身一样大的裁切路径(也就是没有裁切效果)。
绘制星星示例
1 function draw() { 2 var ctx = document.getElementById('canvas').getContext('2d'); 3 ctx.fillRect(0,0,150,150); 4 ctx.translate(75,75); 5 6 // Create a circular clipping path 7 ctx.beginPath(); 8 ctx.arc(0,0,60,0,Math.PI*2,true); 9 ctx.clip(); 10 11 // draw background 12 var lingrad = ctx.createLinearGradient(0,-75,0,75); 13 lingrad.addColorStop(0, '#232256'); 14 lingrad.addColorStop(1, '#143778'); 15 16 ctx.fillStyle = lingrad; 17 ctx.fillRect(-75,-75,150,150); 18 19 // draw stars 20 for (var j=1;j<50;j++){ 21 ctx.save(); 22 ctx.fillStyle = '#fff'; 23 ctx.translate(75-Math.floor(Math.random()*150), 24 75-Math.floor(Math.random()*150)); 25 drawStar(ctx,Math.floor(Math.random()*4)+2); 26 ctx.restore(); 27 } 28 29 } 30 function drawStar(ctx,r){ 31 ctx.save(); 32 ctx.beginPath() 33 ctx.moveTo(r,0); 34 for (var i=0;i<9;i++){ 35 ctx.rotate(Math.PI/5); 36 if(i%2 == 0) { 37 ctx.lineTo((r/0.525731)*0.200811,0); 38 } else { 39 ctx.lineTo(r,0); 40 } 41 } 42 ctx.closePath(); 43 ctx.fill(); 44 ctx.restore(); 45 }
首先,我画了一个与 canvas 一样大小的黑色方形作为背景,然后移动原点至中心点。然后用 clip
方法创建一个弧形的裁切路径。裁切路径也属于 canvas 状态的一部分,可以被保存起来。如果我们在创建新裁切路径时想保留原来的裁切路径,我们需要做的就是保存一下 canvas 的状态。
裁切路径创建之后所有出现在它里面的东西才会画出来。在画线性渐变时我们就会注意到这点。然后会绘制出50 颗随机位置分布(经过缩放)的星星,当然也只有在裁切路径里面的星星才会绘制出来。