创建画布
在HTML页面中创建 canvas 标签,即可创建一个 canvas 画布:
<canvas id="drawing" style="border:1px solid black;"></canvas>
canvas 节点可以设置一些样式属性,但宽度和高度的设置比较特殊。
在 JavaScript 脚本中获取画布对象,并使用画布对象的getContext()
方法创建绘图上下文:
var drawing = document.getElementById("drawing");
if (drawing.getContext) {
// 确定浏览器支持<canvas>标签
var context = drawing.getContext("2d"); // 2d上下文
}
导出图像
Canvas 画布上绘制的图像可以导出为 png 格式的图像,只需要使用画布对象的toDataURL(type)方法,type 参数是一个导出类型字符串,导出为 png 格式则取值"image/png":
HTML:
<canvas id="drawing" style="border:1px solid black;"></canvas>
<img id="pngImg" style="border:1px solid black;" />
JavaScript:
var drawing = document.getElementById("drawing");
var pngImg = document.getElementById("pngImg");
if (drawing.getContext) {
// 确定浏览器支持<canvas>标签
var context = drawing.getContext("2d");
// 绘图
...
pngImg.src = drawing.toDataURL("image/png"); // 将画布绘制的图像导出为png
}
填充和描边
填充就是用指定的样式(颜色、渐变或图像)填充图像;描边则是只在图像边缘画线。设置填充样式需要设置上下文对象的 fillStyle 属性,设置描边样式则是设置 strokeStyle 属性,设置这两个属性值会覆盖原来的值。
设置描边线条宽度可以设置 lineWidth 属性,取值是任意整数。
绘制矩形
绘制矩形有两种形式,分别是填充矩形和描边矩形。
填充矩形先要设置填充属性 fillStyle,然后使用fillRect()
方法绘制矩形。fillRect(x, y, w, h)
接收的4个参数都是数值,参数x为相对画布左上点水平距离,参数y为竖直距离,参数w为宽度,参数h为高度。
描边矩形先设置描边属性 strokeStyle,然后使用strokeRect()
方法绘制矩形。strokeRect(x, y, w, h)
接收的4个参数同fillRect(x, y, w, h)
。
除了以上两个绘制矩形的方法,还可以使用清除矩形块方法clearRect(x, y, w, h)
,其接收参数与绘制矩形方法的参数相同。
...
// 填充矩形
context.fillStyle = "red";
context.fillRect(10, 10, 50, 50); // 填充红色矩形
context.fillStyle = "blue";
context.fillRect(60, 10, 50, 50); // 填充蓝色矩形
// 描边矩形
context.lineWidth = 1; // 线条宽度设为1
context.strokeStyle = "green";
context.strokeRect(111, 11, 48, 48); // 描边绿色矩形
context.strokeStyle = "yellow";
context.strokeRect(161, 11, 48, 48); // 描边黄色矩形
// 清除矩形
context.clearRect(20, 20, 30, 30);
...
绘制路径
2D上下文支持很多种在画布上绘制路径的方法,通过路径可以创造出复杂的形状和线条。
开始路径使用语句:context.beginPath()
绘制路径的方法有以下这些:
arc(x, y, radius, startAngle, endAngle, counterclockwise)
绘制弧线,前两个参数(数值)用于设置中心点位置;第三个参数(数值)为弧线半径;startAngle 参数和 endAngle 参数分别设置起始和结束位置(用弧度表示);最后一个参数(布尔值)设置绘制方向是顺时钟还是逆时针,false 为顺时针(默认),true 为逆时针。
...
context.beginPath();
context.arc(100, 80, 50, 0, Math.PI / 2, true); // 以(100,80)为中心,半径为50,逆时针从0开始-90°结束画弧
context.stroke();
...
moveTo(x, y)
将绘图游标移动到(x,y)。lineTo(x, y)
从绘图游标位置为起点,(x,y)为终点画直线。
...
context.moveTo(100, 80);
context.lineTo(150, 80); // 以(100,80)为起点,(150,80)为终点画直线
context.stroke();
...
绘制完路径后,可以执行以下操作:
- 描边路径:
context.stroke()
; - 填充路径:
context.fill()
; - 闭合路径:
context.closePath()
;
绘制文本
绘制文本有同样两种方式:填充和描边。填充文本用fillText(str, x, y),描边文本用strokeText(str, x, y),str 参数为文本内容,x和y参数为文本显示位置。这两个方法又基于3个属性:
- font:表示文本样式、大小、字体类型等,其取值与 CSS 的 font 属性取值相同;
- textAlign:文本对齐方式,取值有"start"、"end"和"center"等;
- textBaseline:文本基线,取值有"top"、“middle”、"bottom"等。
...
context.font = "bold 50px Georgia"; // 50px字体大小,加粗,字体类型为Georgia
context.textAlign = "center"; // 水平居中对齐
context.textBaseline = "middle"; // 竖直居中对齐
context.strokeText("20", 120, 70);
context.fillText("17", 180, 70);
...
阴影
2D上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影:
- shadowColor:阴影颜色,取值与 CSS 颜色取值相同;
- shadowOffsetX:阴影水平偏移量,默认值为0;
- shadowOffsetY:阴影竖直偏移量,默认值为0;
- shadowBlur:模糊像素数,默认为0,即不模糊。
...
context.shadowColor = "#3456c1";
context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 5;
context.strokeRect(20, 20, 50, 50); // 绘制一个带浅蓝色阴影的正方形
...
渐变
渐变有两种:线性渐变和径向渐变,径向渐变难以控制,故只说明线性渐变的使用。
创建一个线性渐变,使用的是createLinearGradient(startX, startY, endX, endY)
方法,它接收四个参数:startX 和 startY 参数用于获取渐变起点位置,endX 和 endY 参数用于获取渐变终点位置。使用这个方法后将返回一个渐变实例对象。
创建了渐变实例对象后,下一步就是使用addColorStop(num, color)
方法指定色标,它接收两个参数:num 参数是一个数值,取值0或1,0表示起点,1表示终点;color 参数为颜色值,设置起点或终点色标。
将渐变应用到图像上只要将 fillStyle 或 strokeStyle 设置为渐变实例对象即可。
...
var gradient = context.createLinearGradient(20, 20, 70, 70);
gradient.addColorStop(0, "#00a4e9");
gradient.addColorStop(1, "#3456c1");
context.fillStyle = gradient;
context.fillRect(20, 20, 50, 50); // 完全将由浅蓝到深蓝的渐变应用到矩形上
...
注意,如果想让渐变完全覆盖图像,应将createLinearGradient()
前两个参数设为图像左上点坐标,后两个参数设为图像右下点坐标。.
SVG
这一小节不是书中的内容,因为 SVG 和 Canvas 都是 HTML5 新增的内容,所以特别在本篇文章中记录这两者的内容,并比较两者的异同。
SVG 指可伸缩矢量图形(Scalable Vector Graphics),可用来定义用于网络的基于矢量的图形。SVG 使用 XML 格式定义图形,在放大或改变尺寸的情况下其图形质量不会有所损失,IE9 以及 Firefox 和 Chrome 都支持 SVG。
预定义形状元素
绘制时钟实例
示例代码:
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="560" height="560">
<circle cx="280" cy="280" r="250" fill="#2795a5" opacity="0.75" stroke="#3456c1" stroke-width="5" />
<circle cx="280" cy="280" r="15" fill="black" stroke="#3456c1" stroke-width="5" />
<line x1="280" y1="280" x2="480" y2="280" stroke="black" stroke-width="10" />
<line x1="280" y1="280" x2="280" y2="420" stroke="black" stroke-width="10" />
<line x1="280" y1="280" x2="200" y2="200" stroke="black" stroke-width="10" />
</svg>
效果图:
Canvas与SVG的区别
Canvas 和 SVG 的主要区别是:使用 Canvas 绘制图形是通过调用其API,而 SVG 则是通过构建一棵 XML 元素树来实现的。
Canvas 的特点:
- 依赖分辨率;
- 不支持事件处理器;
- 弱的文本渲染能力;
- 能够以.png或.jpg格式保存结果图像;
- 最适合图像密集型的游戏,其中的许多对象会被频繁重绘。
SVG 的特点:
- 不依赖分辨率;
- 支持事件处理器;
- 最适合带有大型渲染区域的应用程序(比如谷歌地图);
- 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快);
- 不适合游戏应用。