Canvas基础篇:三次贝塞尔曲线
前言
在我的前两篇文章中 Canvas基础篇:图形绘制 和 Canvas基础篇:二次贝塞尔曲线 中,分别讲述了如何使用Canvas绘制直线和圆弧,以及如何使用Canvas绘制二次贝塞尔曲线,本篇文章将讲解如何使用Canvas绘制三次贝塞尔曲线。
三次贝塞尔曲线
定义与概念
三次贝塞尔曲线:通过四个点来定义的一条曲线,这四个点分别代表起始点P1、控制点C1、控制点C2 和终点P2,其本质是一个三元一次方程。三次贝塞尔曲线从起始点开始,受C1、C2两个控制点的影响,向终点延伸形成曲线,其形状由这四个点的位置共同决定。
数学表达式
给定起始点P1(x1, y1)、控制点C1(cx1, cy1) 、控制点C2(cx2, cy2)和终点P2(x2, y2),三次贝塞尔曲线的参数方程如下:
B
(
t
)
=
(
1
−
t
)
3
P
1
+
3
t
(
1
−
t
)
2
C
1
+
3
t
2
(
1
−
t
)
C
2
+
t
3
P
2
,其中
t
∈
[
0
,
1
]
。
B(t)=(1−t)^3 P_1 + 3t (1−t)^2 C_1 + 3t^2 (1−t) C2 + t^3 P_2,其中t∈[0,1]。
B(t)=(1−t)3P1+3t(1−t)2C1+3t2(1−t)C2+t3P2,其中t∈[0,1]。
将其展开为极坐标形式如下:
x
(
t
)
=
(
1
−
t
)
3
x
1
+
3
t
(
1
−
t
)
2
c
x
1
+
3
t
2
(
1
−
t
)
c
x
2
+
t
3
x
2
x(t) = (1−t)^3 x_1 + 3t (1−t)^2 cx_1 + 3t^2 (1−t) cx_2 + t^3 x_2
x(t)=(1−t)3x1+3t(1−t)2cx1+3t2(1−t)cx2+t3x2
y
(
t
)
=
(
1
−
t
)
3
y
1
+
3
t
(
1
−
t
)
2
c
y
1
+
3
t
2
(
1
−
t
)
c
y
2
+
t
3
y
2
y(t) = (1−t)^3 y_1 + 3t (1−t)^2 cy_1 + 3t^2 (1−t) cy_2 + t^3 y_2
y(t)=(1−t)3y1+3t(1−t)2cy1+3t2(1−t)cy2+t3y2
随着t从0变化到1,(x(t),y(t))就会描绘出三次贝塞尔曲线。当t=0时,B(0)=P1,即曲线的起始点;当t=1时,B(1)=P2,即曲线的终点。
语法说明
在Canvas中,我们可以使用quadraticCurveTo()
方法绘制三次贝塞尔曲线,其语法如下:
bezierCurveTo(cx1, cy1, cx2, cy2, x2, y2)
其中(cx1, cy1)代表控制点C1坐标,(cx2, cy2)代表控制点C2坐标,(x2, y2)代表终点坐标;对于起点坐标,一般通过moveTo()
方法定义。
三次贝塞尔曲线示例
效果预览
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三次贝塞尔曲线示例</title>
</head>
<body>
<canvas id="myCanvas" width="600" height="600"></canvas>
<script>
// 获取 canvas 元素和绘图上下文
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 定义起始点、第一个控制点、第二个控制点和终点
const startX = 50;
const startY = 200;
const cp1X = 100;
const cp1Y = 50;
const cp2X = 300;
const cp2Y = 350;
const endX = 350;
const endY = 200;
// 开始绘制路径
ctx.beginPath();
// 移动到起始点
ctx.moveTo(startX, startY);
// 绘制三次贝塞尔曲线
ctx.bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, endX, endY);
// 设置线条样式
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
// 绘制路径
ctx.stroke();
</script>
</body>
</html>
三次贝塞尔曲线图解
三次贝塞尔曲线静态图解
上述代码为我们直观的展示了如何在Canvas中绘制一条三次贝塞尔曲线,但是曲线中各个点的位置并没有标明,我们可以通过下面的图解示例为大家更好的理解三次贝塞尔曲线:
上图中,起始点P1到终点P2的曲线即为我们的目标曲线:三次贝塞尔曲线;起点P1到控制点C1、终点P2到控制点C1、控制点C1到控制点C2的三条线,为曲线的辅助线。
上述图示的源码,我放在了 三次贝塞尔曲线静态图解 HTML 代码资源 ,有兴趣可以下载预览!
三次贝塞尔曲线动态图解
当然,上面的三次贝塞尔曲线静态图解可能还是不够直观,在这里我们通过固定起点和终点,动态调整控制点的位置,来更直观地观察三次贝塞尔曲线的变化:
上述图示的源码,我放在了 三次贝塞尔曲线动态图解 HTML 代码资源 ,有兴趣可以下载预览!
三次贝塞尔曲线应用实例
官方实例
在Canvas官方文档中,使用了多个三贝塞尔曲线来绘制心形,其效果图如下所示:
效果预览
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三次贝塞尔曲线官方实例</title>
</head>
<body>
<canvas id="canvas" width="600" height="600"></canvas>
<script>
// 获取 canvas 元素和绘图上下文
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
//三次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(75, 40);
ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
ctx.fill();
</script>
</body>
</html>
自定义实例:云朵
上述我们引入了Canvas官方文档中的一个实例,这里我们自定义一个实例:使用三次贝塞尔曲线实现一个云朵,其效果图如下所示:
效果预览
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三次贝塞尔曲线自定义实例-云朵</title>
</head>
<body>
<canvas id="canvas" width="600" height="600"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(100, 300);
ctx.bezierCurveTo(80, 260, 140, 220, 200, 250);
ctx.bezierCurveTo(230, 230, 270, 220, 320, 250);
ctx.bezierCurveTo(370, 220, 420, 230, 450, 280);
ctx.bezierCurveTo(480, 330, 400, 350, 300, 350);
ctx.bezierCurveTo(200, 350, 120, 330, 100, 300);
ctx.strokeStyle = 'lightgray';
ctx.lineWidth = 2;
ctx.stroke();
</script>
</body>
</html>
结语
本文主要介绍了三次贝塞尔曲线的相关内容,包括曲线定义、语法、图形示例和图解,在文章最后给出了两个三次贝塞尔曲线的应用实例。对于文章中错误的地方或者有任何问题,欢迎在评论区留言分享!