第 15 章 使用 Canvas 绘图

94 阅读6分钟

HTML5 添加的最受欢迎的功能就是<canvas>元素。这个元素负责在页面中设定一个区域,然后就可以通过JavaScript 动态地在这个区域中绘制图形。

15.1 基本用法

要使用<canvas>元素,必须先设置其 width 和 height 属性,指定可以绘图的区域大小。

<canvas id="drawing" width=" 200" height="200">A drawing of something.</canvas>

与其他元素一样,<canvas>元素对应的 DOM 元素对象也有 width 和 height 属性

要在这块画布(canvas)上绘图,需要取得绘图上下文。需要调用getContext()方法并传入上下文的名字。传入"2d",就可以取得 2D 上下文对象。

var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    //更多代码
}

使用 toDataURL()方法,可以导出在<canvas>元素上绘制的图像。这个方法接受一个参数,即图像的 MIME 类型格式,而且适合用于创建图像的任何上下文

    var drawing = document.getElementById("drawing");
    //确定浏览器支持<canvas>元素
    if (drawing.getContext){
    //取得图像的数据 URI
    var imgURI = drawing.toDataURL("image/png");
    //显示图像
    var image = document.createElement("img");
    image.src = imgURI;
    document.body.appendChild(image);
}

15.2 2D 上下文

使用 2D 绘图上下文提供的方法,可以绘制简单的 2D 图形,比如矩形、弧线和路径。2D 上下文的坐标开始于<canvas>元素的左上角,原点坐标是(0,0)。x 值越大表示越靠右,y 值越大表示越靠下。

15.2.1 填充和描边

填充,就是用指定的样式(颜色、渐变或图像)填充图形;描边,就是只在图形的边缘画线。它们的结果结果取决于两个属性:fillStyle 和 strokeStyle。

var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    context.strokeStyle = "red";
    context.fillStyle = "#0000ff";
}

15.2.2 绘制矩形

矩形是唯一一种可以直接在 2D 上下文中绘制的形状。与矩形有关的方法包括 fillRect()、strokeRect()和 clearRect()。。这三个方法都能接收 4 个参数:矩形的 x 坐标、矩形的 y 坐标、矩形宽度和矩形高度。

fillRect()画实心填充矩形

var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    //绘制红色矩形
    context.fillStyle = "#ff0000";
    context.fillRect(10, 10, 50, 50);
    //绘制半透明的蓝色矩形
    context.fillStyle = "rgba(0,0,255,0.5)";
    context.fillRect(30, 30, 50, 50);
}

strokeRect()画空心矩形

var drawing = document.getElementById("drawing");

//确定浏览器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");

    //绘制红色描边矩形
    context.strokeStyle = "#ff0000";
    context.strokeRect(10, 10, 50, 50);

    //绘制半透明的蓝色描边矩形
    context.strokeStyle = "rgba(0,0,255,0.5)";
    context.strokeRect(30, 30, 50, 50);
}

clearRect()方法用于清除画布上的矩形区域

15.2.3 绘制路径

要绘制路径,首先必须调用 beginPath()方法,表示要开始绘制新路径。然后,再通过调用下列方法来实际地绘制路径。

  • arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)为圆心绘制一条弧线,弧线半径为 radius,起始和结束角度(用弧度表示)分别为 startAngle 和endAngle。最后一个参数表示 startAngle 和 endAngle 是否按逆时针方向计算,值为 false表示按顺时针方向计算。

  • arcTo(x1, y1, x2, y2, radius):从上一点开始绘制一条弧线,到(x2,y2)为止,并且以给定的半径 radius 穿过(x1,y1)。

  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点开始绘制一条曲线,到(x,y)为止,并且以(c1x,c1y)和(c2x,c2y)为控制点。

  • lineTo(x, y):从上一点开始绘制一条直线,到(x,y)为止。

  • moveTo(x, y):将绘图游标移动到(x,y),不画线。

  • quadraticCurveTo(cx, cy, x, y):从上一点开始绘制一条二次曲线,到(x,y)为止,并且以(cx,cy)作为控制点。

  • rect(x, y, width, height):从点(x,y)开始绘制一个矩形,宽度和高度分别由 width 和height 指定。这个方法绘制的是矩形路径,而不是 strokeRect()和 fillRect()所绘制的独立的形状。

15.2.4 绘制文本

2D 绘图上下文也提供了绘制文本的方法。绘制文本主要有两个方法:fillText()和 strokeText()。fillText()方法使用fillStyle 属性绘制文本,而 strokeText()方法使用 strokeStyle 属性为文本描边。

15.2.5 变换

可以通过如下方法来修改变换矩阵。

  • rotate(angle):围绕原点旋转图像 angle 弧度。
  • scale(scaleX, scaleY):缩放图像,在 x 方向乘以 scaleX,在 y 方向乘以 scaleY。scaleX和 scaleY 的默认值都是 1.0。
  • translate(x, y):将坐标原点移动到(x,y)。执行这个变换之后,坐标(0,0)会变成之前由(x,y)表示的点。
  • transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改变换矩阵,方式是乘以如下矩阵。
  • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将变换矩阵重置为默认状态,然后再调用 transform()。

15.2.6 绘制图像

把一幅图像绘制到画布上,可以使用 drawImage()方法。

var image = document.images[0];
context.drawImage(image, 10, 10);

15.2.7 阴影

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

  • shadowColor:用 CSS 颜色格式表示的阴影颜色,默认为黑色。
  • shadowOffsetX:形状或路径 x 轴方向的阴影偏移量,默认为 0。
  • shadowOffsetY:形状或路径 y 轴方向的阴影偏移量,默认为 0。
  • shadowBlur:模糊的像素数,默认 0,即不模糊。

15.2.8 渐变

渐变由 CanvasGradient 实例表示,很容易通过 2D 上下文来创建和修改。创建了渐变对象后,下一步就是使用 addColorStop()方法来指定色标。

var gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");

15.2.9 模式

模式其实就是重复的图像,可以用来填充或描边图形。要创建一个新模式,可以调用createPattern()方法。

var image = document.images[0],
pattern = context.createPattern(image, "repeat");

//绘制矩形
context.fillStyle = pattern;
context.fillRect(10, 10, 150, 150);

15.2.10 使用图像数据

2D 上下文的一个明显的长处就是,可以通过 getImageData()取得原始图像数据。这个方法接收4 个参数:要取得其数据的画面区域的 x 和 y 坐标以及该区域的像素宽度和高度。

var imageData = context.getImageData(10, 5, 50, 50);

15.2.11 合成

还有两个会应用到 2D 上下文中所有绘制操作的属性:globalAlpha 和 globalCompositionOperation。

//绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//修改全局透明度
context.globalAlpha = 0.5;
//绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
//重置全局透明度
context.globalAlpha = 0;

15.3 WebGL

WebGL 是针对 Canvas 的 3D 上下文。与其他 Web 技术不同,WebGL 并不是 W3C 制定的标准,而是由 Khronos Group 制定的。

15.3.1 类型化数组

WebGL 引入了一个概念,叫类型化数组(typed arrays)。类型化数组也是数组,只不过其元素被设置为特定类型的值。

类型化数组的核心就是一个名为 ArrayBuffer 的类型

15.3.2 WebGL上下文

WebGL 的名字叫"experimental-webgl"

var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext){
    var gl = drawing.getContext("experimental-webgl");
    if (gl){
        //使用 WebGL
    }
}

一般都把WebGL上下文对象命名为gl。大多数WebGL应用和示例都遵守这一约定,因为 OpenGL ES 2.0 规定的方法和值通常都以"gl"开头。