CSS如何实现弹簧动画效果

这篇文章的思路以及文章中所涉及到的数学公式都来自于@Thai Pangsakulyanont分享的《Spring Animation in CSS》一文。

CSS Animation在Web Animation中已不是新技术,不过在制作动画的时候,或许常常纠结timing-function如何使用。一般情况之下,都会使用animation-timing-function/transition-timing-function自带的几个关键词动画函数。稍为熟悉Web Animation的同学可能会使用cubic-bezier.com帮助自己创建一些timing-function。往往这一切都只是局限于使用,而不知道其原理究竟是什么。

另外,使用这些基本的timing-function几乎是无法模拟出一个真实弹跳(类似弹簧弹性)的动画效果。

其实,事实并不是如此。为什么这么说呢?在制作动画过程中,数学可能帮我们做很多更有意义的事情,比如说借助数学微积分的一些原理就可以让我们制作出更真实的动画效果。就比如说弹簧弹跳动效。那么这篇文章讲的就是这样的内容,如果你感兴趣欢迎继续往下阅读。

首先来看一个动画效果的示例:

上面动画示例来自于@dtinth写的案例。只不过这里将作者的Stylus换成了Sass。

话说这些数学公式都是来自于@Thai Pangsakulyanont分享的《Spring Animation in CSS》一文。而且自己离开学校有近二十年,很多知识都还给了老师,如果文章有不对之处,还请大家多多指正。

为什么选择CSS Animation

这是一个亘古不变的话题,其实没有啥好纠结的。对于一位在JavaScript方面啥都不懂的同学而言,他往往追过的是如何将动画效果能通过CSS完成,而且达到近似JavaScript方面的效果(虽然这几乎是不太可能,但往往很多时候是不会相关很远)。那么抛开这些而言,我们从技术角度出发,目前实现Web Animation有很多优秀的库,比如React-motionVelocity.jsGSAP。但它们都有一个问题:JavaScript访问DOM都是单线程。而使用CSS Animation没有这一问题存在。

Tweening的基础知识

来看一个简单的动画,比如将一个盒子从left:100px推到left:200px

这意味着,随着时间的推移,在100px200px之间不要停。

当动画执行时,我希望覆盖的面是减小100px(从100%0%),与此同时,覆盖的而增加到200px(从0%100%)。

处理动画到200px有一个过程,我们把这个过程简称为p,通过p使用使用下面的公式,可以计算出每个时间段left的值:

$$left: (1-p)(100px)+p(200px)$$

下面这张图解释了它是如何工作的:

CSS Animation中的一些数学计算

来概括一下,如果动画要从A过渡到B,而运动进展是p,那么他的属性值将是:

$$(1-p)A+pB$$

有些同学可能喜欢写成这样:

$$A+p(B-A)$$

把这个称之为lerp或者linear interpolation(线性插值)。

虽然把这个称为线性,但现实世界的动画并不是线性的。例如,你可能希望动画开始是缓慢的,而快要结束时速度是快速的(相当于物体做加速度)。在动画播放中可以使用一个缓动函数(easing function),但这样处理过程和时间就不是线性操作。

而缓动函数主要是用来创建时间和动画发展之间的关系。

缓动函数指定动画效果在执行时的速度,使其看起来更加真实。现实物体照着一定节奏移动,并不是一开始就移动很快的。当我们打开抽屉时,首先会让它加速,然后慢下来。当某个东西往下掉时,首先是越掉越快,撞到地上后回弹,最终才又碰触地板。——easing function

注:mj.js官网对easing function做了很详细的阐述。

物理(Physics)

下面一个弹簧块,假设在它不动的时候位置是x = 1:

物理

现在你推了一下弹簧,它的位置为成了x = 0:

物理

剩余70%内容付费后可查看
* 请输入阅读码(忘记阅读码?

如需转载,烦请注明出处:https://www.w3cplus.com/animation/spring-animation-in-css.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部