说说如何使用 Canvas 路径来绘制线段

156 阅读2分钟

在 Canvas 中,调用 2d context 对象的 beginPath() 函数就会开始一个路径绘制,调用 closePath() 函数结束一个路径绘制。连接路径内的两个点的路径称为子路径。如果终点与起点相连,子路径就称为封闭路径。

我们需要绘制的线段代码,就包含在这两个函数之间。

1 简单直线线段

context.strokeStyle = "black";
context.lineWidth = 10;
context.lineCap = 'square';
context.beginPath();
context.moveTo(200, 100);
context.lineTo(300, 100);
context.stroke();
context.closePath();

运行结果:

首先利用 strokeStyle 属性定义线段颜色,lineWidth 属性定义了线段宽度。然后定义端点类型,即 lineCap 属性。

(1) lineCap 属性

lineCap 属性可定义线的端点类型,有三种端点类型:

说明
butt 默认值,端点是垂直于线段边缘的平直边缘 。
round 在线段边缘处以线宽为直径的半圆。
square 在选段边缘处以线宽为长 、 以一半线宽为宽的矩形。

效果如下:

(2)moveTo 方法

moveTo 方法用于指定一条路径开始坐标位置,语法为 context.moveTo(x,y);

参数 描述
x 路径的目标位置的 x 坐标
y 路径的目标位置的 y 坐标

(3)lineTo 方法

lineTo 方法用于表示路径按线的方式,移动到指定坐标位置,语法为 context.lineTo(x,y);,入参与 moveTo 方法相同。


接着调用 context.stroke(); 开始绘制路径,最后记得调用 closePath() 关闭该路径。

2 lineJoin 属性

两条线相交时,Canvas会在连接处创建一个填充形状,我们可以使用 lineJoin 来设置这个形状的属性。

说明
miter 默认值,在连接处边缘延长相接 。
bevel 连接处是对角线斜角。
round 连接处是圆。
/**
 * 绘制路径
 * @param context
 * @param lineJoin 连接类型
 * @param x x 坐标
 * @param y y 坐标
 */
function drawPath(context, lineJoin,x, y) {
    context.lineWidth = 20;
    context.lineJoin = lineJoin;
    context.beginPath();
    context.moveTo(x, y);
    context.lineTo(x * 3, y);
    context.lineTo(x * 3, y * 1.5);
    context.stroke();
    context.closePath();
}



drawPath(context, 'miter',30, 50);
drawPath(context, 'bevel',30, 150);
drawPath(context, 'round',30, 300);

运行结果:

3 左上角怪相

Steve Fulton 举了一个这样的示例:

//圆形端点,斜角连接,在画布左上角
context.strokeStyle = "black";
context.lineWidth = 15;
context.lineJoin = 'bevel';
context.lineCap = 'round';
context.beginPath();
context.moveTo(0, 0);
context.lineTo(25, 0);
context.lineTo(25, 25);
context.stroke();
context.closePath();

//圆形端点,斜角连接,不在画布左上角
context.beginPath();
context.moveTo(10, 50);
context.lineTo(35, 50);
context.lineTo(35, 75);
context.stroke();
context.closePath();

运行结果:

代码中,首先从画布左上角(0,0) 开始绘制,结果发生了一个奇怪的现象 。Canvas 路径在 x 轴和 y 轴方向上都绘制到了起点的外侧,导致第一条线看起来比设置值更细一些。左上角水平部分中,无法看到圆形端点;无法看到对角线斜角,因为它们都被绘制到了屏幕之外的负值坐标区域。

离开画布左上角再进行绘制,就可以解决这个问题。