canvas元素本身很简单,只有两个属性width和height来指定元素在屏幕上的大小。canvas元素里包裹的内容会在浏览器不支持canvas元素时作为备用内容展示。canvas所有的功能都体现在JavaScript对象上。
获取画布上下文
为了在canva元素上绘图,需要获得一个画布的上下文对象,这个对象会开放针对特定图形样式的绘图函数,通过在DOM里代表canvas元素的对象HTMLCanvasElement获得上下文,该对象有一个方法是getContext(context)为画布返回绘图的上下文。
绘制矩形
简单的图形方法:
clearRect(x, y, w, h): 清除指定的矩形,return void
fillRect(x, y, w, h): 绘制实心矩形,return void
strokeRect(x, y, w, h): 绘制空心矩形, return void
(x, y): 是从canvas元素左上角算起的偏移量
w, h: 是指定了待绘制矩形的宽和高
示例代码:
html:
<canvas id="rect-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const RectCanvas = document.getElementById('rect-canvas').getContext('2d')
const offset = 10
const size = 50
const count = 5
for (let i = 0; i < count; i++) {
RectCanvas.fillRect(i * (offset + size) + offset, offset, size, size)
RectCanvas.strokeRect(i * (offset + size) + offset, (2 * offset) + size, size, size)
RectCanvas.clearRect(i * (offset + size) + offset, offset + 5, size, size - 10)
}
效果:
设置画布绘制状态
绘图操作由绘制状态配置。
基本的绘制状态属性:
fillStyle: 获取或设置用于实心图形的样式
lineJoin: 获取或设置线条与图形连接时的样式
lineWidth: 获取或设置线条的宽度
strokeStyle: 获取或设置用于线条的样式
示例代码:
html:
<canvas id="drawing-state-canvas" width="350" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const DrawingStateCanvas = document.getElementById('drawing-state-canvas').getContext('2d')
const offset = 10
const size = 50
const count = 5
const lineTypes = ['round', 'bevel', 'miter']
const fillColors = ['black', 'grey', 'lightgrey', 'red', 'blue']
const strokeColors = ['rgb(0, 0, 0)', 'rgb(100, 100, 100)', 'rgb(200, 200, 200)',
'rgb(255, 0, 0)', 'rgb(0, 0, 255)']
for (let i = 0; i < count; i++) {
DrawingStateCanvas.lineWidth = i * 2 // 线条宽度
DrawingStateCanvas.lineJoin = lineTypes[i % 3] // 线条或图形连接时的样式
DrawingStateCanvas.fillStyle = fillColors[i] // 实心图形的样式
DrawingStateCanvas.strokeStyle = strokeColors[i] // 线条样式
DrawingStateCanvas.fillRect(i * (offset + size) + offset, offset, size, size)
DrawingStateCanvas.strokeRect(i * (offset + size) + offset, (2 * offset) + size, size, size)
}
效果:
使用渐变
除了纯色还可以把填充和笔触样式设置成渐变色,渐变是两种或更多颜色之间的渐进转变。canvas元素支持两类渐变:线性和径向。
渐变方法:
createLinearGradient(x0, y0, x1, y1): 创建线性渐变,return CanvasGradient。(x0, y0):开始坐标,(x1, y1):结束坐标
createRadialGradient(x0, y0, r0, x1, y1, r1): 创建径向渐变,return CanvasGradient。(x0, y0):起点圆的圆心坐标,r0:起点圆的半径,(x1, y1):终点圆的圆心半径,r1:终点圆的半径
CanvasGradient对象方法:
addColorStop(position, color): 给渐变的梯度线添加一种纯色,return void。position:在线段上应用颜色的位置,线段的起点由0表示,终点用1表示;color:线段上应用的颜色。
`
线性渐变
线性渐变指的是沿着一条线设定要用的若干颜色。我们在定义梯度线时要相对于画布进行设置,而不是绘制的图形。
示例代码:
html:
<canvas id="linear-gradient-canvas" width="350" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const linearGradientCanvas = document.getElementById('linear-gradient-canvas').getContext('2d')
const grad = linearGradientCanvas.createLinearGradient(0, 0, 350, 140) // 相对于画布
grad.addColorStop(0, 'red')
grad.addColorStop(0.5, 'white')
grad.addColorStop(1, 'black')
linearGradientCanvas.fillStyle = grad
linearGradientCanvas.fillRect(0, 0, 350, 140) // 相对于画布
效果:
径向渐变
用两个圆定义径向渐变,渐变的起点由第一个圆定义,终点则是第二个圆,在两者之间添加颜色点。给渐变添加颜色时,他们会被放置在起点圆边界(改点的值为0.0)和终点圆的边界(改点的值为1.0)之间的一条线上。当你设定的一个圆与另一个不存在包含关系时要小心,各种浏览器对于如何开始渐变存在不一致性,结果也很混乱。
示例代码:
html:
<canvas id="radial-gradient-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const radialGradientCanvas = document.getElementById('radial-gradient-canvas').getContext('2d')
const grad = radialGradientCanvas.createRadialGradient(200, 70, 20, 200, 70, 100)
grad.addColorStop(0, 'red')
grad.addColorStop(0.5, 'white')
grad.addColorStop(1, 'black')
radialGradientCanvas.fillStyle = grad // fillStyle
radialGradientCanvas.fillRect(0, 0, 250, 140)
radialGradientCanvas.lineWidth = 100
radialGradientCanvas.strokeStyle = grad // strokeStyle
radialGradientCanvas.strokeRect(301, 0, 150, 140)
效果:
使用图案
除了纯色和渐变之外,还可以创建图案。使用画布上下文对象所定义的createPattern方法。2D绘图上下文定义了三种图案类型支持:图像、视频和画布。
createPattern(patternObj, type): patternObj为图案对象;type为重复样式,repeat为图像被垂直和水平重复;repeat-x为图像被水平重复;repeat-y为图像被垂直重复;no-repeat为图像不应当被重复
示例代码:
html:
<canvas id="pattern-gradient-canvas" width="500" height="200">
Your browser doesn't support the canvas
element.
</canvas>
<img id="pattern-img" src="../assets/logo.png" hidden/>
js:
const patternGradientCanvas = document.getElementById('pattern-gradient-canvas').getContext('2d')
const imageElem = document.getElementById('pattern-img')
const pattern = patternGradientCanvas.createPattern(imageElem, 'repeat')
patternGradientCanvas.fillStyle = pattern // fillStyle
patternGradientCanvas.fillRect(0, 0, 250, 200)
patternGradientCanvas.lineWidth = 20
patternGradientCanvas.strokeStyle = pattern // strokeStyle
patternGradientCanvas.strokeRect(270, 30, 200, 100)
效果:
图案复制的是img元素的当前状态,当用JavaScript和DOM修改了img元素的src属性的时候,此图案不会改变。
保存和恢复绘制状态
绘制状态保存时会被存放在一个后进先出的栈中,就是当我们用sava方法最后保存的状态会被restore方法首先进行恢复。画布里面的内容不会被保存或恢复,只有绘制状态的属性值才会。
save(): 保存绘制状态属性的值,并把它们推入状态栈
restore(): 取出状态栈的第一组值,用它们来设置绘制状态
绘制图像
使用drawImage方法在画布上绘制图像,图像来源可以是img,video或其他canvas元素的DOM对象。
使用img
drawImage(source, x0, y0, w0, h0, x1, y1, w1, h1)
source:图像的来源
(x0, y0):在源图像内的偏移量
(w0, h0):源图像所需使用区域的宽度和高度
(x1, y1):指定了所选区域的左上角将要在画布上绘制的坐标
(w1, h1):指定了所选区域将要绘制的宽度和高度
此方法可以有三个、五个或九个参数
示例代码:
html:
<canvas id="draw-image-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
<img id="draw-image-img" src="../assets/logo.png" hidden/>
js:
const DrawImageCanvas = document.getElementById('draw-image-canvas').getContext('2d')
const imageElement = document.getElementById('draw-image-img')
DrawImageCanvas.drawImage(imageElement, 0, 0)
DrawImageCanvas.drawImage(imageElement, 220, 0, 100, 100)
DrawImageCanvas.drawImage(imageElement, 50, 50, 100, 100, 350, 10, 100, 100)
效果:
使用video
可以用video元素作为drawImage方法的图像来源。观看各种HTML5演示时,经常会见到canvas被用来在视频上绘图。
使用画布图像
可以将一张画布的内容作为另一张里drawImage方法的图像来源。
用路径绘图
用路径绘制图形,路径本质上是一组独立的线条(被称为子路径),他们组合到一起构成图形。画布上的每一条子路径都以上一条的终点作为起点。
基本路径方法:
beginPath(): 开始一条新路径,return void
closePath(): 尝试闭合现有路径,方法是绘制一条线,连接最后那条线的终点与起始坐标,return void
fill(): 填充用子路径描述的图形,return void
isPointInPath(x, y): 如果指定的点在当前路径所描述的图形之内则返回true,return Boolean
lineTo(x, y): 绘制一条到指定坐标的子路径,return void
moveTo(x, y): 移动到指定坐标而不绘制子路径,return void
rect(x, y, w, h): 绘制一个矩形,其左上角位于(x, y),宽度是我,高度是h,return void
stroke(): 给子路径描述的图形绘制轮廓线,return void
绘制一条路径的基本顺序:
1. 调用beginPath方法
2. 用moveTo方法移动到起点
3. 用arc和lineTo等方法绘制子路径
4. 调用closePath方法(可选)
5. 调用fill或stoke方法
lineCap: 属性设置线条末端样式,选项:butt(默认),round,square
示例代码:
html:
<canvas id="path-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const PathCanvas = document.getElementById('path-canvas').getContext('2d')
PathCanvas.fillStyle = 'yellow'
PathCanvas.strokeStyle = 'black'
PathCanvas.lineWidth = 8
PathCanvas.lineCap = 'round' // 线条末端样式
// 用线条绘制路径
PathCanvas.beginPath()
PathCanvas.moveTo(10, 10)
PathCanvas.lineTo(100, 10)
PathCanvas.lineTo(100, 120)
PathCanvas.closePath()
PathCanvas.fill()
PathCanvas.stroke()
// 用线条绘制矩形
PathCanvas.beginPath()
PathCanvas.moveTo(220, 10)
PathCanvas.lineTo(220, 100)
PathCanvas.lineTo(120, 10)
PathCanvas.closePath()
PathCanvas.rect(230, 10, 210, 90)
PathCanvas.rect(250, 100, 240, 30)
PathCanvas.fill()
PathCanvas.stroke()
效果:
绘制圆弧
使用arc和arcTo方法在画布上绘制圆弧。
圆弧方法:
arc(x, y, rad, startAngle, endAngle, direction): 绘制一段圆弧到(x, y),半径为rad,其实角度为startAngle,结束角度为endAngle。direction为可选参数指定圆弧方向是按顺时针(false)还是逆时针(true),return void
arcTo(x1, y1, x2, y2): 绘制一段半径为rad,经过(x1, y1),直到(x2, y2)的圆弧,return void
使用arcTo方法
示例代码:
html:
<canvas id="arcTo-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const ArcToCanvas = document.getElementById('arcTo-canvas').getContext('2d')
const point1 = [100, 10]
const point2 = [200, 10]
const point3 = [200, 110]
ArcToCanvas.fillStyle = 'yellow'
ArcToCanvas.strokeStyle = 'black'
ArcToCanvas.lineWidth = 4
// 画圆弧
ArcToCanvas.beginPath()
ArcToCanvas.moveTo(point1[0], point1[1])
ArcToCanvas.arcTo(point2[0], point2[1], point3[0], point3[1], 100)
ArcToCanvas.stroke()
// 画辅助点
drawPoint(point1[0], point1[1])
drawPoint(point2[0], point2[1])
drawPoint(point3[0], point3[1])
// 画辅助线
ArcToCanvas.beginPath()
ArcToCanvas.moveTo(point1[0], point1[1])
ArcToCanvas.lineTo(point2[0], point2[1])
ArcToCanvas.lineTo(point3[0], point3[1])
ArcToCanvas.stroke()
function drawPoint (x, y) {
ArcToCanvas.lineWidth = 1
ArcToCanvas.strokeStyle = 'red'
ArcToCanvas.strokeRect(x - 2, y - 2, 4, 4)
}
效果:
使用arc方法
示例代码:
html:
<canvas id="arc-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const ArcCanvas = document.getElementById('arc-canvas').getContext('2d')
ArcCanvas.fillStyle = 'yellow'
ArcCanvas.lineWidth = 3
// 画圆弧一
ArcCanvas.beginPath()
ArcCanvas.arc(70, 70, 60, 0, Math.PI * 2, true)
ArcCanvas.stroke()
// 画圆弧二
ArcCanvas.beginPath()
ArcCanvas.arc(200, 70, 60, Math.PI / 3, Math.PI, true)
ArcCanvas.fill()
ArcCanvas.stroke()
// 圆弧三
ArcCanvas.beginPath()
let val = 0
for (let i = 0; i < 4; i++) {
ArcCanvas.arc(350, 70, 60, val, val + Math.PI / 4, false)
val += Math.PI / 2
}
ArcCanvas.closePath()
ArcCanvas.fill()
ArcCanvas.stroke()
效果:
绘制贝塞尔线
canvas支持绘制两种贝塞尔曲线:三次和两次
曲线方法:
bezierCurveTo(cx1, cy1, cx2, cy2, x, y): 绘制一段贝塞尔曲线到点(x, y),控制点为(cx1, cy1)和(cx2, cy2),return void
quadraticCurveTo(cx, cy, x, y): 绘制一段二次贝塞尔曲线到点(x, y),控制点为(cx, cy)
创建剪辑区域
以上说到用stroke和fill方法来绘制或填充一条路径,还一种方法用clip裁剪方法也可以做到。一旦定义一块裁剪区域,就只有区域内的路径才会显示到屏幕上。
clip(): 创建新的裁剪区域,return void
示例代码:
html:
<canvas id="clip-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const ClipCanvas = document.getElementById('clip-canvas').getContext('2d')
// 绘制一个填满画布的矩形
ClipCanvas.fillStyle = 'yellow'
ClipCanvas.beginPath()
ClipCanvas.rect(0, 0, 500, 140)
ClipCanvas.fill()
// 绘制裁剪区域
ClipCanvas.beginPath()
ClipCanvas.rect(100, 20, 300, 100)
ClipCanvas.clip()
// 绘制一个填满画布的矩形
ClipCanvas.fillStyle = 'red'
ClipCanvas.beginPath()
ClipCanvas.rect(0, 0, 500, 140)
ClipCanvas.fill()
效果:
绘制文本
可以在画布上绘制文本,不过对这种功能支持的还很初步。
绘制文本方法:
fillText(text, x, y, width): 在位置(x, y)上绘制并填充指定文本。宽度参数可选,它设置了文本宽度的上限。return void
strokeText(text, x, y, width): 在位置(x, y)上绘制并描边指定的文本,它设置了文本宽度的上限。return void
文本绘制方式的绘制状态属性:
font: 设置绘制文本时使用的字体
textAlign: 设置文本的对齐方式:start,end,right,center
textBaseLine: 设置文本的基线:top,hanging,middle,alphabetic,ideographic,bottom
示例代码:
html:
<canvas id="font-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const FontCanvas = document.getElementById('font-canvas').getContext('2d')
FontCanvas.fillStyle = 'lightgrey'
FontCanvas.strokeStyle = 'black'
FontCanvas.lineWidth = 3
FontCanvas.font = '80px sans-serif'
FontCanvas.fillText('Hello', 20, 100) // fillText
FontCanvas.strokeText('Hello', 270, 100) // strokeText
效果:
使用特效和变换
使用阴影
添加阴影的四种绘制状态属性:
shadowBlur: 设置阴影的模糊程度
shadowColor: 设置阴影的颜色
shadowOffsetX: 设置阴影的水平偏移量
shadowOffsetY: 设置阴影的垂直偏移量
使用透明度
使用绘制状态属性globalAlpha设置全局性透明度,属性值可以从0(完全透明)到1(完全不透明,这是默认值)。
使用合成
使用状态属性globalCompositeOpetation来控制图形和文字在画布上绘制的方式。globalCompositeOpetation允许的值自省去网上搜索,在这儿就不一一列举。有些浏览器对globalCompositeOpetation设置的值的解释样式会有些不同,可自行测试。
使用变换
变换的属性:
scale(xScale, yScale): 沿X轴缩放画布xScale倍,沿Y轴缩放yScale倍
rotate(angle): 使画布围绕点(0, 0)顺时针旋转指定的弧度数
translate(x, y): 重映射画布坐标为沿X轴x,沿Y轴y
transform(a, b, c, d, e, f): 合并现有的变换和a-f值所指定的矩阵
setTransform(a, b, c, d, e, f): 用a-f值所指定的矩阵替换现有的变换
测试代码:
html:
<canvas id="effects-canvas" width="500" height="140">
Your browser doesn't support the canvas
element.
</canvas>
js:
const EffectsCanvas = document.getElementById('effects-canvas').getContext('2d')
EffectsCanvas.fillStyle = 'lightgrey'
EffectsCanvas.strokeStyle = 'black'
EffectsCanvas.lineWidth = 3
EffectsCanvas.shadowOffsetX = 5 // 阴影水平偏移量
EffectsCanvas.shadowOffsetY = 5 // 阴影垂直偏移量
EffectsCanvas.shadowBlur = 5 // 阴影模糊程度
EffectsCanvas.shadowColor = 'grey' // 阴影的颜色
// 设置文字
EffectsCanvas.font = '90px sans-serif'
EffectsCanvas.fillText('Hello', 10, 100)
EffectsCanvas.strokeText('Hello', 10, 100)
// 设置矩形
EffectsCanvas.strokeRect(250, 20, 100, 100)
// 设置圆弧
EffectsCanvas.beginPath()
EffectsCanvas.arc(420, 70, 50, 0, Math.PI, true)
EffectsCanvas.stroke()
EffectsCanvas.beginPath()
EffectsCanvas.arc(420, 80, 40, 0, Math.PI, false)
EffectsCanvas.fill()
EffectsCanvas.globalCompositeOperation = 'destination-out' // 使用合成
EffectsCanvas.fillStyle = 'red'
EffectsCanvas.globalAlpha = 0.5 // 使用透明度
EffectsCanvas.fillRect(80, 20, 65, 100)
// 使用变换
EffectsCanvas.scale(0.9, 0.9)
EffectsCanvas.translate(50, -103)
EffectsCanvas.rotate(0.3)
EffectsCanvas.globalCompositeOperation = 'source-over' // 使用合成
EffectsCanvas.fillStyle = 'green'
EffectsCanvas.globalAlpha = 0.5 // 使用透明度
EffectsCanvas.fillRect(300, 10, 160, 120)
效果:
参考资料:《HTML5权威指南》: http://www.ituring.com.cn/boo...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。