简介
canvas 是H5新增的一个用于图形绘制的标签 参考:Canvas - Web API 接口参考 | MDN (mozilla.org)
例子: 画一个矩形边框和一个填充的矩形
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Demo</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="my-canvas" width="600" height="600">
该浏览器版本不支持canvas标签
</canvas>
<script>
</script>
</body>
</html>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
// 画一个矩形边框
// 设置边框颜色
ctx.strokeStyle = 'red'
// 绘制一个矩形边框
ctx.strokeRect(50, 50, 100, 100)
// 画一个填充的矩形
ctx.fillStyle = 'green'
ctx.fillRect(150, 150, 100, 100)
效果:
注意: </canvas>不可缺省
绘制形状
canvas 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)
绘制矩形
canvas提供了三种方法绘制矩形
- fillRect(x, y, width, height):绘制一个填充的矩形
- strokeRect(x, y, width, height):绘制一个矩形的边框
- clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明。
绘制路径
绘制路径会用到一下方法
beginPath():新建一条路径closePath():闭合路径moveTo():设置起点lineTo():绘制直线stroke():通过线条来绘制图形轮廓。fill():通过填充路径的内容区域生成实心的图形
注意:当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。 例子:画一个三角形
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
ctx.beginPath()
ctx.moveTo(50, 50)
ctx.lineTo(100, 100)
ctx.lineTo(50, 150)
ctx.fill()
效果:
绘制圆弧
绘制圆弧会用到一下方法:
- arc(x, y, radius, startAngle, endAngle, anticlockwise) 画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。
- arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
例子:画一个圆
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
// 画一个圆
ctx.arc(100, 100, 50, 0, Math.PI * 2, false)
ctx.fill()
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为结束点。
例子:
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
ctx.moveTo(100, 100)
ctx.quadraticCurveTo(125, 50, 200, 75)
ctx.stroke()
效果:
样式和颜色
色彩
fillStyle = color设置图形的填充颜色。strokeStyle = color设置图形轮廓的颜色。globalAlpha = transparencyValue这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
线型
lineWidth = value设置线条宽度。lineCap = type设置线条末端样式,type取以下值:butt线段末端以方形结束,默认值round线段末端以圆形结束。square线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域
lineJoin = type设定线条与线条间接合处的样式,type取以下值:round通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。 圆角的半径是线段的宽度。bevel在相连部分的末端填充一个额外的以三角形为底的区域, 每个部分都有各自独立的矩形拐角。miter默认值,通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。这个设置可以通过 miterLimit 属性看到效果。
setLineDash(segments)设置当前虚线样式。
segments: 一个Array数组。一组描述交替绘制线段和间距(坐标空间单位)长度的数字。 如果数组元素的数量是奇数, 数组的元素会被复制并重复。例如, [5, 15, 25] 会变成 [5, 15, 25, 5, 15, 25]。lineDashOffset = value设置虚线样式的起始偏移量。- 例子:
效果:/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('my-canvas') // 上下文 const ctx = canvas.getContext('2d') let y = 20 function drawDashedLine(pattern) { ctx.beginPath() ctx.setLineDash(pattern) ctx.moveTo(0, y) ctx.lineTo(300, y) ctx.stroke() y += 20 } drawDashedLine([]) drawDashedLine([1, 1]) drawDashedLine([10, 10]) drawDashedLine([20, 5]) drawDashedLine([15, 3, 3, 3]) drawDashedLine([20, 3, 3, 3, 3, 3, 3, 3]) drawDashedLine([12, 3, 3]) // 等同于 [12, 3, 3, 12, 3, 3]
- 例子2: 虚线边框矩形
效果:/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('my-canvas') // 上下文 const ctx = canvas.getContext('2d') ctx.setLineDash([4, 2]) ctx.strokeRect(10, 10, 100, 100)
- 例子:
lineDashOffset = value设置虚线样式的起始偏移量。 例子:蚂蚁线效果:/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('my-canvas') // 上下文 const ctx = canvas.getContext('2d') var offset = 0 function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.setLineDash([4, 2]) ctx.lineDashOffset = -offset ctx.strokeRect(10, 10, 100, 100) } function march() { offset++ if (offset > 16) { offset = 0 } draw() } setInterval(() => { march() }, 20)
渐变
createLinearGradient(x1, y1, x2, y2):该方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)。 例子:/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('canvas') // 上下文 const ctx = canvas.getContext('2d') // 线性渐变 const linear = ctx.createLinearGradient(100, 100, 100, 300) linear.addColorStop(0, 'red') linear.addColorStop(0.2, 'orange') linear.addColorStop(0.4, 'yellow') linear.addColorStop(0.6, 'green') linear.addColorStop(0.8, 'blue') linear.addColorStop(1, 'purple') ctx.fillStyle = linear ctx.fillRect(100, 100, 200, 200)
createRadialGradient(x1, y1, r1, x2, y2, r2):方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。
图案样式
createPattern(image, type):该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y 和 no-repeat。 例子:/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('my-canvas') // 上下文 const ctx = canvas.getContext('2d') // 创建新 image 对象,用作图案 var img = new Image() img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png' img.onload = function () { // 创建图案 var ptrn = ctx.createPattern(img, 'repeat') ctx.fillStyle = ptrn ctx.fillRect(0, 0, 150, 150) }
阴影
-
shadowOffsetX = floatshadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。 -
shadowOffsetY = floatshadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。 -
shadowBlur = floatshadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。 -
shadowColor = colorshadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。例子:
/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('canvas') // 上下文 const ctx = canvas.getContext('2d') ctx.shadowOffsetX = 10 ctx.shadowOffsetY = 10 ctx.shadowBlur = 3 ctx.shadowColor = 'red' ctx.font = '30px 宋体' ctx.fillText('你好你好你好你好', 100, 100)
绘制文本
文本绘制
canvas 提供了两种方法来渲染文本:
-
fillText(text, x, y [, maxWidth])
在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的. -
strokeText(text, x, y [, maxWidth])
在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.例子:
/** @type {HTMLCanvasElement} */ const canvas = document.getElementById('my-canvas') // 上下文 const ctx = canvas.getContext('2d') ctx.font = '30px 宋体' ctx.fillText('你好你好你好', 100, 100) ctx.font = '30px 宋体' ctx.strokeText('你好你好你好', 100, 200)
文本的样式
font = value
当前我们用来绘制文本的样式. 这个字符串使用和 CSS font 属性相同的语法. 默认的字体是 10px sans-serif。
textAlign = value
文本对齐选项. 可选的值包括:start, end, left, right, center. 默认值是 start。
textBaseline = value
基线对齐选项. 可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。
direction = value
文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。
使用图像
绘制图像
- drawImage
void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Demo</title>
<style>
canvas {
border: 1px solid #ccc
}
</style>
</head>
<body>
<canvas id="my-canvas" width="300" height="300">
该浏览器版本不支持canvas标签
</canvas>
<img src="https://media.prod.mdn.mozit.cloud/attachments/2012/07/09/1456/941aaa8d98ead9a0d46aef80d02198f7/Canvas_sun.png" width="300" height="300" />
<script>
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
const image = new Image()
image.src = 'https://media.prod.mdn.mozit.cloud/attachments/2012/07/09/1456/941aaa8d98ead9a0d46aef80d02198f7/Canvas_sun.png'
image.onload = function() {
ctx.drawImage(image, 100, 100, 100, 100, 0, 0, 100, 100)
}
</script>
</body>
</html>
变形
状态的保存和恢复
save():保存画布(canvas)的所有状态restore():恢复画布状态
移动
translate(x, y): 该方法接受两个参数。x 是左右偏移量,y 是上下偏移量,如右图所示。
旋转
rotate(angle): 该方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
缩放
scale(x, y): 该方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比1小,会缩小图形, 如果比1大会放大图形。默认值为1, 为实际大小。
合成与裁剪
合成
globalCompositeOperation = type: 这个属性设定了在画新图形时采用的遮盖策略,其值是一个标识12种遮盖方式的字符串。
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'deeppink'
ctx.arc(100, 100, 50, 0, Math.PI * 2, false)
ctx.fill()
ctx.globalCompositeOperation = 'source-over'
ctx.fillStyle = 'blue'
ctx.fillRect(100, 100, 100, 100)
source-over: 默认值,如上destination-over
source-in
destination-in
source-out
destination-out
source-atop
destination-atop
lighter:两个重叠图形的颜色是通过颜色值相加来确定的。
copy:只显示新图形
xor:图像中,那些重叠和正常绘制之外的其他地方是透明的。
multiply:将顶层像素与底层相应像素相乘,结果是一幅更黑暗的图片。
screen:像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。
其他的参考:Compositing 示例 - Web API 接口参考 | MDN (mozilla.org)
裁剪路径
clip():将当前正在构建的路径转换为当前的裁剪路径。
/** @type {HTMLCanvasElement} */
const canvas = document.getElementById('my-canvas')
// 上下文
const ctx = canvas.getContext('2d')
ctx.arc(100, 100, 75, 0, Math.PI * 2, false)
ctx.clip()
ctx.fillRect(0, 0, 100, 100)