canvas 用法
基础用法
创建画布
1 | <canvas id="my_canvas" width="500px" height="500px" > |
canvas
为替换内容,如果浏览器不支持canvas
,就会显示元素内部的内容width
、height
都是可选属性,用于定义canvas
的宽高。默认宽高为300px*150px
。id
属性用于绘制时,找到该画布。
渲染上下文
canvas
元素的getContext()
方法可以获取渲染上下文和绘功能,参数’2d’表示开启 2D 绘图。
1 | let my_canvas=document.getElementById('my_canvas'); |
检查 JS 的支持性
1 | if(my_canvas.getContext){ |
绘制图形
矩形
fillRect(x,y,width,height)
绘制填充矩形strokeRect(x,y,width,height)
绘制描边矩形clearRect(x,y,width,height)
清除指定矩形区域,让清除部分完全透明x,y
指画布上所绘制矩形的左上角(相对于画布的左上角(0,0))width,height
设置矩形的尺寸
1 | function draw(ctx) { |
路径/直线
beginPath()
开始一条新路径closePath()
闭合路径,会自动将起点和终点连接起来,如果不需要连接,可以不使用。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。stroke()
绘制图形轮廓fill()
填充路径内容区域的生成的实心图形moveTo()
将笔触移动到指定的坐标(x,y)
上lineTo()
绘制一条从当前位置到坐标(x,y)
上的直线
1 | function draw(ctx) { |
圆弧
arc(x,y,radius,startAngle,endAngle,anticlockwise)
画一个以(x,y)
为圆心,以radius
为半径的圆弧(圆),从startAngle
开始到endAngle
结束,按照anticlockwise
给定的方向(默认顺时针)来生成。startAngle
以及endAngle
参数用弧度定义了开始以及结束的弧度,都是以x
轴为基准。
单位是弧度不是角度,弧度=(Math.PI/180)*角度
anticlockwise
为true
是逆时针,否则为顺时针
arcTo(x1,y1,x2,y2,radius)
从坐标(x1,y1)
到坐标(x2,y2)
以半径 radius 画一段圆弧,再以直线连接两个控制点。
1 | function draw(ctx) { |
贝塞尔曲线
quadraticCurveTo(cp1x, cp1y, x, y)
二次贝塞尔曲线,cp1x,cp1y
为一个控制点,x,y
为结束点bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
三次贝塞尔曲线,cp1x,cp1y
为控制点一,cp2x,cp2y
为控制点一,x,y
为结束点
1 | function draw(ctx) { |
1 | function draw(ctx) { |
Path2D 对象
返回一个初始化的 Path2D 对象,参数可以是一个路径或 SVG path 数据的字符串,就是创建参数的副本。
1 | new Path2D(); |
path2D.addPath(path[,transform])
也可以给对象添加新路径或变化矩阵。
1 | function draw(ctx) { |
1 | function draw(ctx) { |
样式和颜色
填充颜色
fillStyle=color
,设置图形的填充颜色轮廓颜色
strokeStyle=color
,设置图形轮廓的颜色
默认填充颜色和轮廓颜色都是黑色('#000'
/'black'
/rgba(0,0,0,1)
)的。color
可以是颜色值,渐变对象或图案对象。
1 | function draw(ctx) { |
1 | function draw(ctx) { |
- 透明度
globalAlpha=transparent
设置整个canvas
里所有图形的透明度,范围是 0.0(完全透明)到 1.0(完全不透明)。
同样可以设置strokeStyle
或fillStyle
的值为透明度(rgba
)的颜色
1 | function draw() { |
1 | function draw(ctx) { |
线型 line styles
lineWidth=value
,设置线条宽度,默认为 1.0,必须为正数。1
2
3
4
5
6
7
8
9
10function draw(ctx) {
for (let i = 0; i < 10; i++) {
ctx.beginPath();
ctx.moveTo(5 + i * 15, 5);
ctx.lineWidth = i + 1;
ctx.lineTo(5 + i * 15, 100);
ctx.stroke()
ctx.closePath()
}
}lineCap=type
,设置线条末端样式butt
:默认,方头与辅助线齐平round
:圆头,半径为宽度的一半square
:方头,端点处加上了等宽且高度为一半线宽的方块。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function draw(ctx) {
let lineCap = ['butt', 'round', 'square'];
//辅助线
ctx.strokeStyle = '#09f';
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(140, 10);
ctx.moveTo(10, 140);
ctx.lineTo(140, 140);
ctx.stroke();
//线条
ctx.strokeStyle = 'black';
for (let i = 0; i < lineCap.length; i++) {
ctx.lineWidth = 15;
ctx.lineCap = lineCap[i];
ctx.beginPath();
ctx.moveTo(30 + 40 * i, 10);
ctx.lineTo(30 + 40 * i, 140);
ctx.stroke();
ctx.closePath()
}
}
lineJoin=type
,设定线条与线条间结合处的样式round
,bevel
,miter
,默认
1 | function draw(ctx) { |
miterLimit=value
,限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。getLineDash()
,返回一个包含当前虚线的样式,长度为非负偶数的数组。setLineDash(segments)
,设置当前虚线样式。lineDashOffset=value
,设置虚线样式的起始偏移量。
1 | var offset = 0; |
渐变
createLinearGradient(x1, y1, x2, y2)
渐变起点(x1,y1)终点(x2,y2);createRadialGradient(x1, y1, r1, x2, y2, r2)
定义两个圆:一个是小圆,是外面大圆的反光,以(x1,y1)为圆点,r1 为圆心,另一个以(x2,y2)为圆心,r2 为半径。gradient.addColorStop(position, color)
给创建的渐变对象gradient
上色,position
:渐变颜色的所在位置,[0.0, 1.0]
1 | function draw(ctx) { |
第一是背景渐变,
第二种渐变不是从 0.0 开始的,所以 0-0.5 都是黑色的。
1 | function draw(ctx) { |
图案样式
createPattern(image,type)
image
:是一个image
对象的引用,或另一个canvas
对象。type
:repeat
,repeat-x
,repeat-y
,no-repeat
1 | function draw(ctx) { |
阴影 shadows
shadowOffsetX=float
shadowOffsetY=float
shadowOffsetX
和shadowOffsetY
用来设定阴影在X
和Y
轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。shadowBlur=float
用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。shadowColor=color
阴影颜色,默认是全透明的黑色。1
2
3
4
5
6
7
8
9
10function draw(ctx) {
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(255,0,0,0.5)";
ctx.font = '20px times New Roman';
ctx.fillStyle = "black";
ctx.fillText('Sample String', 5, 50)
}
Canvas 填充规则
用fill
,clip
,isPointinPath
填充,可以使用以下填充规则:
nonzero
:non-zero winding rule,默认值evenodd
:even-odd winding rule,颜色间隔出现
1 | function draw(ctx) { |
绘制文本
fillText(text,x,y[,maxWidth])
指定在(x,y)
位置填充指定文本,绘制的最大宽度可选。strokeText(text, x, y [,maxWidth])
指定在(x,y)
位置填充指定文本,绘制的最大宽度可选1
2
3
4
5function draw(ctx) {
ctx.font = '48px serif'
ctx.fillText('fillText', 10, 50);
ctx.strokeText('strokeText', 10, 90)
}
文本样式
font=value
与 css 属性相同,默认10px sans-serif
textAlign=value
, 文本对齐方式start
默认end
left
right
center
textBaseline=value
,基线对齐选项top
hanging
middle
alphabetic
默认ideographic
bottom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19function draw(ctx) {
ctx.strokeStyle = 'red';
ctx.font = '28px serif'
ctx.moveTo(0, 40);
ctx.lineTo(650, 40);
ctx.stroke();
ctx.textBaseline = 'top'
ctx.fillText('top', 10, 40);
ctx.textBaseline = 'middle'
ctx.fillText('middle', 60, 40)
ctx.textBaseline = 'hanging'
ctx.fillText('hanging', 160, 40)
ctx.textBaseline = 'alphabetic'
ctx.fillText('alphabetic', 270, 40)
ctx.textBaseline = 'ideographic'
ctx.fillText('ideographic', 410, 40)
ctx.textBaseline = 'bottom'
ctx.fillText('bottom', 560, 40)
}
direction=value
,文本方向ltr
rtl
inherit
默认
预测量文本宽度
measureText()
返回有个TextMwtrics
对象的宽度、所在像素
绘制图像
获取图像源
获得需要绘制的图片
HTMLImageElement
由Image()
函数构造出来的元素,或者<img>
元素HTMLVideoElement
<video></video>
元素,从视频中抓取当前帧作为一个图像HTMLCanvasElement
使用另外一个<canvas></canvas>
元素作为图片源ImageBitmap
高性能位图,可以低延迟的绘制。,它可以从上述的所有源以及其它几种源中生成。
使用相同页面内的图片
获取当前页面的图片引用:
document.images
集合document.getElementsByTagName()
document.getElementById()
使用其他域名下的图片
如果图片允许跨域访问,可以正常渲染
canvas
,如果图片不允许跨域访问,会污染当前canvas
.使用其他 canvas 元素
获取 canvas 元素
document.getElementsByTagName()
document.getElementById()
由零开始创建图像
1
2
3
4
5var img=new Image();
img.onload=function(){
//执行drawImage语句
}
img.src='img.png'通过
data.url
方式嵌入图像1
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
使用视频帧
1
2
3
4
5
6
7
8function getMyVideo() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
return document.getElementById('myvideo');
}
}
绘制图片
drawImage(image,x,y)
image
就是用上面的方法获取的图片源,SVG 图像必须在<svg>
根指定元素的宽度和高度。x
,y
,绘制图片左上角在画布中的起始坐标
1
2
3
4
5
6
7
8
9
10
11
12
13function draw(ctx) {
let img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0);
ctx.beginPath();
ctx.moveTo(30, 96);
ctx.lineTo(70, 66);
ctx.lineTo(102, 76);
ctx.lineTo(170, 15);
ctx.stroke();
}
img.src = 'bird.jpg'
}drawImage(image,x,y,width,height)
;width
和height
用来控制当前canvas
画入时应该缩放的大小
1 | function draw(ctx) { |
drawImage(image,sx,sy,sWidth,sHeight,dx,dy,dWidth,dHeight)
第一个参数同上还是图片源,
后面 8 个参数,前四个参数定义图像源的切片位置和大小,后四个定义切片的目标显示的位置和大小。
1 | function draw(ctx) { |
渲染 frame
1 | // Draw frame |
- 控制图像的缩放行为
mozImageSmoothingEnabled
,默认为true
,为false
时图像不会平滑的缩放。ctx.mozImageSmoothingEnabled = false;
变形 Transformation
状态的保存和恢复
save()
保存画布的现在的状态restore()
恢复canvas
状态。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
1 | function draw(ctx) { |
移动
translate(x, y)
x
为左右偏移量,y
为上下偏移量
1 | function draw(ctx) { |
旋转
rotate(angle)
角度(angle)
是顺时针方向,以弧度为单位。
旋转的中心始终是canvas
的原点
缩放
scale(x,y)
x
为水平缩放,y
为垂直缩放x,y
都是实数,比 1 小会缩小图形,比 1 大会放大图片,默认为 1。
画布初始情况下, 是以左上角坐标为原点的第一象限。如果为负实数, scale(-1,1)
以y
轴作为对称轴镜像反转,scale(1,-1)
以x
轴作为对称轴镜像反转。
1 | function draw(ctx) { |
变形
transform(a,b,c,d,e,f)
这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵,如下面的矩阵所示:$\left[ \begin{array}{ccc} a & c & e \ b & d & f \ 0 & 0 & 1 \end{array} \right]$a(m11)
: 水平方向的缩放b(m12)
: 水平方向的倾斜偏移c(m21)
: 竖直方向的倾斜偏移d(m22)
: 竖直方向的缩放e(m31)
: 水平方向的移动f(m32)
: 竖直方向的移动
setTransform(a,b,c,d,e,f)
将当前的变形矩阵重置为单位矩阵,然后用相同的参数调用 transform 方法。该方法是取消了当前变形,然后设置为指定的变形,一步完成。resetTransform()
重置当前变形为单位矩阵,它和调用以下语句是一样的:ctx.setTransform(1, 0, 0, 1, 0, 0)
。
1 | function draw(ctx) { |
组合
globalCompositeOperation=type
设定新绘制图形与原图形的遮盖方式。
目标画布-已有,新图像
source-over
:默认,在现有画布上下文之上绘制新图形。source-in
:新图形只在新图形和目标画布重叠的地方绘制。其他的都是透明的。source-out
: 在不与现有画布内容重叠的地方绘制新图形,重叠部分是透明的。source-atop
: 新图形只在与现有画布内容重叠的地方绘制,原有画布非重叠部分不变。destination-over
: 在现有的画布内容后面绘制新的图形。destination-in
: 现有的画布内容保持在新图形和现有画布内容重叠的位置。其他的都是透明的。destination-out
:现有内容保持在新图形不重叠的地方,其他地方透明。destination-atop
:现有的画布只保留与新图形重叠的部分,新的图形是在画布内容后面绘制的。lighter
:两个重叠图形的颜色是通过颜色值相加来确定的。copy
:只显示新图形。xor
:图像中,那些重叠和正常绘制之外的其他地方是透明的。multiply
:将顶层像素与底层相应像素相乘,结果是一幅更黑暗的图片。screen
:像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。overlay
:multiply
和screen
的结合,原本暗的地方更暗,原本亮的地方更亮。darken
:保留两个图层中最暗的像素。lighten
:保留两个图层中最亮的像素。color-dodge
:将底层除以顶层的反置。color-burn
:将反置的底层除以顶层,然后将结果反过来。hard-light
:屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。soft-light
:用顶层减去底层或者相反来得到一个正值。difference
:一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。exclusion
:和 difference 相似,但对比度较低。
…
裁切路径
clip()
将当前正在构建的路径转换为当前的裁剪路径。
默认情况下,canvas 有一个与它自身一样大的裁切路径(也就是没有裁切效果)。
1 | function draw(ctx) { |