ZetCode

HTML5 Canvas 中的线条

最后修改于 2023 年 7 月 17 日

线是简单的图形图元。线是一个连接两个点的对象。

在 HTML5 Canvas 中,线是通过路径对象创建的。路径是点的列表,由不同形状、弯曲或不弯曲、不同宽度和不同颜色的线段连接而成。在路径对象中,线是用 lineTo 方法创建的。

线条

以下示例绘制了两条线。

lines.html
<!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 设置第二条线的宽度;该线更粗。

Lines
图:线条

清晰的线条

奇数宽度的线条会显得模糊。这是因为线条是渲染在 Canvas 的网格线之间的。有一个快速的解决方案——将坐标偏移半个单位。

crisp_lines.html
<!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 方法将坐标系移动半个单位。

Crisp lines
图:清晰的线条

线段

线可以使用各种线段绘制。线段是由不透明和透明部分混合创建的模式。线段通过 Canvas 上下文的 setLineDash 方法指定。

line_dashes.html
<!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 个单位。

Line dashes
图:线段

线帽

线帽是应用于未闭合子路径和线段末端的装饰。Java 2D 中有三种不同的线帽:'square''round''butt'

line_caps.html
<!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 上下文属性指定。

Line caps
图:线帽

垂直线突显了线的大小差异。

连接

线连接是应用于两个路径段交叉处和子路径端点交叉处的装饰。有三种装饰:'bevel''miter''round'

line_joins.html
<!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 属性设置。

Joins
图:连接

贝塞尔曲线

贝塞尔曲线是贝塞尔曲线(三次曲线),由数学公式定义。绘制曲线的数学方法是由 Pierre Bézier 在 20 世纪 60 年代末为雷诺汽车制造而创建的。

Canvas 上下文的 bezierCurveTo 方法将三次贝塞尔曲线添加到路径中。它需要三个点:前两个点是控制点,第三个点是终点。起点是当前路径的最后一个点,可以在创建贝塞尔曲线之前使用 moveTo 进行更改。通过移动控制点来修改曲线形状。

bezier_curve.html
<!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);

这些线绘制了曲线的控制点。

Bézier curve
图:贝塞尔曲线

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