Canvas入门
文章目录
通过<canvas>
标签可以让我们使用JavaScript脚本绘制图形,制作照片,创建动画,甚至可以进行实时视频处理或渲染。
WebGL也使用<canvas>
元素在网页上绘制硬件加速的3D图形。
示例
1 | <canvas id="canvas"></canvas> |
1 | var canvas = document.getElementById('canvas'); |
基础信息
<canvas>
标签只是一个空白的画布,供JavaScript在上面进行绘画等操作。<canvas>
标签和其它DOM标签一样拥有标签属性用于定义标签的特性。<canvas>
标签常用属性有width
和height
,通过它设定画布的大小。如果不指定width
和height
则默认宽高是:300x150。
绘图步骤:
- 获取画布节点
- 获取渲染上下文和绘画功能
- 开始绘画
1 | var canvas = document.getElementById('canvasNode'); // 获取画布节点 |
<canvas>
画布是个栅格布局,起点(0,0)是左上角,向右是x轴,向下是y轴。所有元素的位置都相对于原点定位。
绘制图形
绘制矩形
canvas
只提供了矩形的绘制方法,其它图形绘制需要通过路径完成。
矩形的绘制有三个方法:
fillRect(x, y, width, height)
绘制一个填充的矩形strokeRect(x, y, width, height)
绘制一个矩形的边框clearRect(x, y, width, height)
清除指定矩形区域,让清除部分完全透明。
1 | var canvas = document.getElementById('canvas'); |
绘制路径
路径:通过连续的点集合形成的不同颜色和宽度的线段或曲线。将多个路径连接闭合可以形成完整的图形。
canvas
除了矩形其它图形都需要通过路径绘制。绘制路径的一般通过一下几步:
- 创建路径起始点
- 使用画图命令去画出路径
- 把路径封闭
- 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。
注意: 图形是通过不同路径组成的,不同的路径可能并不连续,这时你需要通过moveto
移动画笔位置。
路径绘制的方法有:
beginPath()
新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。通过函数指定绘制路径,在调用绘制函数前你也许需要通过
moveTo(x,y)
移动画笔到合适位置。closePath()
闭合路径之后图形绘制命令又重新指向到上下文中。就是闭合路径closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。
stroke()
通过线条来绘制图形轮廓。fill()
通过填充路径的内容区域生成实心的图形。
注意: 当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
绘制三角形
1 | function draw() { |
绘制直线
绘制一条从当前位置到指定x以及y位置的直线。
1 | function draw() { |
注意: 当一个路径绘制结束,如果需要再绘制路径需要再调用beginPath
。
绘制圆弧
绘制圆弧的方法有:arc()
和arcTo()
。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
- x 圆弧中心(圆心)的 x 轴坐标
- y 圆弧中心(圆心)的 y 轴坐标
- radius 圆弧的半径
- startAngle 圆弧的起始点, x轴方向开始计算,单位以弧度表示
- endAngle 圆弧的终点, 单位以弧度表示
- anticlockwise | 可选(Boolean) 如果为
true
,逆时针绘制圆弧,反之,顺时针绘制。 默认是顺时针
arcTo(x1, y1, x2, y2, radius)
根据控制点和半径绘制圆弧路径,使用当前的描点(前一个moveTo或lineTo等函数的止点)。根据当前描点与给定的控制点1连接的直线,和控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径。
注意 arc()
函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:弧度=(Math.PI/180)*角度 。
Math.PI = 3.1415936 = 180度
1 | function draw() { |
绘制曲线
通过贝塞尔曲线用于绘制曲线,canvas
提供了二次贝塞尔曲线和三次贝塞尔曲线的绘制方法。
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() { |
绘制三次贝塞尔曲线
1 | function draw() { |
填充样式和颜色
Colors
canvas
对颜色的处理有两种:
fillStyle = color
设置图形的填充颜色strokeStyle = color
设置图形轮廓的颜色。
color
可以是表示 CSS 颜色值的字符串,渐变对象或者图案对象。我们迟些再回头探讨渐变和图案对象。默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000
)
1 | // 这些 fillStyle 的值均为 '橙色' |
透明度 Transparency
通过设置 globalAlpha
属性或者使用一个半透明颜色作为轮廓或填充的样式。
globalAlpha = transparencyValue
这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
透明功能也可以使用strokeStyle
和 fillStyle
属性完成。
1 | // 指定透明颜色,用于描边和填充样式 |
线型 Line styles
lineWidth = value
设置线条宽度
1 | function draw() { |
lineCap = type
设定线条与线条间接合处的样式
1 | function draw() { |
miterLimit = value
限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。lineJoin
的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:round
, bevel
和 miter。
默认是 miter
。
1 | function draw() { |
getLineDash()
返回一个包含当前虚线样式,长度为非负偶数的数组
setLineDash(segments)
设置当前虚线样式
1 | var canvas = document.getElementById("canvas"); |
lineDashOffset = value
设置虚线样式的起始偏移量
渐变 Gradients
canvas
中绘制渐变图形分为四个步骤:
- 创建处理渐变的对象,这个对象定义了渐变位置范围(createLinearGradient、createRadialGradient)。
- 设置渐变颜色和渐变速率(
addColorStop
)。 - 将渐变对象赋予
fillStyle
或strokeStyle
。 - 绘制图形
1 | var canvas = document.getElementById("canvas"); |
阴影 Shadows
canvas
中可以给图形或文字设置阴影。需要使用的方法有:
shadowOffsetX 和 shadowOffsetY
用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0
。
shadowBlur = float
shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为0
。注意:将shadowColor属性设置成不透明,阴影才会被绘制。shadowColor = color
shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
1 | var canvas = document.getElementById("canvas"); |
图案样式 Patterns
canvas
图形处理可以填充颜色。渐变色,还可以填充图案,借用方法createPattern
。
1 | function draw() { |
注意: 与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。
Canvas填充
canvas
中填充方法是fill
。fill
可以结合clip
设置路径的截取部分填充。例如:
1 | var canvas = document.getElementById("canvas"); |
fill
可以设置填充规则:
- 非零环绕原则
nonzero
默认 - 奇偶原则
evenodd
非零环绕原则 nonzero
是用来判断哪些区域属于路径内( 计算结果非0,即为路径内 )。
- 在路径包围的区域中,随便找一点,向外发射一条射线,
- 和所有围绕它的边相交,
- 然后开启一个计数器,从0计数,
- 如果这个射线遇到顺时针围绕,那么+1,
- 如果遇到逆时针围绕,那么-1,
- 如果最终值非0,则这块区域在路径内。
奇偶原则 evenodd
- 在路径包围的区域中,随便找一点,向外发射一条射线,
- 和所有围绕它的边相交,
- 查看相交线的个数,如果为奇数,就填充,如果是偶数,就不填充。(0是偶数)
1 | function draw() { |
上图吐槽部分是两个圆间隙部分,因为只有这部分的点向四周放射直线和路径交集次数是奇数。
作者: Fynn
链接: https://fynn90.github.io/2018/11/09/Canvas%E5%85%A5%E9%97%A8/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可