Canvas 图形
创建 元素时至少要设置 width 和 height 属性。
<canvas id="xkcCanvas" width="700" height="700">小卡车 CANVAS</canvas>
注意:如果发现在编写 canvas 的时候,发现没有 API 提示的话,需要在 JavaScript 代码之前写下以下代码即可。
/** @type {HTMLCanvasElement}*/
基本画布功能
在画布上绘制图形,首先要先取得绘图上下文。使用 getContext()
方法可以获得对绘图上下文的引用。需要给这个方法传入参数 “2d”,表示获取 2D 上下文对象
let xkcCanvas = document.getElementById("xkcCanvas");
if (xkcCanvas.getContext) {
let context = xkcCanvas.getContext("2d");
}
使用 toDataURL()
方法导出 元素上的图像。接收一个参数:要生成图像的 MIME 类型。
let imgURI = xkcCanvas.toDataURL("image/png");
2D 绘图上下文
填充和描边
2D 上下文有两个基本绘制操作:填充和描边。填充以指定样式(颜色、渐变、图像)自动填充形状,而描边只为图形边界着色。显示效果取决于两个属性:fillStyle
和 strokeStyle
。
两个属性可以是字符串、渐变对象或图案对象。
context.strokeStyle = "blue";
context.fillStyle = "#00ff00";
绘制矩形
2D 绘图上下文可以绘制的形状只有矩形。与绘制矩形相关的方法有 3 个:fillRect()
、strokeRect()
和 clearRect()
。都接收 4 个参数:矩形 x 坐标、矩形 y 坐标、矩形宽度和矩形高度。
-
fillRect()
方法用于以指定颜色在画布上绘制并填充矩形。填充颜色使用fillStyle
属性设置。// 填充一个在canvas 元素中 x 为20像素,y 为20像素,宽高为100像素的原谅色的矩形 context.fillStyle = "green"; context.fillRect(20, 20, 100, 100); // 绘制透明矩形 context.fillStyle = "rgba(0, 255, 0, 0.5)"; context.fillRect(130, 20, 100, 100);
-
strokeRect()
方法使用strokeStyle
属性指定的颜色绘制矩形轮廓。// 绘制矩形轮廓 context.strokeStyle = "blue"; context.strokeRect(10, 10, 50, 50); // 绘制透明矩形轮廓 context.strokeStyle = "rgba(0, 0, 255, 0.5)"; context.strokeRect(10, 100, 50, 50);
-
clearRect()
方法可以擦除画布中某个区域。用于将绘图上下文某个区域便透明。// 清除矩形 context.fillStyle = "#353b48"; context.fillRect(250, 10, 100, 100); context.clearRect(275, 35, 50, 50);
绘制路径
通过路径可以创建复杂的形状和线条。绘制路径,必须首先调用 beginPath()
方法以表示要开始绘制新路径。
arc(x, y, radius, startAngle, endAngle, counterclockwise)
:以坐标 (x, y)为圆心,以radius
为半径绘制一条弧线,起始角度为startAngle
,结束角度为endAngle
。最后一个参数counterclockwise
表示是否逆时针计算起始角度和结束角度(默认是顺时针)。arcTo(x1, y1, x2, y2, radius)
:以给定半径radius
,经由 (x1, y1) 绘制一条从上一点到 (x2, y2) 的弧线。bezierCurveTo(c1x, c1y, c2x, c2y, x, y)
:以 (c1x, c1y) 和 (c2x, c2y) 为控制点,绘制一条从上一点到 (x, y) 的弧线(三次贝塞尔曲线)。lineTo(x, y)
:绘制一条从上一点到 (x, y) 的直线。moveTo(x, y)
:不绘制线条,只把绘制光标移动到 (x, y)。quadraticCurveTo(cx, cy, x, y)
:以 (cx, cy) 为控制点,绘制一条从上一点到 (x, y)的弧线(二次贝塞尔曲线)。rect(x, y, width, height)
:以给定宽度和高度在坐标点 (x, y) 绘制一个矩形。这个方法与strokeRect()
和fillRect()
的区别在于,它创建的是一条路线,而不是独立的图像。
创建路径之后,可以使用 closePath()
方法绘制一条返回起点的线。如果路线已经完成,则既可以指定 fillStyle
属性并调用 fill() 方法来填充路径,也可以指定 strokeStyle
属性并调用 stroke()
方法来描画路径,可以调用 clip()
方法基于已有路径创建一个新剪切区域。
isPointInPath()
方法,接收 x 轴和 y 轴坐标作为参数。这个方法用于确定指定的点是是否在路径上。
绘制文本
2D 绘制上下文提供绘制文本的方法,即 fillText()
和 strokeText()
。接收了 4 个参数:要绘制的字符串、x 坐标、y 坐标和可选的最大像素宽度。这两个方法最终的绘制结果都取决于以下 3 个属性:
font
:以 CSS 语法指定的字体样式、大小、字体族等。textAlign
:指定文本的对齐方式,可能的值包括 “start”、“end”、“left”、“right” 和 “center”。推荐使用 “start” 和 “end”。不使用 “left” 和 “right”。因为前者无论在从左到右书写的语言还是从右到左书写的语言中含义都更明确。textBaseLine
:指定文本的基线,可能的值包括 “top”、“hanging”、“middle”、“alphabetic”、“ideographic” 和 “bottom”。
measureText()
方法用于辅助确定文本大小。接收一个参数:要绘制的文本,返回一个 TextMetrics 对象。这个返回的对象目前只有一个属性 width。measureText()
方法使用 font
、textAlign
和 textBaseline
属性当前的值计算绘制指定文本后的大小。
变换
2D 绘图上下文支持所有常见的绘制变换。
变换的方法
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_!, m1_2, m2_1, m2_2, dx, dy)
:像下面这样通过矩阵乘以直接修改矩阵。setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy)
:把矩阵重置为默认值,再以传入的参数调用transform()
。
绘制图像
2D 绘图上下文内置支持操作图像。如果想把现有图像绘制到画布中,可以使用 drawImage() 方法。接收 3 组不同的参数,并产生不同的结果。最简单的调用是传入一个 HTML 的 元素,以及表示绘制目标的 x 和 y 坐标,结果把图像绘制到指定位置。
let image = document.images[0];
context.drawImage(image, 10, 10);
上述代码表示,将文档中的第一张图片,在画布中坐标(10, 10)处绘制出来。绘制出来的图像与原来的图像一样大。如果想要改变所绘制图像的大小,可以再传入两个参数:目标宽度和目标高度。
context.drawImage(image, 50, 10, 20 , 30);
代码执行之后图像会缩放成 20像素宽,30像素高。
可以把图像绘制到上下文中的一个区域。需要给 drawImage()
提供 9 个参数:要绘制的图像、源图像 x 坐标、源图像 y 坐标、源图像宽度、源图像高度、目标区域 x 坐标、目标区域 y 坐标、目标区域宽度和目标区域高度。
context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);
阴影
2D 上下文可以根据以下属性的值自动为已有形状或路径生成阴影。
shadowColor
:CSS 颜色值,表示要绘制的阴影颜色,默认为黑色。shadowOffsetX
:阴影相对于形状或路径的 x 坐标的偏移量,默认为 0 。shadowOffsetY
:阴影相对于形状或路径的 y 坐标的偏移量,默认为 0 。shadowBlur
:像素,表示阴影的模糊量。默认值为 0 ,表示不模糊。
渐变
创建一个线性渐变,可以调用上下文的 createLinearGradient()
方法。接收 4 个参数:起点 x 坐标、起点 y 坐标、终点 x 坐标和终点 y 坐标。会创建处一个新的 CanvasGradient 对象并返回实例。
有了 gradient 对象之后,使用 addColorStop()
方法为渐变指定色标。接收 2 个参数:色标位置和 CSS 颜色字符串。色标位置通过 0 ~ 1 范围内的值表示,0 是第一种颜色,1 是最后一种颜色。
let gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "green");
上述代码表示:在画布上从 (30, 30) 到 (70, 70) 绘制一个渐变。渐变的起点颜色是白色,终点颜色是原谅色。可以把这个值赋值给 fillStyle
或 strokeStyle
属性。
context.fillStyle = gradient;
例:
// 线性渐变
let gradient1 = context.createLinearGradient(300, 300, 500, 500);
gradient1.addColorStop(0, "white");
gradient1.addColorStop(1, "green");
context.fillStyle = gradient1;
context.fillRect(300, 300, 200, 200);
径向渐变,使用 createRadialGradient()
方法来创建。接收 6 个参数。分别对应两个圆形圆心的坐标和半径。前 3 个参数指定起点圆形中心的 x 、y 坐标和半径,后 3 个参数指定终点圆形中心的 x、y 坐标和半径。
要创建起点圆心在形状中心并向外扩散的径向渐变,需要将两个圆形设置为同心圆。
let gradient = context.createRadialGradient(66, 66, 10, 66, 66, 30);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "blue");
例:
let gradient = context.createRadialGradient(200, 200, 60, 200, 200, 100);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "rgba(0, 0, 255, 0.5)");
context.fillStyle = gradient;
context.fillRect(100, 100, 200, 200);
图案
图案用于填充和描画图形的重复图像。创建新图案,通过调用 createPattern()
方法并传入两个参数:一个 HTML 元素和一个表示该如何重复图像的字符串。第二个参数的值与 CSS 的 background-repeat
的属性一样。包括 “repeat” 、 “repeat-x”、“repeat-y” 和 “no-repeat”。
let image = document.images[0];
let pattern = context.createPattern(image, "repeat");
context.fillStyle = pattern;
context.fillRect(10, 10, 100, 100);
图像数据
使用 getImageData()
方法获取原始图像数据。接收 4 个参数:要取得数据中第一个像素的左上角坐标和取得的像素宽度及高度。
let imageData = context.getImageData(10, 10, 50, 50);
返回的对象是一个 ImageData 的实例,每个 ImageData 包含 3 个属性:width、height 和 data,其中 data 属性包含图像的原始像素信息的数组。每个像素在data 数组中由 4 个值表示,分别代表红、绿、蓝和透明度值。
let data = imageData.data,
red = data[0],
green = data[1],
blue = data[2],
alpha = data[3];
合成
2D 上下文绘制的所有内容都会应用两个属性: globalAlpha
和 globalCompositionOperation
。
globalAlpha
属性是一个范围在 0 ~ 1 的值(包括 0 和 1),用于指定所有绘制内容的透明度。默认值是 0 。如果后面需要绘制同样的透明度,可以将 globalAlpha
属性设置为适当的值,执行绘制,然后再把 globalAlpha
属性设置为 0 。
globalCompositionOperation
属性表示新绘制的形状如何与上下文中已有的形状融合。
- source-over:默认值,新图形绘制在原有图形上面。
- source-in:新图形只绘制出与原有图形重叠的部分,画布上其余部分全部透明。
- source-out:新图形只绘制出不与原有图形重叠的部分,画布上其余部分全部透明。
- source-atop:新图形只绘制出与原有图形重叠的部分,原有图形不受影响。
- destination-over:新图形绘制在原有图形下面,重叠部分只有原图形透明像素下的部分可见。
- destination-in:新图形绘制在原有图形下面,画布上只剩下二者重叠的部分,其余部分完全透明。
- destination-out:新图形与原有图形重叠的部分完全透明,原图形其余部分不受影响。
- destination-atop:新图形绘制在原有图形下面,原有图形与新图形不重叠的部分完全透明。
- lighter:新图形将擦除与原有图形重叠部分的像素值相加,使该部分变亮。
- copy:新图形将擦除并完全取代原有图形。
- xor:新图形与原有图形重叠部分的像素执行 “异或” 计算。