难题

给过渡和动画加上缓动效果是一种常见的手法(比如具有回弹效果的过渡过程)是一种流行的表现手法,可以让界面显得更加生动和真实:在现实世界中,物体A点到B点往往也是不完全匀速的

以纯技术的角度来看,回弹效果是指当一个过渡达到最终值时,往回到一点,然后再次回到最终值,如此往复一次或者多次,并逐渐收敛,最终稳定在最终值。有相当的多JavaScript类库可以创建动画,且内置回弹效果等其他缓动效果。但是眼下,我们其实已经不需要借助脚本来实现过渡和动画了。不过,在CSS中实现回弹效果的最佳方式是什么呢?

弹跳动画

我们的第一感觉可能就是使用css动画,并且设置如下关键帧:

@keyframes bounce{
60%,80%,to{transform:translateY(350px);}
70%{transform:translateY(250px);}
90%{transform:translateY(300px);}
}

相信我们都做过这样的事,但是我们跑一遍这个动画,会发现它显示的及其不真实,主要原因在于,每当这个小球方向改变时,她得移动过程都是持续加速的,这看起来很不自然。原因其实就是因为它的调速函数在关键帧的衔接都是一样的

所有的过渡和动画之间都是跟一条曲线有关的,这条曲线指定了动画过程在整段时间中是如何推进的

如果不指定调速函数,就是得到一个默认值。但是这个默认值并不是我们想象中的匀速效果,而是:

注意,当时间进行到一半时,这个过渡已经推进到80%.

说到调速函数,我们很自然联系到了css内置的缓动曲线和贝塞尔曲线。

不论是在animation/transition简写属性中,还是在animation-timing-function/transition-timing-function展开属性中,你都可以把这个默认的调速函数显示指定ease关键字。除了ease外,还有四种内置的缓动曲线,你可以借助他们来改变动画的推进方式

从上面四个图中,我们很直观的看出,ease-outease-in的反向版本。而这一对组合正是实现回弹效果所需要的:每当小球的运动方向相反时,我们希望调速函数也是相反的。我们希望小球下落是加速的(ease-out),而弹起向上是减速的(ease-in):

@keyframes bounce{
60%,80%,to{
transform:translateY(400px);
animation-timing-function:ease-out;
}
70%{transform:translateY(300px);}
90%{transform:translateY(360px);}
}
.ball{
animation:bounce 3s ease-in;
}

虽然我们改动不大,但是已经发现回弹效果变得真实起来。不过显然这五种内置的缓动曲线是不够用的,假如我们这个回弹效果是用来模拟自由落体的,那么我们需要一个更高的加速度和ease的反向版本,又如何得到呢?

其实所有的这五种曲线都是通过(三次)贝塞尔曲线来指定的,而CSS的调速函数都是只有一个片段的贝塞尔曲线,每个函数也只有两个控制锚点,CSS就提供了一个cubic-bezier()函数,允许我们指定自定义调速函数。他接受四个参数,分别是两个控制锚点的坐标值,

cubic-bezier(x1,y1,x2,y2),曲线的两个端点固定在(0,0)和(1,1)之间,前者是整个过渡的起点(时间进度0%,动画进度0%)而后者是整个过渡的终点(时间进度100%,动画进度100%)。

举例来说,ease等同于cubic-bezier(.25,.1,.25,1),因此它的反向版本就是cubic-bezier(.1,.25,1,.25)

@keyframes bounce{
60%,80%,to{
transform:translateY(400px);
animation-timing-function:ease;
}
70%{
transform:translateY(300PX);
}
90%{
transform:translateY(160px);
}
} .ball{
animation:bounce 3s cubic-bezier(.1,.25,1,.25);
}

codepen中查看效果

See the Pen css-animation-easing by okaychen (@okaychen) on CodePen.

我们可以借助cubic-bezier.com的图形化工具,进行反复尝试和优化,从而进一步改写这个回弹动画.

最后

经过以上这些知识的学习储备和练习,相信我们已经可以做出很棒的弹跳动画了.

我们在文章开始放了一个小球弹跳的gif图效果,那么就让我们真真正正的动手来写一下吧!

codepen中查看效果

See the Pen css-animation-easing-practice by okaychen (@okaychen) on CodePen.

弹性过渡

假设我们有一个文本输入框,每当它被聚焦时,都需要展示一个提示框

我们有如下结构:

    <label>
Your username:<input id="username" />
<span class="callout">Only letters,numbers,usrescore(_) and hyphens (-) allowed!</span>
</label>

每当用户聚焦这个文本输入框时,都会有一个半秒钟的过渡,可能我们会完成这样的代码

input:not(:focus) + .callout{
transform:scale(0);
}
.callout{
transition:.5s transform;
transition-origin:1.4em -.4em;
}

这个过渡没有任何问题,但是我们希望它在结尾时能在夸张一点话,显得更加自然生动,我们可能会把这个过渡改为一个动画,然后用上面提到的缓动曲线

@keyframes elastic-grow{
from{transform:scale(0);}
70% {
transform:scale(1.1);
animation-timing-function:cubic-bezier(.1,.25,1,.25); /*反向的ease*/
}
} input:not(:focus) + .callout{ transform:scale(0); } input:focus + .callout{ animation:elastic-grow .5s; } .callout{ transform-origin:1.4em -.4em; }

添加了这个动画之后,确实发挥了作用。不过这里我们其实只是需要一个过渡而已,而我们本质上却使用了一个动画,显得有些大材小用,有一种杀鸡用牛刀的感觉,我们如何只用过渡完成这个效果呢?

这里我们就用到了上面说起的调速函数cubic-bezier(),在这个例子中,我们希望调速函数先到达110%的程度(相当于scale(1.1)),然后在过渡回100%,我们把控制锚点向上移,

这个自定义调速函数在垂直坐标上已经超出0~1的区间,最终又回到1,在70%的时间点到达了110%的变形程度的高峰,然后继续用剩下30%的时间回到它的最终值

整个过渡的推进,非常接近前面的动画方案,但他仅需要一行代码就可以实现整个效果

input:not(:focus) + .callout{ transform:scale(0) }

.callout{
transform-origin:1.4em -.4em;
transition:.5s cubic-bezier(.25,.1,.3,1.5);
}

but,wait...当提示框收缩时,左下角出现的是什么?其实,当我们把焦点从输入框切出去的时候,所触发的过渡会以scale(1)作为起始值,并以scale(0)作为最终值,这个过渡仍然会在350ms后到达110%的变形程度。只不过在这里,110%的变形程度的解析结果并不是scale(1.1),而是scale(-0.1)

我们可以定义关闭状态的css规则(假如我们指定普通的ease调速函数)把当前的调速函数覆盖掉

input:not(:focus) + .callout{
transform:scale(0);
transition-timing-function:ease; /*覆盖cubic-bezier*/
} .callout{
transform-origin:1.4em -.4em;
transition:.5s cubic-bezier(.25,.1,.3,1.5);
}

再试一试,发现已经关闭提示框已经恢复到我们设置cubic-bezier()之前的样子了,

但是其实我们仔细观察发现另一个问题:提示框的关闭动作明显要迟钝一些。我们细细想来发现,在提示框展开过程中,当时间为50%(250ms)时,它就已经到达100%的尺寸效果了。但是在收缩过程中,从0%~100%的变化会花费我们为过渡所指定的素有时间(500ms),因此感觉会慢上一般

然后我们会想到同时覆盖过渡的持续时间:可以用transition-duration这一属性,也可以用transition这个简写属性来覆盖所有值,如果选择后者的话就不需要指定ease了,因为他本来就是transition的初始值:

input:not(:focus) + .callout{
transform:scale(0);
transition:.25s;
} .callout{
transform-origin:1.4em -.4em;
transition:.5s cubic-bezier(.25,.1,.3,1.5);
}

codepen中查看效果

See the Pen css-animation-task by okaychen (@okaychen) on CodePen.

最后

虽然弹性过渡在很多过渡中都可以收到不错的效果,但是某些时候他产生的效果可能相当糟糕。典型的反面案例出现在对颜色属性的弹性过渡中。尽管颜色发生弹性过渡可能非常有趣,但这种效果在UI场景中通常是不合适的.

为了避免不小心对颜色设置了弹性过渡,可以尝试把过渡的作用范围限制在某几种特定的属性上,transition不指定时,transition-property就会得到它的初始值:all,这意味着只要是过渡的属性都会参与过渡。我们可以在transition中设置transform

input:not(:focus){
transform:scale(0);
transition:.25s transform;
} .callout{
transition-origin:1.4em -.4em;
transform:.5s cubic-bezier(.25,.1,.3,1.5) transform;
}

参考资料

过渡与动画 - 缓动效果&基于贝塞尔曲线的调速函数的更多相关文章

  1. window.requestAnimationFrame与Tween.js配合使用实现动画缓动效果

    window.requestAnimationFrame 概述 window.requestAnimationFrame()这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数,以满足开发者操作 ...

  2. 过渡与动画 - steps调速函数&CSS值与单位之ch

    写在前面 上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果. 但是如果我们想要实现逐帧动画,基于贝塞尔曲线的调速函数就显得有些无能为力了,因为我们并不需要帧与帧之间的过 ...

  3. 过渡与动画 - 逐帧动画&steps调速函数

    写在前面 上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果. 但是如果我们想要实现逐帧动画,基于贝塞尔曲线的调速函数就显得有些无能为力了,因为我们并不需要帧与帧之间的过 ...

  4. Adobe Edge Animate –弹性的方块-使用tweenmax缓动效果

    Adobe Edge Animate –弹性的方块-使用tweenmax缓动效果 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. 此前有Edge爱好者提出一 ...

  5. 【WPF学习】第五十一章 动画缓动

    线性动画的一个缺点是,它通常让人觉得很机械且不能够自然.相比而言,高级的用户界面具有模拟真实世界系统的动画效果.例如,可能使用具有触觉的下压按钮,当单击时按钮快速弹回,但是当没有进行操作时它们会慢慢地 ...

  6. javascript的缓动效果

    这部分对原先的缓动函数进行抽象化,并结合缓动公式进行强化.成品的效果非常惊人逆天.走过路过不要错过. 好了,打诨到此为止.普通的加速减速是难以让人满意的,为了实现弹簧等让人眼花缭乱的效果必须动用缓动公 ...

  7. 重新想象 Windows 8 Store Apps (19) - 动画: 线性动画, 关键帧动画, 缓动动画

    原文:重新想象 Windows 8 Store Apps (19) - 动画: 线性动画, 关键帧动画, 缓动动画 [源码下载] 重新想象 Windows 8 Store Apps (19) - 动画 ...

  8. 软件项目技术点(1)——Tween算法及缓动效果

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 Tween算法及缓动效果 软件里在切换步序时需要有过渡动画效果,从当前位置的画面缓动到目标位置的画面.动画效果可重新查看文章系列第一篇 ...

  9. 背水一战 Windows 10 (15) - 动画: 缓动动画

    [源码下载] 背水一战 Windows 10 (15) - 动画: 缓动动画 作者:webabcd 介绍背水一战 Windows 10 之 动画 缓动动画 - easing 示例演示缓动(easing ...

随机推荐

  1. 记录定时任务的一个错误:crontab 中使用"%"的问题

    最近工作需要,需要定时执行命令文件,并且把执行的日志重定向输出到以日期命名的文件中,命令如下: /bin/bash /data/shell/merge.sh &>> /data/s ...

  2. Android、IOS文字居中偏离的解决方案

    前言 移动端开发,经常会遇到的问题,就是文字居中.一般都只能往css方向去fix这个问题. 自己以前也用过position:relative;top:-*px的方式去解决.

  3. 【第二篇】SAP ABAP7.5x新语法之OPEN SQL

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:SAP ABAP7.5x系列之OPEN SQL ...

  4. input子系统事件处理层(evdev)的环形缓冲区【转】

    在事件处理层(evdev.c)中结构体evdev_client定义了一个环形缓冲区(circular buffer),其原理是用数组的方式实现了一个先进先出的循环队列(circular queue), ...

  5. python socket 套接字编程 单进程服务器 实现多客户端访问

    服务器: import socket #单进程服务器 实现多客户端访问 IO复用 #吧所有的客户端套接字 放在一个列表里面,一次又一次的便利过滤 server = socket.socket(sock ...

  6. 使用Jenkins+gitlab自动化构建时排除分支

    我们的目的是gitlab上的代码有变动时会自动向Jenkins发送web钩子请求,触发指定的动作: 但默认情况下,所有分支(如测试环境和预生产)的代码有变动时都会触发,此时可以在Jenkins的项目设 ...

  7. January 29th, 2018 Week 05th Monday

    Losing all hope was freedom. 彻底绝望就是真正的自由. Losing all the hopes, and we are free to challenge everyth ...

  8. Unity3d粒子系统详解

  9. 简易 Token 验证的实现

    简易 Token 验证的实现 前言 在我们的服务器和客户端的交互中,由于我们的业务中使用 RESTful API 的形式和客户端交互,而 API 又是无状态的,无法帮助我们识别这一次和上一次的请求由谁 ...

  10. <20180927>新开一篇章记录常用到的IT名词

    (一)有些名词在市场化的今天用的很多,和IT的名词重叠和易混淆, 有些缩写根本连外国人都很少用, 国人却用的津津乐道.这篇是专门用来记录的. 1.1 SMB , 这个在IT领域用的很多, 阐述的是 “ ...