简单地说:初始状态的canvas是一张透明的画布,我们能用不同方法在canvas上画图。
1 | <canvas width="1440" height="720"></canvas> |
canvas标签的特性只有宽和高可以设置。css中也可以改变它的宽高,但是默认保持原始宽高比。如果在css中强行同时设置宽高的话canvas标签和里面的画面会被拉伸,所以建议使用特性设置宽高。另外,虽然绘制过程中可以作出矢量图,但在浏览器渲染结束以后得到的是位图,这时通过样式放大的图将不会再具有矢量图的特性,马赛克严重。
- 兼容性:目前canvas基本得到了所有较新版本主流浏览器的支持,详见Can I Use Canvas? ,如果遇到了不兼容的浏览器的话,这里也有解决方案:
1 | <canvas width="1440" height="720"> |
- **
</canvas>**是必须的:如果没有写结束标签,那么<canvas>之后的所有内容都会被当做替代内容隐藏。
- canvas也可以用来渲染3d内容,比如使用WebGL。
一、使用步骤
- 在html中插入canvas标签,设置id(比如tutorial);
- 在js中找到canvas标签:
const canvas = document.getElementById('tutorial'); - 检查支持性:
if (!canvas.getContext) return; - 获取canvas2d画布:
const ctx = canvas.getContext('2d'); - 使用canvas自带的方法作画。
二、栅格系统&形状绘制
1. 栅格系统
和绝大部分其他元素一样,默认canvas左上角为原点,向右为x轴正方向,向下为y轴正方向,单位是像素。原点可以用其他方法移动,网格也可以旋转和缩放。
2. 形状绘制
矩形
一共有三个方法可以对矩形范围内的像素进行操作:
fillRect(x, y, width, height)画一个填充了颜色的矩形,x和y代表矩形左上角,下同;strokeRect(x, y, width, height)画一个指定矩形的外边框;clearRect(x, y, width, height)清除指定矩形内所有像素。
路径
canvas只能画矩形和路径,也就是说除了矩形其他所有形状都要先建立路径再画。路径本身是透明的,必须要描边和填充才能在画面上显示出来。
通过路径画画的步骤:
- 用
beginPath方法新建一条路径,相当于把笔拿起来; - 用
moveTo(x, y)方法决定路径起始点(x, y),相当于把笔尖放到点(x, y);路径默认是连续的,想停笔再从新位置开始画就一定要使用moveTo; - 用各种方法拖动路径,相当于在画面上规定想画的线;
- 如果是用
stroke画闭合线条,那么需要手动或者用closePath方法闭合路径;fill画闭合填充不需要; - 重复步骤234直到想画的线条/想填充的区域已经规划好了,用
stroke()或fill()方法描边/填充。
可以绘制的所有路径如下:
线段:用
lineTo(x, y)方法绘制一条从上一个路径的终点/moveTo方法的决定点到(x, y)的路径弧线:用
arc(x, y, r, 开始角度, 结束角度, 是否为逆时针)绘制一条从点(x, y)、以r为半径的弧线。角度使用的是弧度制。贝赛尔曲线:因为缺少视觉反馈,一般会结合辅助工具一起使用。
用
quadraticCurveTo(cp1x, cp1y, x, y)绘制二次贝赛尔曲线。(cp1x, cp1y)为控制点,(x, y)为结束点;用
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)绘制三次贝赛尔曲线。(cp1x, cp1y)为控制点1,(cp2x, cp2y)为控制点2,(x, y)为结束点;
矩形:除了直接画矩形以外,也可以先通过
rect(x, y, width, height)绘制路径再进行描边/填充。这个方法在绘制前会自动执行moveTo(x, y),最后路径会停在(x, y)。
- 用
构造函数Path2D(IE不支持)
- Path2D的实例可以将之前对路径的描述储存为一个路径对象,然后再把它作为
stroke和fill的参数使用描边/填充。这样可以让每个路径独立出来,可读性更强:
1
2
3
4
5
6
7const circle = new Path2D()
circle.arc(50, 50, 25, 0, Math.PI * 2)
ctx.stroke(circle)
const rectangle = new Path2D()
rectangle.rect(20, 20, 10, 20) // 由于rect自动重置起始点所以不用moveTo
ctx.fill(rectangle)可以使用
new Path2D(path)克隆一个新的路径实例path1.addPath(path2[, transform])可以将path2添加到path1中(只能添加一个),之后统一进行处理。transform则可以用来进行矩阵变换。实例化的时候可以用SVG的路径数据来创建路径实例:
1
2
3
4
5
6
7// M20 10:移动到点(20, 10)
// h 70:水平方向正向移动70
// v 80:垂直方向正向移动80
// h -80:垂直方向逆向移动80
// Z:回到起点处
var p = new Path2D("M20 10 h 70 v 80 h -80 Z")
ctx.stroke(p) // 会画出一个斜边在左的直角梯形
- Path2D的实例可以将之前对路径的描述储存为一个路径对象,然后再把它作为
三、色彩
canvas中可以通过设置
strokeStyle和fillStyle的值来分别给描边和填充上色。注意一旦设置了新颜色,这个颜色就是之后所有描边和填充的默认颜色了。想换颜色就再次设置吧。设置颜色时要使用css3标准的有效字符串
透明度:
- 通过改变
globalAlpha的值来设置之后所有颜色的透明度,不透明是1.0(默认),完全透明是0.0; - 单个描边/填充设置颜色的时候就在赋值的时候使用
rgba就好,这个透明度会和globalAlpha的值以乘法叠加。一般只使用这个方法就好。
- 通过改变
四、线条
线条有一系列属性可以修改样式:
lineWidth = value:设置线条宽度。默认为1.0。线宽是指给定路径的中心到两边的粗细。
换句话说就是在路径的两边各绘制线宽的一半。因为画布的坐标并不和像素直接对应,当需要获得精确的水平或垂直线的时候要特别注意。
lineCap = type:设置线条两端的样式;有三种样式可以选择:
- butt(默认)
- round
- square
lineJoin = type:设置两线段结合处的样式;样式有三种:
- round
- bevel
- miter(默认)
miterLimit = value:限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
两线相交时,线段的外侧边缘会被延伸交汇于一点上。线段之间夹角比较大时,交点不会太远,但随着夹角变小,交点距离会呈指数级增大。所以需要限制这个距离,如果交点距离大于设定值,连接效果就会变成 bevel。
setLineDash([a, b]):设置当前虚线样式。接受一个数组[a, b]:a表示实线长度,b表示间隔长度。lineDashOffset:设置虚线样式的起始偏移量。动画里可以通过不断改变其大小来实线虚线移动的效果。getLineDash():返回一个包含当前虚线样式,长度为非负偶数的数组。
五、渐变色
使用步骤:
通过ctx的
createLinearGradient或createRadialGradient方法创建一个渐变对象。createLinearGradient(x1, y1, x2, y2)创建一个从(x1, y1)到(x2, y2)的渐变,方向从第一个点到第二个点。createRadialGradient(x1, y1, r1, x2, y2, r2)创建一个从圆(x1, y1, r1)到圆(x2, y2, r2)的渐变。注意第二个圆一定要完整覆盖住第一个圆。第一个圆内完全是范围0的颜色,第二个圆外完全是范围1的颜色。
使用渐变对象的
addColorStop方法在自己想要的地方添加基色(范围0.0 ~ 1.0)。- 如果两个颜色位置重复了,那么顺序会决定渐变颜色(比如:0处为black、0.5处为white、0.5处为red、1处为blue,那么0
0.5的地方是黑色到白色渐变,然后0.51的地方是红色到蓝色渐变,白色和红色之间不会有渐变)。
- 如果两个颜色位置重复了,那么顺序会决定渐变颜色(比如:0处为black、0.5处为white、0.5处为red、1处为blue,那么0
设置ctx的
fillStyle或strokeStyle属性的值为渐变对象。使用各种描边和填充方法图上渐变色。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 创建渐变对象
const linGrad = ctx.createLinearGradient(0, 0, 10, 20)
const radGrad = ctx.createRadialGradient(100, 100, 0, 110, 110, 14.15)// 第二个圆的半径要大于10√2
// 给线性渐变对象添加一个0.1处为'#f91'、0.9处为'#19f'的渐变
linGrad.addColorStop(.1, '#f91')
linGrad.addColorStop(.9, '#19f')
// 给辐射渐变对象添加0处为白色、0.7处为黑色的渐变
radGrad.addColorStop(0, '#fff')
radGrad.addColorStop(.7, '#000')
// 改变笔刷颜色
ctx.strokeStyle = linGrad
ctx.fillStyle = radGrad
// 给需要的地方上色
ctx.fillRect(90, 90, 130, 130)
ctx.strokeRect(0, 0, 15, 25)
六、图案-pattern
canvas支持用重复图案填充,使用的方法为
createPattern(image, type):- image:可以是Image对象或者另一个canvas画布对象。使用Image实例时要确定图像已经加载完毕,一般将语句放在load事件内。
- type:取值为
repeat、repeat-x、repeat-y、no-repeat
使用方法:
- 获取img对象或者其他canvas对象。
- 使用
ctx.createPattern方法创建一个图案对象。 - 将
fillStyle或strokeStyle属性赋值为图案对象 - 描边或填充
七、阴影
和css中类似,需要设置四个值:
shadowOffsetX和shadowOffsetY:取值为浮点数,设定阴影延伸距离,正方向分别为→和↓。shadowBlur:取值为浮点数,设定模糊程度。shadowColor:取值为标准css颜色值,默认为rgba(0, 0, 0, 0)
八、填充规则
当用到 fill(或者 clip和isPointinPath )时可以选择一个填充规则。该填充规则根据某处在路径的外面或者里面来决定该处是否被填充,这对于自己与自己路径相交或者路径被嵌套的时候是有用的。
1 | ctx.beginPath() |
九、文本
canvas支持绘制文本或者文本的外轮廓:
ctx.fillText(text, x, y [, maxWidth]):从(x, y)处绘制一个内容是text(,最大宽度为maxWidth)的文本ctx.strokeText(text, x, y [, maxWidth]):和上面的方法类似,不同的是绘制的是文本的外轮廓(类似华文彩云)
canvas支持修改文本样式:
ctx.font:和css相同,可以修改是否斜体、文字粗细、文字大小、文字字体ctx.textAlign:和css相同ctxtextBaseline:基线对齐选项。可选的值包括:top,hanging,middle,alphabetic,ideographic,bottom。默认值是alphabetic。ctx.direction:文本方向。可能的值包括:ltr,rtl,inherit。默认值是inherit。
十、图片
canvas中可以使用外链的图片来作图:
- 获取图片/其他canvas元素作为图源。
- 使用
drawImage方法把图片绘制到canvas中。
图源:
- 同一页面内的图片:如果需要用页面内已经读取的img元素内的图片,canvas可以直接使用其dom对象。
- 使用其他域名内的图片:通过跨域,canvas可以加载其他域名内的图片。但如果服务器不允许跨域访问,那么有污染canvas的风险。
- 使用其他canvas元素:drawImage方法支持使用其他canvas的dom对象,该方法常用于缩略图和双缓冲中。
- 读取新图片:可以使用Image构造函数获取一张新图片。不过需要把回调函数放到load事件中,否则要么什么都不会发生,要么会报错。
- 使用
data:url获取图片:使用base64编码的字符串来定义图片。缺点是图片无法缓存,同时图片太大会导致html文件过大。 - 使用视频帧截图:canvas支持使用video标签的视频帧,将当前视频播放的画面渲染到canvas上。
绘图:
drawImage方法有三种使用手段:
ctx.drawImage(image, x, y):最基础的使用方法,以ctx的点(x, y)为左上角,绘制image图源,大小和图源相同。ctx.drawImage(image, x, y, width, height):可以缩放图源的方法,通过width和height来控制绘制在canvas上的宽高。ctx.drawImage(image, x0, y0, width0, height0, x, y, width, height):终极方法,可以截取图源image的内容。从以点(x0, y0)为左上角,以width0和height0为宽高把需要的内容截取出来,然后绘制在canvas上,绘制方法和第二条一样。常用于精灵图的展示。
是否在图像缩放时平滑处理:
图源在被过度缩放时会产生模糊或像素化,canvas默认会将平滑处理功能打开。根据需要也可以关闭这个功能:
ctx.imageSmoothimgEnabled = boolean:默认值为true。



