创建画布

在HTML页面中创建 canvas 标签,即可创建一个 canvas 画布:

  1. <canvas id="drawing" style="border:1px solid black;"></canvas>

canvas 节点可以设置一些样式属性,但宽度和高度的设置比较特殊。

在 JavaScript 脚本中获取画布对象,并使用画布对象的getContext()方法创建绘图上下文:

  1. var drawing = document.getElementById("drawing");
  2. if (drawing.getContext) {
  3. // 确定浏览器支持<canvas>标签
  4. var context = drawing.getContext("2d"); // 2d上下文
  5. }

导出图像

Canvas 画布上绘制的图像可以导出为 png 格式的图像,只需要使用画布对象的toDataURL(type)方法,type 参数是一个导出类型字符串,导出为 png 格式则取值”image/png”:

HTML:

  1. <canvas id="drawing" style="border:1px solid black;"></canvas>
  2. <img id="pngImg" style="border:1px solid black;" />

JavaScript:

  1. var drawing = document.getElementById("drawing");
  2. var pngImg = document.getElementById("pngImg");
  3. if (drawing.getContext) {
  4. // 确定浏览器支持<canvas>标签
  5. var context = drawing.getContext("2d");
  6. // 绘图
  7. ...
  8. pngImg.src = drawing.toDataURL("image/png"); // 将画布绘制的图像导出为png
  9. }

填充和描边

填充就是用指定的样式(颜色、渐变或图像)填充图像;描边则是只在图像边缘画线。设置填充样式需要设置上下文对象的 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),其接收参数与绘制矩形方法的参数相同。

  1. ...
  2. // 填充矩形
  3. context.fillStyle = "red";
  4. context.fillRect(10, 10, 50, 50); // 填充红色矩形
  5. context.fillStyle = "blue";
  6. context.fillRect(60, 10, 50, 50); // 填充蓝色矩形
  7. // 描边矩形
  8. context.lineWidth = 1; // 线条宽度设为1
  9. context.strokeStyle = "green";
  10. context.strokeRect(111, 11, 48, 48); // 描边绿色矩形
  11. context.strokeStyle = "yellow";
  12. context.strokeRect(161, 11, 48, 48); // 描边黄色矩形
  13. // 清除矩形
  14. context.clearRect(20, 20, 30, 30);
  15. ...

绘制路径

2D上下文支持很多种在画布上绘制路径的方法,通过路径可以创造出复杂的形状和线条。

开始路径使用语句:context.beginPath()

绘制路径的方法有以下这些:

  1. arc(x, y, radius, startAngle, endAngle, counterclockwise)
    绘制弧线,前两个参数(数值)用于设置中心点位置;第三个参数(数值)为弧线半径;startAngle 参数和 endAngle 参数分别设置起始和结束位置(用弧度表示);最后一个参数(布尔值)设置绘制方向是顺时钟还是逆时针,false 为顺时针(默认),true 为逆时针。

    1. ...
    2. context.beginPath();
    3. context.arc(100, 80, 50, 0, Math.PI / 2, true); // 以(100,80)为中心,半径为50,逆时针从0开始-90°结束画弧
    4. context.stroke();
    5. ...
  2. moveTo(x, y)
    将绘图游标移动到(x,y)。

  3. lineTo(x, y)
    从绘图游标位置为起点,(x,y)为终点画直线。

    1. ...
    2. context.moveTo(100, 80);
    3. context.lineTo(150, 80); // 以(100,80)为起点,(150,80)为终点画直线
    4. context.stroke();
    5. ...

    绘制完路径后,可以执行以下操作:

  4. 描边路径:context.stroke()

  5. 填充路径:context.fill()
  6. 闭合路径:context.closePath()

绘制文本

绘制文本有同样两种方式:填充和描边。填充文本用fillText(str, x, y),描边文本用strokeText(str, x, y),str 参数为文本内容,x和y参数为文本显示位置。这两个方法又基于3个属性:

  1. font:表示文本样式、大小、字体类型等,其取值与 CSS 的 font 属性取值相同;
  2. textAlign:文本对齐方式,取值有”start”、”end”和”center”等;
  3. textBaseline:文本基线,取值有”top”、”middle”、”bottom”等。
    1. ...
    2. context.font = "bold 50px Georgia"; // 50px字体大小,加粗,字体类型为Georgia
    3. context.textAlign = "center"; // 水平居中对齐
    4. context.textBaseline = "middle"; // 竖直居中对齐
    5. context.strokeText("20", 120, 70);
    6. context.fillText("17", 180, 70);
    7. ...

阴影

2D上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影:

  1. shadowColor:阴影颜色,取值与 CSS 颜色取值相同;
  2. shadowOffsetX:阴影水平偏移量,默认值为0;
  3. shadowOffsetY:阴影竖直偏移量,默认值为0;
  4. shadowBlur:模糊像素数,默认为0,即不模糊。
    1. ...
    2. context.shadowColor = "#3456c1";
    3. context.shadowOffsetX = 5;
    4. context.shadowOffsetY = 5;
    5. context.shadowBlur = 5;
    6. context.strokeRect(20, 20, 50, 50); // 绘制一个带浅蓝色阴影的正方形
    7. ...

渐变

渐变有两种:线性渐变和径向渐变,径向渐变难以控制,故只说明线性渐变的使用。

创建一个线性渐变,使用的是createLinearGradient(startX, startY, endX, endY)方法,它接收四个参数:startX 和 startY 参数用于获取渐变起点位置,endX 和 endY 参数用于获取渐变终点位置。使用这个方法后将返回一个渐变实例对象。

创建了渐变实例对象后,下一步就是使用addColorStop(num, color)方法指定色标,它接收两个参数:num 参数是一个数值,取值0或1,0表示起点,1表示终点;color 参数为颜色值,设置起点或终点色标。

将渐变应用到图像上只要将 fillStyle 或 strokeStyle 设置为渐变实例对象即可。

  1. ...
  2. var gradient = context.createLinearGradient(20, 20, 70, 70);
  3. gradient.addColorStop(0, "#00a4e9");
  4. gradient.addColorStop(1, "#3456c1");
  5. context.fillStyle = gradient;
  6. context.fillRect(20, 20, 50, 50); // 完全将由浅蓝到深蓝的渐变应用到矩形上
  7. ...

注意,如果想让渐变完全覆盖图像,应将createLinearGradient()前两个参数设为图像左上点坐标,后两个参数设为图像右下点坐标。

SVG

这一小节不是书中的内容,因为 SVG 和 Canvas 都是 HTML5 新增的内容,所以特别在本篇文章中记录这两者的内容,并比较两者的异同。

SVG 指可伸缩矢量图形(Scalable Vector Graphics),可用来定义用于网络的基于矢量的图形。SVG 使用 XML 格式定义图形,在放大或改变尺寸的情况下其图形质量不会有所损失,IE9 以及 Firefox 和 Chrome 都支持 SVG。

预定义形状元素

w1.pngw2.pngw3.pngw4.pngw5.png

绘制时钟实例

示例代码:

  1. <svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="560" height="560">
  2. <circle cx="280" cy="280" r="250" fill="#2795a5" opacity="0.75" stroke="#3456c1" stroke-width="5" />
  3. <circle cx="280" cy="280" r="15" fill="black" stroke="#3456c1" stroke-width="5" />
  4. <line x1="280" y1="280" x2="480" y2="280" stroke="black" stroke-width="10" />
  5. <line x1="280" y1="280" x2="280" y2="420" stroke="black" stroke-width="10" />
  6. <line x1="280" y1="280" x2="200" y2="200" stroke="black" stroke-width="10" />
  7. </svg>

效果图:
w6.png

Canvas与SVG的区别

Canvas 和 SVG 的主要区别是:使用 Canvas 绘制图形是通过调用其API,而 SVG 则是通过构建一棵 XML 元素树来实现的。

Canvas 的特点:

  1. 依赖分辨率;
  2. 不支持事件处理器;
  3. 弱的文本渲染能力;
  4. 能够以.png.jpg格式保存结果图像;
  5. 最适合图像密集型的游戏,其中的许多对象会被频繁重绘。

SVG 的特点:

  1. 不依赖分辨率;
  2. 支持事件处理器;
  3. 最适合带有大型渲染区域的应用程序(比如谷歌地图);
  4. 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快);
  5. 不适合游戏应用。