贝塞尔曲线又叫贝兹曲线,在大学高数中一度让我非常头疼。前阵子练手写动画的时候,发现贝塞尔曲线可以应用于轨迹的绘制以及定义动画曲线。
本文就来探究一下,贝塞尔曲线到底是个什么样的存在。
贝塞尔曲线原理
贝塞尔曲线由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/bezier-curve/
实际应用
贝塞尔曲线在前端中主要有两方面的应用,一方面可以作为动画曲线应用于CSS3动画中;另一方面可以通过canvas来绘制曲线达到需要的效果。
CSS3中贝塞尔曲线的应用
在CSS3中,有两属性经常被用到:transition-timing-function
和animation-timing-function
,这两个分别代表了过渡的速度和动画的速度。CSS3为我们提供了一个新的工具——cubic-bezier(x1,y1,x2,y2)
。这个工具能够生成一个速度曲线,使我们的元素按照该曲线来调节速度。
在上面的推导中,我们知道在贝塞尔公式中,有两个点的位置恒定——P0和P1,cubic-bezier
中定义了两个控制点的位置,所以该曲线为三阶贝塞尔曲线。
有个网站可以方便我们快速建立一个贝塞尔曲线:cubic-bezier
贝塞尔曲线与动画曲线的关联
先来一波动图简单粗暴的感受一下: 例一:
例二:
例三:
左边的是贝塞尔曲线,横轴代表了事件,竖轴代表了进度,无法直观得感受出速度的变化。
右边的曲线是控制面板中的动画曲线,横轴是时间,竖轴是速度,可以方面地看出速度的变化。
上述例子中,以前进反向为速度正方向,后退方向为速度反方向。
如何得知速度的变化
推导
例一中,贝塞尔曲线为一条直线,当时间均匀变化时,进度也在均匀变大,由此可知速度恒定不变,时间和进度之间的关系可以用一个线性方程来表示:
代码语言:javascript复制y=ax b (a=1,b=0)
其中x为时间,y为进度,a即为速度。
推导案例一
从上面结论中启发,去观察其他贝塞尔曲线,
图中是一段变化的曲线,我们取其中一小段,将其看作稳定不变的一段直线,通过下面的线性方程来表示,并通过红线标注在图中:
代码语言:javascript复制y=ax b
根据初中数学的内容,我们知道,当a>1时,与x轴的夹角∈(45°,90°);当a∈(0,1)时,与x轴的夹角在(0,45°)之间。相同的时间内,与x轴的夹角越大,a越大,速度越快。
观察上图的夹角变化趋势,夹角逐渐变小趋向于0,而后逐渐变大,趋向于90°,对应速度应是速度逐渐变慢趋向于0,之后逐渐变快。
放上动画曲线以及动图来验证一下我们的推测:
推导案例二
下图中的曲线部分在第四象限,部分在第一象限,这时对应的动画曲线该如何推导呢。
同样将该曲线视为由n段平滑的直线构成,由线性方程来表示直线的趋势,可知速度a方向一开始为负,之后慢慢向正方靠近,a的速率也在由大变小,当为0时,再向正方慢慢变大。即该曲线表示元素一开始在朝反方向减速运动,当速度为0后,向正方向作加速运动。
通过动画曲线及动图来验证上述推导:
验证
用两个曲线来验证一下上面的结论:
曲线一:
曲线二:
从结果可以判断,用上述推导方法可以正确得出贝塞尔曲线与动画曲线之间的关系。
动画曲线的应用
了解了如何用贝塞尔曲线来指定动画曲线后,很多动画涉及到速度方面的效果就可以实现了,例如小车加速刹车,弹簧动画等速度轨迹都可以根据自己的需要来进行定制。
放上一个缓动函数速查网址,可以让自己的动效更加真实:缓动函数
放一个小例子:
该动画模拟了小球落下回弹的过程
代码如下:
代码语言:javascript复制 <div class="ground">
<div class="ball" id="ball"></div>
</div>
代码语言:javascript复制 .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;
}
@<span class="hljs-keyword">keyframes</span> move {
0% {
<span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
}
100% {
<span class="hljs-attribute">top</span>: <span class="hljs-number">90%</span>;
}
}
这类动画可以参考网上大大们的案例:
贝塞尔曲线与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 ★,转载请注明出处。