Skip to content

缓动效果

用处

对几乎所有类型的过渡动画来说,它都可以显著增强动画的体验

  • 尺寸变化,如 :hover 时变大,弹出框弹出时等
  • 角度变化,如元素的旋转动作,饼图从 0 过渡到实际大小等

弹跳动画

第一想法是使用 CSS 动画

css
@keyframes bounce {
    60%, 80%, to { transform: translateY(200px); }
    70% { transform: translateY(100px) }
    90% { transform: translateY(130px) }
}
.box {
    animation: bounce 3s;
}

但如动画一样,效果并不好,这是因为动画的调速与弹跳运动的加速度不一致,下面是各个调速函数 animation-timing-function(默认值是 ease

按物理认知,在下降过程中,加速度是逐渐增加的(ease-in);在上升过程中,加速度是逐渐减少的(ease-out

css
@keyframes bounce {
    60%, 80%, to { 
        transform: translateY(200px); 
        animation-timing-function: ease-out;
    }
    70% { transform: translateY(100px) }
    90% { transform: translateY(130px) }
}
.box {
    animation: bounce 3s ease-in;
}

效果好了很多,但还没达到完美,所以我们需要使用自定义调速函数,cubic-bezier(x1, y1, x2, y2),如下图,紫粉色的是 (x1, y1),青蓝色的是 (x2, y2)。但调到想要的函数比较困难,可以通过下面网站调节

可视化界面

css
/* 这里使用 animate.css 库的函数,效果会好很多 */
@keyframes bounce {
    60%, 80%, to { 
        transform: translateY(200px); 
        animation-timing-function: cubic-bezier(.215,.61,.355,1);
    }
    70% { transform: translateY(100px) }
    90% { transform: translateY(130px) }
}
.box {
    animation: bounce 3s cubic-bezier(.755,.05,.855,.06);
}

弹性过渡

初始效果:文本输入框被聚焦时,弹出一个提示框

html
<label>
    用户名:
    <input type="text">
    <span>用户名已存在</span>
</label>
css
input:not(:focus) + span {
    transform: scale(0);
}
label span {
    transition: transform .3s;
    transform-origin: 10px -7px;
}

如何使动画更生动?比如说,先扩大到 110%,再缩回 100%,当然可以把过渡改成动画,但是否有更简单的方法呢?

css
/* 把过渡改成动画 */
@keyframes elastic {
    from { transform: scale(0); }
    70% { transform: scale(1.1); }
}

其实 cubic-bezier() 就可以做到,正常来说描点应该是再 [0, 1]x 轴上确时只能在这个区间变化,但 y 轴却是可以突破这个区间的,从而使其经历一个比最终值更大的状态

但注意,收缩回去的时候,同样会过度,出现如下的情况,所以应该这样写

css
input:not(:focus) + span {
    transform: scale(0);
    transition-timing-function: ease; /* 回缩时用正常的调速函数 */
}
label span {
    transition: transform .3s cubic-bezier(.25,.1,.3,1.5);
    transform-origin: 10px -7px;
}