一、简介
HTML5 中的定义:“它是依赖分辨率的位图画布,你可以在 canvas 上面绘制任何图形,甚至加载照片。”
- 矩形空白区域
- 通过 javascript 绘制图形
- 可以加载图片
二、HTML 部分
<canvas id="a" width="300" height="300">您的浏览器不支持 canvas</canvas>
简单的在 HTML 页面添加一个 canvas
元素,设定宽高,添加 id
便于 javascript
获取。
- 每个
canvas
初始都是一个白板。 - 样式除了宽高,尽量写在画布里,而不是使用 CSS
canvas
标签里如果添加文本,那么当浏览器不支持canvas
时显示文本
三、绘图上下文环境
var a = document.getElementById('a');
var a_context = a.getContext("2d");
- 获取到
canvas
元素 - 调用它的
getContext()
方法获取绘图上下文环境,参数必须为2d
,未来可能会有3d
- 基于上下文环境的方法进行绘图
绘图上下文包含所有绘制方法和属性的定义。
四、路径
beginPath()
开始新路径
4.1 表示重新开始新的路径。
canvas 是基于状态的绘图,开启一条新的路径,就可以设置新的状态。但是 beginPath()
不会将状态重置回默认值。
**同一条路径上的线条和曲线都会是相同的颜色。**所以需要绘制不同颜色的时候,必须开启新的路径。
closePath()
结束路径
4.2 用于结束路径,与 beginPath()
并不一定成对出现。
注意:默认结束路径后,图形自动封闭,即首尾相连。所以有些时候不会用到结束路径。
stroke()
绘制路径
4.3 绘制已定义的路径
fill()
填充路径
4.4 将准备画的路径块填充
fill()
会覆盖描边 stroke()
边框的一半。所以,在需要描边的填充色,需要先填充,后描边。
isPointInPath()
是否在路径中
4.5 如果指定的点位于当前路径中,则返回 true,否则返回 false
context.isPointInPath(x,y);
x
测试点的 x 坐标y
测试点的 y 坐标
clip()
剪切
4.6 从原始画布剪切任意形状和尺寸的区域
context.clip();
注意:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用
clip()
方法前通过使用save()
方法对当前画布区域进行保存,并在以后的任意时间通过restore()
方法进行恢复。
五、线条以及填充颜色
fillStyle
填充样式
5.1 设置或返回用于填充绘画的颜色、渐变或模式,需要在填充前声明才有效
context.fillStyle=color|gradient|pattern;
color
指示绘图填充色的 CSS 颜色值。默认值是 #000000。gradient
用于填充绘图的渐变对象pattern
用于填充绘图的pattern
对象
strokeStyle
线条样式
5.2 设置或返回用于笔触的颜色、渐变或模式,需要在绘制前声明才有效
context.strokeStyle=color|gradient|pattern;
color
指示绘图笔触颜色的 CSS 颜色值。默认值是 #000000。gradient
用于填充绘图的渐变对象pattern
用于创建pattern
笔触的pattern
对象
lineCap
线条结束端点样式
5.3 设置或返回线条的结束端点样式
context.lineCap="butt|round|square";
butt
默认。向线条的每个末端添加平直的边缘。round
向线条的每个末端添加圆形线帽。square
向线条的每个末端添加正方形线帽。
round
和 square
会使线条略微变长。
lineJoin
线条拐角类型
5.4 设置或返回两条线相交时,所创建的拐角类型
context.lineJoin="bevel|round|miter";
bevel
创建斜角round
创建圆角miter
默认。创建尖角
lineWidth
线条宽度
5.5 设置或返回当前的线条宽度
context.lineWidth=number;
number
当前线条的宽度,以像素计
miterLimit
线条最大斜接长度
5.6 设置或返回最大斜接长度
context.miterLimit=number;
number
正数 如果斜接长度超过miterLimit
的值,边角会以lineJoin
的bevel
类型来显示。
斜接长度指的是在两条线交汇处内角和外角之间的距离。
只有当 lineJoin
属性为 miter
时,miterLimit
才有效。
边角的角度越小,斜接长度就会越大。 为了避免斜接长度过长,我们可以使用 miterLimit 属性。 如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 "bevel" 类型来显示(图解 3):
六、直线路径
moveTo()
起点坐标
6.1 把路径移动到画布中的指定点,不创建线条。声明直线开始的起点坐标。括号里面填写坐标。
context.moveTo(100,100);
lineTo()
终点坐标
6.2 声明直线结束的终点坐标。括号里面填写坐标。
context.moveTo(100,100);//起点
context.lineTo(700,700);//终点
连续出现相当于以前一个为起点继续走向另一个坐标。
context.moveTo(100,100);//起点
context.lineTo(700,700);//终点
context.lineTo(100,700);//以前一个终点为起点坐标
当 lineTo()
在 beginPath()
后面使用时,可以代替 moveTo()
,和 moveTo()
起到相同效果。
6.3 多边形
从 moveTo()
开始,使用 lineTo()
画直线到三个顶点,最终回到起点坐标。
如三角形:
//路径描述
context.moveTo(100,100);
context.lineTo(700,700);
context.lineTo(100,700);
context.lineTo(100,100);
//绘制
context.stroke();
七、贝塞尔曲线
7.1 quadraticCurveTo() 二次贝塞尔
通过使用表示二次贝塞尔曲线的指定控制点,向当前路径添加一个点。
二次贝塞尔曲线需要两个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。最后添加的是结束点
注意:曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用
beginPath()
和moveTo()
方法来定义开始点。
context.quadraticCurveTo(cpx,cpy,x,y);
cpx
,cpy
贝塞尔控制点的坐标x
,y
结束点的坐标
7.2 bezierCurveTo() 三次贝塞尔
通过使用表示三次贝塞尔曲线的指定控制点,向当前路径添加一个点。
三次贝塞尔曲线需要三个点。前两个点是用于三次贝塞尔计算中的控制点,第三个点是曲线的结束点。
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
cp1x
,cp1y
第一个贝塞尔控制点的坐标cp2x
,cp2y
第二个贝塞尔控制点的坐标x
,y
结束点的坐标
八、画弧线、圆
arc()
创建圆路径
8.1 创建弧/曲线(用于创建圆形或部分圆)
context.arc(centerX, centerY, radius, startingAngle, endingAngle, anticlockwise=true);
centerx
,centery
表示圆心位置radius
表示半径startingAngle
,endingAngle
表示开始位置和结束位置anticlockwise
表示true
时为顺时针绘制,false
为逆时针绘制。默认为true
其中角度参数的值:0
表示圆的最右边,0.5*Math.PI
表示最下面,1*Math.PI
表示最左边,1.5*Math.PI
表示最上面,2*Math.PI
表示最右边。这些规定是固定的,不会因为顺逆时针改变。
arcTo()
两切线弧
8.2 创建两切线之间的弧/曲线
context.fillRect(x1,y1,x2,y2,r);
x1
,y1
弧的起点坐标x2
,y2
弧的终点坐标r
弧的半径
使用 stroke()
方法在画布上绘制确切的弧。
8.3 绘制
lineWidth
定义线条粗细strokeStyle
定义描边样式stroke()
描边fillStyle
定义填充样式fill()
填充
8.4 圆
context.arc(100,100,80,0,2*Math.PI,true);
表示从右边(0)开始,顺时针画圆,到右边(2 PI)结束。
九、文本
不同于网页中的文本,绘制在 canvas
中的文本是没有盒模型的,没有浮动、边距、留白、自动换行等。
fillText()
填充文本
9.1 context.fillText("text",x,y);
text
规定在画布上输出的文本x
,y
开始绘制文本的坐标位置
strokeText()
描边文本
9.2 context.strokeText(text,x,y,maxWidth);
text
规定在画布上输出的文本x
,y
开始绘制文本的坐标位置maxWidth
可选。允许的最大文本宽度,以像素计
measureText()
测量文本宽度
9.3 measureText()
方法返回包含一个对象,该对象包含以像素计的指定字体宽度。
context.measureText(text).width;
- text 要测量的文本
font
字体样式
9.4 canvas 中的字体会继承 canvas 元素的字体大小和样式风格。
设置 font
属性覆盖继承值。符合 CSS 规则。
context.font = "bold 12px sans-serif";
属性值里面的每个取值用空格隔开
- font style
- font variant
- font size
- font weight
- lineheight
- font family
使用相对字体大小,如
1.5em
或150%
,是基于canvas
元素本身的字体大小。rem
仍是基于根元素。
textAlign
对齐方式
9.5 类似 CSS 中的 text-align
。
context.textAlign = "start";
取值:start
(默认)、end
、left
、right
、center
。
textBaseline
相对于起点的位置
9.6 控制文本相对于起点的位置。
context.textBaseline = "top";
必须使用引号。
取值:top
、bottom
、hanging
、middle
、alphabetic
、ideographic
十、矩形
rect()
创建矩形
10.1 context.rect(x,y,width,height);
x
,y
矩形左上角的坐标width
,height
矩形的宽高
使用 stroke()
或 fill()
方法在画布上实际地绘制矩形。
fillRect()
已填充矩形
10.2 fillRect(x,y,width,height);
x
,y
表示矩形左上角坐标width
,height
表示宽高
使用 fillStyle
属性来设置用于填充绘图的颜色、渐变或模式。
strokeRect()
已描边矩形
10.3 strokeRect(x,y,width,height);
x
,y
表示矩形左上角坐标width
,height
表示宽高
使用 strokeStyle
属性来设置笔触的颜色、渐变或模式。
clearRect()
清空矩形区域
10.4 context.clearRect(x,y,width,height);
x
,y
表示矩形左上角坐标width
,height
表示宽高
十一、添加图片
drawImage()
添加图片
11.1 三种用法:
context.drawImage(img,x,y);
context.drawImage(img,x,y,width,height);
context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)
image
为图片对象,必须sx
,sy
为裁剪开始位置,左上角坐标,可选sw
,sh
为裁剪宽高,可选dx
,dy
为绘制起点,左上角坐标,必须dw
,dh
为自定义的图片宽高,可选
11.2 图片对象
- 已存在的
<img>
元素
//HTML部分
<img id="cat" src="images/cat.png">
//javascript部分
window.onload = function() {
.
.
var cat = document.getElementById('cat');
context.drawImage(cat,0,0);
}
在 window.onload
事件处理器中,获取已有图片对象,然后在 canvas
中安全绘制图片。
- 自己创建的图片对象
var cat = new Image();
cat.src = "images/cat.png";
cat.onload = function() {
context.drawImage(cat,0,0);
};
创建图片对象,然后在 cat.onload 事件处理器中安全地把图片绘制在 canvas
中。
十二、特殊样式
shadowColor
阴影颜色
12.1 设置或返回用于阴影的颜色
context.shadowColor=color;
color
用于阴影的 CSS 颜色值。默认值是 #000000。
shadowBlur
阴影模糊程度
12.2 设置或返回用于阴影的模糊级别
context.shadowBlur=number;
number
阴影的模糊级数
shadowOffsetX
阴影水平偏移
12.3 设置或返回阴影距形状的水平距离
context.shadowOffsetX=number;
number
正值或负值,定义阴影与形状的水平距离。
shadowOffsetY
阴影垂直偏移
12.4 设置或返回阴影距形状的垂直距离
context.shadowOffsetY=number;
number
正值或负值,定义阴影与形状的垂直距离
createPattern()
重复
12.5 在指定的方向内重复指定的元素。
元素可以是图片、视频,或者其他 canvas 元素。 被重复的元素可用于绘制/填充矩形、圆形或线条等等。
context.createPattern(image,"repeat|repeat-x|repeat-y|no-repeat");
image
规定要使用的图片、画布或视频元素。repeat
默认。该模式在水平和垂直方向重复。repeat-x
该模式只在水平方向重复。repeat-y
该模式只在垂直方向重复。no-repeat
该模式只显示一次(不重复)。
createLinearGradient()
创建线性渐变
12.6 调用 createLinearGradient()
方法创建线性渐变
createLinearGradient(x0,y0,x1,y1);
表示沿直线从(x0,y0)到(x1,y1)绘制渐变。
如水平渐变:
var my_gradient = context.createLinearGradient(0,0,300,0);
设置两个 y
值为 0,渐变会沿水平从左到右。
注意:创建渐变需要赋给一个变量,通过这个变量设置色标
createRadialGradient()
创建径向渐变
12.7 调用 createRadialGradient()
方法创建径向渐变
createRadialGradient(x0,y0,r0,x1,y1,r1)
表示沿着两个圆之间的锥面绘制渐变。 前三个参数代表开始圆,后三个参数表示结束圆。
addColorStop()
添加色标
12.8 addColorStop(index,color);
index
渐变位置,可以在 0 - 1 之间取任意值color
渐变颜色,关键字及十六进制颜色要添加引号
注意:这个方法属于创建的渐变对象,也就是前面创建渐变时的变量。
my_gradient.addColorStop(0,"block");
my_gradient.addColorStop(1,"white");
12.9 绘制渐变
context.fillStyle = my_gradient;
context.fillRect(0,0,300,225);
- 将填充颜色设置为创建的渐变
- 填充所需要的图形
十三、转换
转换都应该放在绘制之前
13.1 scale() 缩放
缩放当前绘图至更大或更小
注意:如果您对绘图进行缩放,所有之后的绘图也会被缩放。定位也会被缩放,线条大小也会被缩放。
context.scale(scalewidth,scaleheight);
scalewidth
缩放当前绘图的宽度 (1=100%, 0.5=50%, 2=200%, 依次类推)scaleheight
缩放当前绘图的高度 (1=100%, 0.5=50%, 2=200%, etc.)
13.2 rotate() 旋转
旋转当前绘图
conntext.rotate(angle);
angle
旋转角度,以弧度计。
将角度转换为弧度,请使用 degrees*Math.PI/180
公式进行计算。
13.3 translate() 改变原点坐标
重新映射画布上的 (0,0) 位置,改变坐标原点的位置
context.translate(x,y);
x
添加到水平坐标上的值y
添加到垂直坐标上的值
当您在 translate()
之后调用诸如 fillRect()
之类的方法时,值会添加到 x
和 y
坐标值上。,即后面的绘图涉及到坐标都会在此基础上增加值。
13.4 transform() 变换矩阵
画布上的每个对象都拥有一个当前的变换矩阵。
transform()
方法替换当前的变换矩阵。
它以下面描述的矩阵来操作当前的变换矩阵:
a c e
b d f
0 0 1
也就是说,transform()
允许您缩放、旋转、移动并倾斜当前的环境。
注意:该变换只会影响
transform()
方法调用之后的绘图。 前面的rotate()
,scale()
,translate()
,transform()
方法都会影响到当前的transform()
。 例如:如果您已经将绘图设置为放到两倍,则transform()
方法会把绘图放大两倍,您的绘图最终将放大四倍。
context.transform(a,b,c,d,e,f);
a
水平缩放绘图b
水平倾斜绘图c
垂直倾斜绘图d
垂直缩放绘图e
水平移动绘图f
垂直移动绘图
13.5 setTransform()
将当前转换重置为单位矩阵。然后以同样的参数运行 transform()
,这样就可以不受前面的影响了。
context.setTransform(a,b,c,d,e,f);
a
水平缩放绘图,默认值为 1b
水平倾斜绘图,默认值为 0c
垂直倾斜绘图,默认值为 0d
垂直缩放绘图,默认值为 1e
水平移动绘图,默认值为 0f
垂直移动绘图,默认值为 0
所以矩阵默认为单位矩阵:
1 0 0
0 1 0
0 0 1
13.6 save()、 restore()
save()
保存当前环境的状态- 原点位置
- 缩放大小
- 旋转
- 矩阵变换
- 裁剪块
restore()
返回之前保存过的路径状态和属性
ImageData
对象
十四 对于 ImageData
对象中的每个像素,都存在着四方面的信息,即 RGBA 值:
- R - 红色 (0-255)
- G - 绿色 (0-255)
- B - 蓝色 (0-255)
- A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
因此 ,transparent black
表示 (0,0,0,0)
。
color/alpha
以数组形式存在,并且既然数组包含了每个像素的四条信息,数组的大小是 ImageData
对象的四倍。获得数组大小的办法,就是使用 ImageDataObject.data.length
包含 color/alpha
信息的数组存储于 ImageData
对象的 data
属性中。
createImageData()
创建 ImageData 对象
14.1 创建新的空白 ImageData
对象。
有两个版本的 createImageData()
方法:
//以指定的尺寸(以像素计)创建新的 ImageData 对象
var imgData=context.createImageData(width,height);
//创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据)
var imgData=context.createImageData(imageData);
新对象的默认像素值 transparent black
。
width
ImageData 对象的宽度,以像素计。height
ImageData 对象的高度,以像素计。imageData
另一个 ImageData 对象。
getImageData()
复制画布像素数据
14.2 返回 ImageData
对象,该对象拷贝了画布指定矩形的像素数据,进行操作后,通过 putImageData()
将图像数据放回画布
var imgData = context.getImageData(x,y,width,height);
x
,y
开始复制的左上角位置的坐标width
,height
将要复制的矩形区域的宽高
putImageData()
放入像素数据
14.3 将图像数据(从指定的 ImageData 对象)放回画布上。
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
imgData
规定要放回画布的 ImageData 对象x
,y
ImageData 对象放置在画布上的位置左上角的坐标,以像素计dirtyX
,dirtyY
可选。以像素计,在画布上绘制的图像在 ImageData 对象上的位置坐标dirtyWidth
,dirtyHeight
可选。在画布上绘制图像的宽高
后面四个属性相当于裁剪,但是,在画布上,依然是整个 ImageData 对象。 如:
var imgData=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData,10,70,20,40,30,10);
在画布上放置裁剪部分的位置就变成了(10+20,70+40),宽高是 30, 10。
注意:如果裁剪位置加上裁剪宽度,超出了原来的宽高,超出部分不会绘制
width
、height
宽高
14.4 返回 ImageData 对象的宽高,以像素计。
imgData.width;
imgData.height;
data
图像数据
14.5 返回一个对象,该对象包含指定的 ImageData 对象的图像数据。
对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值: R - 红色 (0-255) G - 绿色 (0-255) B - 蓝色 (0-255) A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的) color/alpha 以数组形式存在,并存储于 ImageData 对象的 data 属性中。
将 ImageData 对象中的第一个像素变为红色的语法:
imgData=ctx.createImageData(100,100);
imgData.data[0]=255;
imgData.data[1]=0;
imgData.data[2]=0;
imgData.data[3]=255;
将 ImageData 对象中的第二个像素变为绿色的语法:
imgData=ctx.createImageData(100,100);
imgData.data[4]=0;
imgData.data[5]=255;
imgData.data[6]=0;
imgData.data[7]=255;
十五、合成
globalAlpha
透明度
15.1 设置或返回绘图的当前 alpha 或透明值
context.globalAlpha=number;
number
透明值。必须介于 0.0(完全透明) 与 1.0(不透明) 之间。
15.2 globalCompositeOperation
设置或返回新图像如何绘制到已有的图像上
源图像 = 您打算放置到画布上的绘图。 目标图像 = 您已经放置在画布上的绘图。
context.globalCompositeOperation="source-in";
source-over
默认。在目标图像上显示源图像。source-atop
在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。source-in
在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。source-out
在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。destination-over
在源图像上方显示目标图像。destination-atop
在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。destination-in
在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。destination-out
在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。lighter
显示源图像 + 目标图像。copy
显示源图像。忽略目标图像。xor
使用异或操作对源图像与目标图像进行组合。
十六、兼容IE
虽然 IE 浏览器不支持 canvas API
,但是他有一个叫 VML
的技术,可以完成 canvas
元素能做的大部分工作。
16.1 ExplorerCanvas——excanvas.js
excanvas.js 是一个开源的,采用 Apache license 许可的 javascript 类库,在 IE 中实现了 canvas 的 API。
<!--[if lt IE9]>
<script src="excanvas.js"></script>
<![endif]-->
16.2 限制
- 颜色渐变只支持线性渐变
- 模式必须在两个方向上重复
- 不支持裁剪
- 非等比缩放
- 很慢