CanvasRenderingContext2D
绘制路径的相关方法
- fill()
使用当前的样式填充子路径。
void ctx.fill();
void ctx.fill(fillRule);
void ctx.fill(path, fillRule);
参数:
fillRule,一种算法,决定点是在路径内还是在路径外。
path,需要填充的Path2D
路径。
- stoke()
使用当前的样式描边子路径。
void ctx.stroke();
void ctx.stroke(path);
参数:path,绘制的路径path2D。
- drawFocusIfNeeded()
如果给定的元素获取了焦点,那么此方法会在当前的路径绘制一个焦点。
void ctx.drawFocusIfNeeded(element);
void ctx.drawFocusIfNeeded(path, element);
参数:
element:是否需要设置焦点的元素。
path:path2D路径。
- scrollPathIntoView()
将当前或给定的路径滚动到窗口。
void ctx.scrollPathIntoView();
void ctx.scrollPathIntoView(path);
- clip()
从当前路径创建一个剪切路径。在 clip() 调用之后,绘制的所有信息只会出现在剪切路径内部。
void ctx.clip();
void ctx.clip(fillRule);
void ctx.clip(path, fillRule);
参数:
fillRule:这个算法判断一个点是在路径内还是在路径外。
path:需要剪切的路径。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Create circular clipping region
ctx.beginPath();
ctx.arc(100, 75, 50, 0, Math.PI * 2);
ctx.clip();
// Draw stuff that gets clipped
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'orange';
ctx.fillRect(0, 0, 100, 100);
以上得出结果:
- isPointInPath()
判断当前路径是否包含检测点。
isPointInPath(x, y)
isPointInPath(x, y, fillRule)
isPointInPath(path, x, y)
isPointInPath(path, x, y, fillRule)
参数
x:检测点的 X 坐标
y:检测点的 Y 坐标
fillRule
:用来决定点在路径内还是在路径外的算法。
path
:Path2D
应用的路径。
html
<canvas id="canvas"></canvas>
<p>In path: <code id="result">false</code></p>
javaScript
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const result = document.getElementById('result');
ctx.rect(10, 10, 100, 100);
ctx.fill();
result.innerText = ctx.isPointInPath(30, 70);
以上例子如图:
- isPointInStroke()
判断检测点是否在路径的描边线上。
boolean ctx.isPointInStroke(x, y);
boolean ctx.isPointInStroke(path, x, y);
参数:
x:检测点的X坐标。
y:检测点的y坐标。
path:Path2D路径。
html
<canvas id="canvas"></canvas>
<p>In stroke: <code id="result">false</code></p>
javaScript
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const result = document.getElementById('result');
ctx.rect(10, 10, 100, 100);
ctx.stroke();
result.innerText = ctx.isPointInStroke(50, 10);
变换
在 CanvasRenderingContext2D
渲染背景中的对象会有一个当前的变换矩阵,一些方法可以对其进行控制。当创建当前的默认路径,绘制文本、图形和 Path2D
对象的时候,会应用此变换矩阵。下面列出的方法保持历史和兼容性的原因,是为了 DOMMatrix
对象现在能够应用于大部分 API,将来会被替换。
rotate()
在变换矩阵中增加旋转,角度变量表示一个顺时针旋转角度并且用弧度表示。
void ctx.rotate(angle);
参数:顺时针旋转的弧度。如果你想通过角度值计算,可以使用公式: degree * Math.PI / 180
。
旋转中心点一直是 canvas 的起始点。如果想改变中心点,我们可以通过 translate()
方法移动 canvas。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Point of transform origin
ctx.arc(0, 0, 5, 0, 2 * Math.PI);
ctx.fillStyle = 'blue';
ctx.fill();
// Non-rotated rectangle
ctx.fillStyle = 'gray';
ctx.fillRect(100, 0, 80, 20);
// Rotated rectangle
ctx.rotate(45 * Math.PI / 180);
ctx.fillStyle = 'red';
ctx.fillRect(100, 0, 80, 20);
// Reset transformation matrix to the identity matrix
ctx.setTransform(1, 0, 0, 1, 0, 0);
旋转中心是蓝色的。未旋转的矩形为灰色,而旋转后的矩形为红色。
如下图:
scale()
根据 x 水平方向和 y 垂直方向,为 canvas 单位添加缩放变换。
默认的,在 canvas 中一个单位实际上就是一个像素。例如,如果我们将 0.5 作为缩放因子,最终的单位会变成 0.5 像素,并且形状的尺寸会变成原来的一半。相似的方式,我们将 2.0 作为缩放因子,将会增大单位尺寸变成两个像素。形状的尺寸将会变成原来的两倍。
void ctx.scale(x, y);
参数:
x:水平方向的缩放因子。y:垂直方向的缩放因子。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Scaled rectangle
ctx.scale(9, 3);
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 8, 20);
// Reset current transformation matrix to the identity matrix
ctx.setTransform(1, 0, 0, 1, 0, 0);
// Non-scaled rectangle
ctx.fillStyle = 'gray';
ctx.fillRect(10, 10, 8, 20);
如下图,红色矩形是缩放的,灰色矩形没有。
translate()
通过在网格中移动 canvas 和 canvas 原点 x 水平方向、原点 y 垂直方向,添加平移变换
void ctx.translate(x, y);
参数:
-
x:水平方向的移动距离。
-
y:垂直方向的移动距离。
transform()
使用矩阵多次叠加当前变换的方法,矩阵由方法的参数进行描述。你可以缩放、旋转、移动和倾斜上下文。
void ctx.transform(a, b, c, d, e, f);
-
a (m11)
:水平缩放。 -
b (m12)
:垂直倾斜。 -
c (m21)
:水平倾斜。 -
d (m22)
:垂直缩放。 -
e (dx)
:水平移动。 -
f (dy)
: 垂直移动。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.transform(1, 0.2, 0.8, 1, 0, 0);
ctx.fillRect(0, 0, 100, 100);
如下图:
setTransform()
使用单位矩阵重新设置(覆盖)当前的变换并调用变换的方法,此变换由方法的变量进行描述。
void ctx.setTransform(a, b, c, d, e, f);
参数与transform的参数一样。
resetTransform()
使用单位矩阵重新设置当前的变换。
void ctx.resetTransform();
合成的相关属性
globalAlpha
在合成到 canvas 之前,设置图形和图像透明度的值。默认 1.0
(不透明)。
如下例子:
绘制了 4 个不同背景色的正方形。在他们上面,绘制半透明的圆形。将那个点绘制的所有图形的 globalAlpha
属性值都设置为 0.2。通过 for 循环绘制半径逐渐增大的圆形。最终形成的结果是放射性渐变。通过不停地叠加圆形,使得先前绘制的圆形的透明度越来越暗。通过增加循环数量绘制更多的圆形,图片中心的背景将会变成完全不透明。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Draw background
ctx.fillStyle = '#FD0';
ctx.fillRect(0, 0, 75, 75);
ctx.fillStyle = '#6C0';
ctx.fillRect(75, 0, 75, 75);
ctx.fillStyle = '#09F';
ctx.fillRect(0, 75, 75, 75);
ctx.fillStyle = '#F30';
ctx.fillRect(75, 75, 75, 75);
ctx.fillStyle = '#FFF';
// Set transparency value
ctx.globalAlpha = 0.2;
// Draw transparent circles
for (let i = 0; i < 7; i++) {
ctx.beginPath();
ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true);
ctx.fill();
}
globalCompositeOperation
设置要在绘制新形状时应用的合成操作的类型,其中 type 是用于标识要使用的合成或混合模式操作的字符串。
-
source-over:(默认)并在现有画布上下文之上绘制新图形。
-
source-in:新图形只在新图形和目标画布重叠的地方绘制。其他的都是透明的。
-
source-out:在不与现有画布内容重叠的地方绘制新图形。
-
source-atop:新图形只在与现有画布内容重叠的地方绘制。
-
destination-over:在现有的画布内容后面绘制新的图形。
-
destination-in:现有的画布内容保持在新图形和现有画布内容重叠的位置。其他的都是透明的。
-
destination-out:现有内容保持在新图形不重叠的地方。
-
destination-atop:现有的画布只保留与新图形重叠的部分,新的图形是在画布内容后面绘制的。
-
lighter:两个重叠图形的颜色是通过颜色值相加来确定的。
-
copy:只显示新图形。
-
xor:图像中,那些重叠和正常绘制之外的其他地方是透明的。
-
multiply:将顶层像素与底层相应像素相乘,结果是一幅更黑暗的图片。
-
screen:像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。
-
overlay:multiply 和 screen 的结合,原本暗的地方更暗,原本亮的地方更亮。
-
darken:保留两个图层中最暗的像素。
-
lighten:保留两个图层中最亮的像素。
-
color-dodge:将底层除以顶层的反置。
-
color-burn:将反置的底层除以顶层,然后将结果反过来。
-
hard-light:屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。
-
soft-light:用顶层减去底层或者相反来得到一个正值。
-
difference:一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。
-
exclusion:和 difference 相似,但对比度较低。
-
hue:保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。
-
saturation:保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)。
-
color:保留了底层的亮度(luma),同时采用了顶层的色调 (hue) 和色度 (chroma)。
-
luminosity:保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)。
以上属性对应以下图片:
绘制图像
drawImage()
绘制指定的图片。该方法有多种格式,提供了很大的使用灵活性。
drawImage(image, dx, dy)
drawImage(image, dx, dy, dWidth, dHeight)
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
参数:
-
image
:绘制到上下文的元素。允许任何的画布图像源。 -
sx
可选:需要绘制到目标上下文中的,image
的矩形(裁剪)选择框的左上角 X 轴坐标。可以使用 3 参数或 5 参数语法来省略这个参数。 -
sy
可选:需要绘制到目标上下文中的,image
的矩形(裁剪)选择框的左上角 Y 轴坐标。可以使用 3 参数或 5 参数语法来省略这个参数。 -
sWidth
可选:需要绘制到目标上下文中的,image
的矩形(裁剪)选择框的宽度。如果不说明,整个矩形(裁剪)从坐标的sx
和sy
开始,到image
的右下角结束。可以使用 3 参数或 5 参数语法来省略这个参数。使用负值将翻转这个图像。 -
sHeight
可选:需要绘制到目标上下文中的,image
的矩形(裁剪)选择框的高度。使用负值将翻转这个图像。 -
dx
:image
的左上角在目标画布上 X 轴坐标。 -
dy
:image
的左上角在目标画布上 Y 轴坐标。 -
dWidth
:image
在目标画布上绘制的宽度。允许对绘制的image
进行缩放。如果不说明,在绘制时image
宽度不会缩放。注意,这个参数不包含在 3 参数语法中。 -
dHeight
:image
在目标画布上绘制的高度。允许对绘制的image
进行缩放。如果不说明,在绘制时image
高度不会缩放。注意,这个参数不包含在 3 参数语法中。
html
<canvas id="canvas"></canvas>
<div style="display:none;">
<img id="source"
src="rhino.jpg"
width="300" height="227">
</div>
javaScript
原图像从坐标 (33,71) 处截取一个宽度为 104 高度为 124 的图像。并将其绘制到画布的 (21, 20) 坐标处,并将其缩放为宽 87、高 104 的图像。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = document.getElementById('source');
image.addEventListener('load', (e) => {
ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
});
canvas状态
save()
使用栈保存当前的绘画样式状态,你可以使用 restore() 恢复任何改变。
restore()
恢复到最近的绘制样式状态,此状态是通过 save() 保存到”状态栈“中最新的元素。
canvas
对 HTMLCanvasElement
只读的反向引用。如果和 <canvas>
元素没有联系,可能为null
。
图像平滑属性
imageSmoothingEnabled
图像平滑的方式;如果禁用,缩放时,图像不会被平滑处理。
像素控制
createImageData()
使用指定的尺寸,创建一个新的、空白的 ImageData
对象。所有的像素在新对象中都是透明的。
getImageData()
返回一个 ImageData
对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示,起始点为*(sx, sy)、宽为sw、高为sh*。
putImageData()
将数据从已有的 ImageData
绘制到位图上。如果提供了脏矩形,只能绘制矩形的像素。
总结
CanvasRenderingContext2D接口还有很多属性和相关方法,这就不一一介绍了。请参考:CanvasRenderingContext2D - Web API 接口参考 | MDN (mozilla.org)