如何理解并应用贝塞尔曲线

9次阅读

共计 2692 个字符,预计需要花费 7 分钟才能阅读完成。

贝塞尔曲线又叫贝兹曲线,在大学高数中一度让我非常头疼。前阵子练手写动画的时候,发现贝塞尔曲线可以应用于轨迹的绘制以及定义动画曲线。
本文就来探究一下,贝塞尔曲线到底是个什么样的存在。
贝塞尔曲线原理
贝塞尔曲线由 n 个点来决定,其曲线轨迹可以由一个公式来得出:

其中 n 就代表了贝塞尔曲线是几阶曲线,该公式描述了曲线运动的路径。
以下我们来讨论一下,贝塞尔公式如何推导。
一阶贝塞尔曲线

设定图中运动的点为 Pt,t 为运动时间,t∈(0,1),可得如下公式

二阶贝塞尔曲线

在二阶贝塞尔曲线中,已知三点恒定(P0,P1,P2),设定在 P0P1 中的点为 Pa,在 P1P2 中的点为 Pb,Pt 在 PaPb 上的点,这三点都在相同时间 t 内做匀速运动。
由公式 (1) 可知

将公式 (2)(3) 代入公式 (4) 中,可得

三阶贝塞尔曲线

同理,根据以上的推导过程可得

由此可以推导

n 阶贝塞尔曲线

放上一个网址,随意感受一下贝塞尔曲线的绘制过程:
http://myst729.github.io/bezi…
实际应用
贝塞尔曲线在前端中主要有两方面的应用,一方面可以作为动画曲线应用于 CSS3 动画中;另一方面可以通过 canvas 来绘制曲线达到需要的效果。
CSS3 中贝塞尔曲线的应用
在 CSS3 中,有两属性经常被用到:transition-timing-function 和 animation-timing-function, 这两个分别代表了过渡的速度和动画的速度。CSS3 为我们提供了一个新的工具——cubic-bezier(x1,y1,x2,y2)。这个工具能够生成一个速度曲线,使我们的元素按照该曲线来调节速度。
在上面的推导中,我们知道在贝塞尔公式中,有两个点的位置恒定——P0 和 P1,cubic-bezier 中定义了两个控制点的位置,所以该曲线为三阶贝塞尔曲线。
有个网站可以方便我们快速建立一个贝塞尔曲线:cubic-bezier
贝塞尔曲线与动画曲线的关联
先来一波动图简单粗暴的感受一下:例一:

例二:

例三:

左边的是贝塞尔曲线,横轴代表了事件,竖轴代表了进度,无法直观得感受出速度的变化。
右边的曲线是控制面板中的动画曲线,横轴是时间,竖轴是速度,可以方面地看出速度的变化。
上述例子中,以前进反向为速度正方向,后退方向为速度反方向。
如何得知速度的变化
推导
例一中,贝塞尔曲线为一条直线,当时间均匀变化时,进度也在均匀变大,由此可知速度恒定不变,时间和进度之间的关系可以用一个线性方程来表示:
y=ax+b (a=1,b=0)
其中 x 为时间,y 为进度,a 即为速度。
推导案例一
从上面结论中启发,去观察其他贝塞尔曲线,

图中是一段变化的曲线,我们取其中一小段,将其看作稳定不变的一段直线,通过下面的线性方程来表示,并通过红线标注在图中:
y=ax+b
根据初中数学的内容,我们知道,当 a >1 时,与 x 轴的夹角∈(45°,90°);当 a∈(0,1)时,与 x 轴的夹角在 (0,45°) 之间。相同的时间内,与 x 轴的夹角越大,a 越大,速度越快。
观察上图的夹角变化趋势,夹角逐渐变小趋向于 0,而后逐渐变大,趋向于 90°,对应速度应是速度逐渐变慢趋向于 0,之后逐渐变快。
放上动画曲线以及动图来验证一下我们的推测:

推导案例二
下图中的曲线部分在第四象限,部分在第一象限,这时对应的动画曲线该如何推导呢。
同样将该曲线视为由 n 段平滑的直线构成,由线性方程来表示直线的趋势,可知速度 a 方向一开始为负,之后慢慢向正方靠近,a 的速率也在由大变小,当为 0 时,再向正方慢慢变大。即该曲线表示元素一开始在朝反方向减速运动,当速度为 0 后,向正方向作加速运动。

通过动画曲线及动图来验证上述推导:

验证
用两个曲线来验证一下上面的结论:
曲线一:

曲线二:

从结果可以判断,用上述推导方法可以正确得出贝塞尔曲线与动画曲线之间的关系。
动画曲线的应用
了解了如何用贝塞尔曲线来指定动画曲线后,很多动画涉及到速度方面的效果就可以实现了,例如小车加速刹车,弹簧动画等速度轨迹都可以根据自己的需要来进行定制。
放上一个缓动函数速查网址,可以让自己的动效更加真实:缓动函数
放一个小例子:

该动画模拟了小球落下回弹的过程
代码如下:
<div class=”ground”>
<div class=”ball” id=”ball”></div>
</div>
.ball {
width: 30px;
height: 30px;
background: #000000;
border-radius: 50%;
position: absolute;
top: 0;
left: 50%;
animation: move 4s cubic-bezier(0.36, 1.7, 0.26, 0.61) 1s infinite;
}

@keyframes move {
0% {
top: 0;
}
100% {
top: 90%;
}
}
这类动画可以参考网上大大们的案例:
贝塞尔曲线与 CSS3 动画、SVG 和 canvas 的应用
理解与运用贝塞尔曲线
利用 canvas 绘制贝塞尔曲线
canvas 中提供了 api 可以快速绘制一条贝塞尔曲线,来达到需要的效果:
二阶贝塞尔曲线
quadraticCurveTo(x1,y1,x2,y2)
var c=document.getElementById(“myCanvas”);
var ctx=c.getContext(“2d”);
ctx.beginPath();
ctx.moveTo(20,20);
ctx.quadraticCurveTo(40,200,200,20);
ctx.stroke();

其中 moveTo 定义了起始点,quadraticCurveTo(x1,y1,x2,y2)中的 (x1,y1) 为控制点,(x2,y2)为终点
三阶贝塞尔曲线
bezierCurveTo(x1,y1,x2,y2,x3,y3)
var c=document.getElementById(“myCanvas”);
var ctx=c.getContext(“2d”);
ctx.beginPath();
ctx.moveTo(20,20);
ctx.bezierCurveTo(40,100,200,150,200,20);
ctx.stroke();

其中 moveTo 定义了起始点,bezierCurveTo(x1,y1,x2,y2)中的 (x1,y1),(x2,y2) 为控制点,(x3,y3)为终点
总结
为了弄清贝塞尔曲线是个什么东西,和动画曲线、速度又有什么关联,作者跑去复习了一下那些早扔给老师的东西,有说错的请轻拍 /(ㄒ o ㄒ)/~~
广而告之
本文发布于薄荷前端周刊,欢迎 Watch & Star ★,转载请注明出处。
欢迎讨论,点个赞再走吧 。◕‿◕。 ~

正文完
 0