贝塞尔曲线在前端的应用
贝塞尔曲线介绍
贝塞尔曲线(Bezier Curve)在计算机图形领域应用非常广泛,比如我们熟知的 CSS 动画、 Canvas 以及 Photoshop 等都可以看到贝塞尔曲线的身影。
百度百科:https://baike.baidu.com/item/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF/1091769?fr=ge_ala
css中的时间函数
css3的transition和animation可以实现动画效果,二者都支持贝塞尔曲线。CSS动画过渡时间函数是三阶贝塞尔曲线。动过时间函数,我们在用transition和animation做动画时,可以控制从起点到终点之间的值随时间的变化,如线性变化,先快后满,等等。
CSS animation-timing-function 属性 https://www.w3school.com.cn/cssref/pr_animation-timing-function.asp
CSS transition-timing-function属性 https://www.w3school.com.cn/cssref/pr_transition-timing-function.asp
时间函数的一些预设值如下,也支持自定义值:
| 值 | 描述 |
|---|---|
| linear | 规定以相同速度开始至结束的过渡效果(等于 cubic-bezier(0,0,1,1))。 |
| ease | 规定慢速开始,然后变快,然后慢速结束的过渡效果(cubic-bezier(0.25,0.1,0.25,1))。 |
| ease-in | 规定以慢速开始的过渡效果(等于 cubic-bezier(0.42,0,1,1))。 |
| ease-out | 规定以慢速结束的过渡效果(等于 cubic-bezier(0,0,0.58,1))。 |
| ease-in-out | 规定以慢速开始和结束的过渡效果(等于 cubic-bezier(0.42,0,0.58,1))。 |
| cubic-bezier(n,n,n,n) | 在 cubic-bezier 函数中定义自己的值。可能的值是 0 至 1 之间的数值。 |
比如我们要实现dom元素从一个点p1到位置p2,就可以用transition来移动,移动的方向是直线的,但是移动的速度就可以由时间函数来控制。
1 | .box{ |
chrome浏览器中,有一个按钮点击可以实现自己拖拽生成合适的贝塞尔曲线。

codepen: https://codepen.io/ahao430/pen/gOJbOyg
tween.js补间动画
tween.js是一款简单易用的JavaScript补间动画库,它可以让Web开发者很方便地创建和控制复杂的动画效果。它的特点是功能全面、易于使用,支持各种类型的动画插值器和缓动函数,以及灵活的回调函数和参数调整。
tween.js文档:https://github.com/tweenjs/tween.js/blob/main/README_zh-CN.md
下面是tween.js的easing function的值:


刚刚说到的dom元素移动,也可以用tween.js来实现相同的效果。
1 | const box = document.getElementById('box') // Get the element we want to animate. |
只不过一般出于性能考虑,能用css实现的,就不用js来做。
codepen: https://codepen.io/ahao430/pen/RwmNNbG
应用示例
css实现大转盘抽奖动画
这里的实现思路是,直接用transition实现过渡,初始rotate角度是0,后面旋转超过1圈,角度可以超过360deg。然后用ease,或者ease-in-out,或者用chrome拖一个先加速再减速的贝塞尔曲线。
css实现购物车小球抛物线动画
这里要理解抛物线的实质,当我们水平或斜抛出一个物体,实际上可以分解为两个方向的运动。水平方向上x我们可以理解为匀速,这个时间函数是线性的。而竖直方向上,由于收到重力的作用,y实际上是一个向下的匀加速运动,当有初始向上的速度时,可以理解为是一个初始的负值,然后逐渐增大。
这样我们实际上可以包装两层div,一层做水平方向的线性运动,一层做竖直方向的一个加速运动。这样两层分别做直线运动,但是时间函数一个线性一个不断加速即可。
tween.js实现数字缓动
这个很简单,直接用tween.js做缓动计算,把数字实时展示就行了,这种一般展示人数变化之类的都是整数,可以取整。
tween.js实现九宫格抽奖动画

同样的,这个要用到tween.js, 这里css是实现不了的。九宫格抽奖的时候,外层的8个位置转圈圈,实际上类似大转盘的转圈,虽然视觉上是循环的,但是我们的角度一直在增加。这里同样的,这里要转N圈的话,让数字从0开始,到 8*N + 停止位置结束,用缓动函数变化,每次得到的值取整,再mod 8,得到动画的实时位置。