HTML5 Canvas 中的线条
最后修改于 2023 年 7 月 17 日
线是简单的图形图元。线是一个连接两个点的对象。
在 HTML5 Canvas 中,线是通过路径对象创建的。路径是点的列表,由不同形状、弯曲或不弯曲、不同宽度和不同颜色的线段连接而成。在路径对象中,线是用 lineTo
方法创建的。
线条
以下示例绘制了两条线。
<!DOCTYPE html> <html> <head> <title>HTML5 canvas lines</title> <script> function draw() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.moveTo(20, 20); ctx.lineTo(250, 150); ctx.stroke(); ctx.beginPath(); ctx.moveTo(20, 20); ctx.lineTo(250, 250); ctx.lineWidth = 5; ctx.stroke(); } </script> </head> <body onload="draw();"> <canvas id="myCanvas" width="350" height="350"> </canvas> </body> </html>
绘制了两条线。第二条线更粗。
ctx.beginPath();
beginPath
方法创建一个新路径。创建后,后续的绘图命令会定向到该路径,并用于构建路径。
ctx.moveTo(20, 20);
moveTo
方法将画笔移动到由 x 和 y 指定的坐标。
ctx.lineTo(250, 150);
lineTo
方法从当前绘图位置绘制一条线到由 x 和 y 指定的位置。
ctx.stroke();
stroke
方法通过描边轮廓来绘制线。
ctx.lineWidth = 5;
lineWidth
设置第二条线的宽度;该线更粗。

清晰的线条
奇数宽度的线条会显得模糊。这是因为线条是渲染在 Canvas 的网格线之间的。有一个快速的解决方案——将坐标偏移半个单位。
<!DOCTYPE html> <html> <head> <title>HTML5 canvas crisp lines</title> <script> function draw() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.lineWidth = 1 ctx.beginPath(); ctx.moveTo(20, 20); ctx.lineTo(250, 20); ctx.stroke(); ctx.beginPath(); ctx.moveTo(20, 40); ctx.lineTo(250, 40); ctx.stroke(); ctx.translate(0.5, 0.5); ctx.beginPath(); ctx.moveTo(20, 60); ctx.lineTo(250, 60); ctx.stroke(); ctx.beginPath(); ctx.moveTo(20, 80); ctx.lineTo(250, 80); ctx.stroke(); } </script> </head> <body onload="draw();"> <canvas id="myCanvas" width="350" height="350"> </canvas> </body> </html>
该示例绘制了四条线。前两条线略有模糊,后两条线更平滑。
ctx.lineWidth = 1
我们有一条奇数宽度的线。
ctx.translate(0.5, 0.5);
这是解决线条模糊问题的快速方法。translate
方法将坐标系移动半个单位。

线段
线可以使用各种线段绘制。线段是由不透明和透明部分混合创建的模式。线段通过 Canvas 上下文的 setLineDash
方法指定。
<!DOCTYPE html> <html> <head> <title>HTML5 canvas line dashes</title> <script> function draw() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.translate(0.5, 0.5); ctx.beginPath(); ctx.setLineDash([2]); ctx.moveTo(10, 10); ctx.lineTo(250, 10); ctx.stroke(); ctx.beginPath(); ctx.setLineDash([7, 2]); ctx.moveTo(10, 20); ctx.lineTo(250, 20); ctx.stroke(); ctx.beginPath(); ctx.setLineDash([4, 4, 1]); ctx.moveTo(10, 30); ctx.lineTo(250, 30); ctx.stroke(); } </script> </head> <body onload="draw();"> <canvas id="myCanvas" width="350" height="250"> </canvas> </body> </html>
该示例绘制了三条具有不同线段模式的线。
ctx.setLineDash([2]);
这条线将交替显示 2 个坐标单位的不透明和透明部分。
ctx.setLineDash([4, 4, 1]);
在这里,线段由以下模式组成:绘制 4 个单位,不绘制 4 个单位,绘制 1 个单位。

线帽
线帽是应用于未闭合子路径和线段末端的装饰。Java 2D 中有三种不同的线帽:'square'
、'round'
和 'butt'
。
'butt'
— 在未闭合子路径和线段的末端不添加任何装饰。'round'
— 在未闭合子路径和线段的末端添加一个圆形装饰,其半径等于笔触宽度的一半。'square'
— 在未闭合子路径和线段的末端添加一个方形投影,该投影延伸到线段末端之外,距离等于线宽的一半。
<!DOCTYPE html> <html> <head> <title>HTML5 canvas line caps</title> <script> function draw() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.translate(0.5, 0.5); ctx.lineWidth = 8; ctx.beginPath(); ctx.lineCap = 'square'; ctx.moveTo(10, 10); ctx.lineTo(250, 10); ctx.stroke(); ctx.beginPath(); ctx.lineCap = 'round'; ctx.moveTo(10, 30); ctx.lineTo(250, 30); ctx.stroke(); ctx.beginPath(); ctx.lineCap = 'butt'; ctx.moveTo(10, 50); ctx.lineTo(250, 50); ctx.stroke(); ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(10, 0); ctx.lineTo(10, 60); ctx.stroke(); ctx.beginPath(); ctx.moveTo(250, 0); ctx.lineTo(250, 60); ctx.stroke(); ctx.beginPath(); ctx.moveTo(254, 0); ctx.lineTo(254, 60); ctx.stroke(); } </script> </head> <body onload="draw();"> <canvas id="myCanvas" width="350" height="250"> </canvas> </body> </html>
在我们的示例中,我们展示了所有三种类型的线帽。
ctx.lineWidth = 8;
我们增加了线的宽度,以便更好地看到线帽。
ctx.lineCap = 'square';
线帽通过 lineCap
上下文属性指定。

垂直线突显了线的大小差异。
连接
线连接是应用于两个路径段交叉处和子路径端点交叉处的装饰。有三种装饰:'bevel'
、'miter'
和 'round'
。
'bevel'
— 通过将它们的宽轮廓的外部角连接起来形成一条直线段来连接路径段。'miter'
— 通过将其外边缘延伸直到它们相遇来连接路径段。'round'
— 通过将角圆化成半径等于线宽一半的圆来连接路径段。
<!DOCTYPE html> <html> <head> <title>HTML5 canvas line joins</title> <script> function draw() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.translate(0.5, 0.5); ctx.lineWidth = 8; ctx.lineJoin = 'miter'; ctx.strokeRect(10, 10, 100, 100); ctx.lineJoin = 'bevel'; ctx.strokeRect(130, 10, 100, 100); ctx.lineJoin = 'round'; ctx.strokeRect(260, 10, 100, 100); } </script> </head> <body onload="draw();"> <canvas id="myCanvas" width="450" height="350"> </canvas> </body> </html>
此代码示例展示了三种不同的线连接效果。
ctx.lineWidth = 8;
对于细线,很难区分连接类型的差异。因此,我们将线设置得更粗,将 lineWidth
设置为八个单位。
ctx.lineJoin = 'miter';
线连接通过 lineJoin
属性设置。

贝塞尔曲线
贝塞尔曲线是贝塞尔曲线(三次曲线),由数学公式定义。绘制曲线的数学方法是由 Pierre Bézier 在 20 世纪 60 年代末为雷诺汽车制造而创建的。
Canvas 上下文的 bezierCurveTo
方法将三次贝塞尔曲线添加到路径中。它需要三个点:前两个点是控制点,第三个点是终点。起点是当前路径的最后一个点,可以在创建贝塞尔曲线之前使用 moveTo
进行更改。通过移动控制点来修改曲线形状。
<!DOCTYPE html> <html> <head> <title>HTML5 canvas Bézier curve</title> <meta charset="utf-8"> <script> function draw() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.moveTo(20, 60); ctx.bezierCurveTo(80, 20, 180, 160, 250, 50); ctx.stroke(); ctx.fillStyle = 'cadetblue'; ctx.fillRect(80, 20, 4, 4); ctx.fillRect(180, 160, 4, 4); } </script> </head> <body onload="draw();"> <canvas id="myCanvas" width="350" height="350"> </canvas> </body> </html>
该示例绘制了一条贝塞尔曲线。
ctx.moveTo(20, 60);
使用 moveTo
方法,我们定义了曲线的起点。
ctx.bezierCurveTo(80, 20, 180, 160, 250, 50);
使用 bezierCurveTo
方法,我们将贝塞尔曲线添加到路径中。前两个点是控制点;最后一个点是曲线的终点。
ctx.fillStyle = 'cadetblue'; ctx.fillRect(80, 20, 4, 4); ctx.fillRect(180, 160, 4, 4);
这些线绘制了曲线的控制点。

在 HTML5 Canvas 教程的这一部分,我们研究了线。