在Canvas画布上如何利用三次贝塞尔曲线绘制出连续的曲线?

在Canvas画布上利用三次贝塞尔曲线绘制出连续的曲线,关键在于确定每个曲线的起点、终点以及控制点,并确保每条曲线的终点与下一条曲线的起点相连。下面是一个完整的HTML文件示例,展示了如何在Canvas上绘制连续的三次贝塞尔曲线。

示例效果与源代码:

运行效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html lang="zh_CN">

<head>
<title>绘制曲线和路径(bezierCurveTo)</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="图形系统开发实战:基础篇 示例">
<meta name="author" content="hjq">
<meta name="keywords" content="canvas,anygraph,javascript,图形">
<script src="../js/helper.js"></script>
</head>

<body style="margin:10px;">
<canvas id="canvas" width="550" height="300" style="border:solid 1px #CCCCCC;"></canvas>
</body>
<script>
// 从页面中获取画板对象
let canvas = document.getElementById('canvas');
// 从画板中获取“2D渲染上下文”对象
let ctx = canvas.getContext('2d');

function drawBackground() {
// 绘制背景网格线
//drawGrid('lightgray', 10, 10);

// 绘制曲线
ctx.beginPath();
ctx.moveTo(30, 260);
ctx.bezierCurveTo(90, 260, 60, 60, 160, 60);
ctx.bezierCurveTo(230, 60, 220, 260, 280, 260);
ctx.bezierCurveTo(340, 260, 310, 60, 400, 60);
ctx.bezierCurveTo(480, 60, 470, 260, 520, 260);
ctx.lineWidth = 4;
ctx.strokeStyle = "red";
ctx.stroke();
}
let idx = 0;

/**
* 一步一步绘制曲线
*/
function draw() {
ctx.lineWidth = 4;
ctx.strokeStyle = "blue";
if (idx == 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBackground();
} else if (idx == 1) {
ctx.beginPath();
ctx.arc(30, 260, 6, 0, 2 * Math.PI, false);
ctx.fillStyle = "blue";
ctx.fill();
} else if (idx == 2) {
ctx.beginPath();
ctx.moveTo(30, 260);
ctx.bezierCurveTo(90, 260, 60, 60, 160, 60);
ctx.stroke();
} else if (idx == 3) {
ctx.beginPath();
ctx.moveTo(160, 60);
ctx.bezierCurveTo(230, 60, 220, 260, 280, 260);
ctx.stroke();
} else if (idx == 4) {
ctx.beginPath();
ctx.moveTo(280, 260);
ctx.bezierCurveTo(340, 260, 310, 60, 400, 60);
ctx.stroke();
} else if (idx == 5) {
ctx.beginPath();
ctx.moveTo(400, 60);
ctx.bezierCurveTo(480, 60, 470, 260, 520, 260);
ctx.stroke();
}

// 下一步
idx = idx < 5 ? idx + 1 : 0;
// 循环绘制
window.setTimeout(draw, 2000);
}

draw();
</script>

</html>

尝试一下 »

解释:

示例中的曲线由4条曲线段组成,绘制方法如下,首先使用beginPath方法开始路径,然后使用moveTo方法指定画笔的当前位置。
接着使用bezierCurveTo方法开始绘制第一条曲线段,
需要注意的是,在bezierCurveTo()执行后,画布会将曲线的终点作为新的当前位置,在绘制第二条曲线段时,会以该位置作为曲线的起点绘制新的曲线段,同理绘制第二条曲线后,曲线的终点位置将作为新的曲线的起点,
同理可连续绘制第三条、第四条曲线段

按照路径绘制的的基本流程,使用strokeStyle设置曲线颜色,最后使用stroke方法对连续的曲线进行描边,将连续曲线的绘制在画布上。
如此,我们就完成了这段连续曲线的绘制。