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)=(1t)3P1+3t(1t)2C1+3t2(1t)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)=(1t)3x1+3t(1t)2cx1+3t2(1t)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)=(1t)3y1+3t(1t)2cy1+3t2(1t)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>

结语

本文主要介绍了三次贝塞尔曲线的相关内容,包括曲线定义、语法、图形示例和图解,在文章最后给出了两个三次贝塞尔曲线的应用实例。对于文章中错误的地方或者有任何问题,欢迎在评论区留言分享!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值