深入浅出 CSS 动画 (上)

简介: 深入浅出 CSS 动画 (上)

本文将比较全面细致的梳理一下 CSS 动画的方方面面,针对每个属性用法的讲解及进阶用法的示意,希望能成为一个比较好的从入门到进阶的教程。


CSS 动画介绍及语法



首先,我们来简单介绍一下 CSS 动画。


最新版本的 CSS 动画由规范 -- CSS Animations Level 1 定义。


CSS 动画用于实现元素从一个 CSS 样式配置转换到另一个 CSS 样式配置。

动画包括两个部分: 描述动画的样式规则和用于指定动画开始、结束以及中间点样式的关键帧。


简单来说,看下面的例子:


div {
    animation: change 3s;
}
@keyframes change {
    0% {
        color: #f00;
    }
    100% {
        color: #000;
    }
}
  1. animation: move 1s 部分就是动画的第一部分,用于描述动画的各个规则;
  2. @keyframes move {} 部分就是动画的第二部分,用于指定动画开始、结束以及中间点样式的关键帧;


一个 CSS 动画一定要由上述两部分组成。


CSS 动画的语法


接下来,我们简单看看 CSS 动画的语法。

创建动画序列,需要使用 animation 属性或其子属性,该属性允许配置动画时间、时长以及其他动画细节,但该属性不能配置动画的实际表现,动画的实际表现是由 @keyframes 规则实现。


animation 的子属性有:


  • animation-name:指定由 @keyframes 描述的关键帧名称。
  • animation-duration:设置动画一个周期的时长。
  • animation-delay:设置延时,即从元素加载完成之后到动画序列开始执行的这段时间。
  • animation-direction:设置动画在每次运行完后是反向运行还是重新回到开始位置重复运行。
  • animation-iteration-count:设置动画重复次数, 可以指定 infinite 无限次重复动画
  • animation-play-state:允许暂停和恢复动画。
  • animation-timing-function:设置动画速度, 即通过建立加速度曲线,设置动画在关键帧之间是如何变化。
  • animation-fill-mode:指定动画执行前后如何为目标元素应用样式
  • @keyframes 规则,当然,一个动画想要运行,还应该包括 @keyframes 规则,在内部设定动画关键帧

其中,对于一个动画:

  • 必须项:animation-name、animation-duration 和 @keyframes规则
  • 非必须项:animation-delay、animation-direction、animation-iteration-count、animation-play-state、animation-timing-function、animation-fill-mode,当然不是说它们不重要,只是不设置时,它们都有默认值


上面已经给了一个简单的 DEMO, 就用上述的 DEMO,看看结果:


e225aa952aaa439faa6c291acc70ed78_tplv-k3u1fbpfcp-zoom-1.gif


这就是一个最基本的 CSS 动画,本文将从 animation 的各个子属性入手,探究 CSS 动画的方方面面。


animation-name / animation-duration 详解


整体而言,单个的 animation-name 和 animation-duration 没有太多的技巧,非常好理解,放在一起。


首先介绍一下 animation-name,通过 animation-name,CSS 引擎将会找到对应的 @keyframes 规则。


8930285afabe45ad89b5e56565e23530_tplv-k3u1fbpfcp-zoom-1.png


当然,它和 CSS 规则命名一样,也存在一些骚操作。譬如,他是支持 emoji 表情的,所以代码中的 animation-name 命名也可以这样写:


div {
    animation: 😄 3s;
}
@keyframes 😄 {
    0% {
        color: #f00;
    }
    100% {
        color: #000;
    }
}


而 animation-duration 设置动画一个周期的时长,上述 DEMO 中,就是设定动画整体持续 3s,这个也非常好理解。


animation-delay 详解



animation-delay 就比较有意思了,它可以设置动画延时,即从元素加载完成之后到动画序列开始执行的这段时间。


简单的一个 DEMO:


<div></div>
<div></div>
div {
    width: 100px;
    height: 100px;
    background: #000;
    animation-name: move;
    animation-duration: 2s;
}
div:nth-child(2) {
    animation-delay: 1s;
}
@keyframes move {
    0% {
        transform: translate(0);
    }
    100% {
        transform: translate(200px);
    }
}


比较下列两个动画,一个添加了 animation-delay,一个没有,非常直观:


8ab1f76e162e4583b99d8026d0808502_tplv-k3u1fbpfcp-zoom-1.gif



上述第二个 div,关于 animation 属性,也可以简写为 animation: move 2s 1s,第一个时间值表示持续时间,第二个时间值表示延迟时间。


animation-delay 可以为负值


关于 animation-delay,最有意思的技巧在于,它可以是负数。也就是说,虽然属性名是动画延迟时间,但是运用了负数之后,动画可以提前进行。


假设我们要实现这样一个 loading 动画效果:


260758ade5c649e8bbb893318cb52e22_tplv-k3u1fbpfcp-zoom-1.gif


有几种思路:


  1. 初始 3 个球的位置就是间隔 120°,同时开始旋转,但是这样代码量会稍微多一点
  2. 另外一种思路,同一个动画,3 个元素的其中两个延迟整个动画的 1/3,2/3 时间出发


方案 2 的核心伪代码如下:


.item:nth-child(1) {
    animation: rotate 3s infinite linear;
}
.item:nth-child(2) {
    animation: rotate 3s infinite 1s linear;
}
.item:nth-child(3) {
    animation: rotate 3s infinite 2s linear;
}


但是,在动画的前 2s,另外两个元素是不会动的,只有 2s 过后,整个动画才是我们想要的:

20f1e77b073249c8a74866448a2589fe_tplv-k3u1fbpfcp-zoom-1.gif


此时,我们可以让第 2、3 个元素的延迟时间,改为负值,这样可以让动画延迟进行 -1s、-2s,也就是提前进行 1s、2s:


.item:nth-child(1) {
    animation: rotate 3s infinite linear;
}
.item:nth-child(2) {
    animation: rotate 3s infinite -1s linear;
}
.item:nth-child(3) {
    animation: rotate 3s infinite -2s linear;
}


这样,每个元素都无需等待,直接就是运动状态中的,并且元素间隔位置是我们想要的结果:


137946058-cd27fdc0-45a6-4710-a5bd-f81a9ee77bd4.gif


利用 animation-duration 和 animation-delay 构建随机效果


还有一个有意思的小技巧。


同一个动画,我们利用一定范围内随机的 animation-duration 和一定范围内随机的 animation-delay,可以有效的构建更为随机的动画效果,让动画更加的自然。

我在下述两个纯 CSS 动画中,都使用了这样的技巧:


  1. 纯 CSS 实现华为充电动画

75ef362be0a24c259c56ffd3ce788a7f_tplv-k3u1fbpfcp-zoom-1.gif


纯 CSS 实现火焰动画:


20971446fdd349b1bcee8185d1a33721_tplv-k3u1fbpfcp-zoom-1.gif


以纯 CSS 实现华为充电动画为例子,简单讲解一下。


仔细观察这一部分,上升的一个一个圆球,抛去这里的一些融合效果,只关注不断上升的圆球,看着像是没有什么规律可言:

db64f395adec42ddbfb04dfc01c23ad8_tplv-k3u1fbpfcp-zoom-1.gif

我们来模拟一下,如果是使用 10 个 animation-duration 和 animation-delay 都一致的圆的话,核心伪代码:


<ul>
    <li></li>
    <!--共 10 个...--> 
    <li></li>
</ul>
ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 5px;
}
li {
    background: #000;
    animation: move 3s infinite 1s linear;
}
@keyframes move {
    0% {
        transform: translate(0, 0);
    }
    100% {
        transform: translate(0, -100px);
    }
}


这样,小球的运动会是这样的整齐划一:


f62a1fb306e74263a0c495247909f4e4_tplv-k3u1fbpfcp-zoom-1.gif

要让小球的运动显得非常的随机,只需要让 animation-duration 和 animation-delay 都在一定范围内浮动即可,改造下 CSS:


@for $i from 1 to 11 {
    li:nth-child(#{$i}) {
        animation-duration: #{random(2000)/1000 + 2}s;
        animation-delay: #{random(1000)/1000 + 1}s;
    }
}


我们利用 SASS 的循环和 random() 函数,让 animation-duration 在 2-4 秒范围内随机,让 animation-delay 在 1-2 秒范围内随机,这样,我们就可以得到非常自然且不同的上升动画效果,基本不会出现重复的画面,很好的模拟了随机效果:


138098999-aa157e82-6058-4377-94d3-ad5324d3b136.gif


CodePen Demo -- 利用范围随机 animation-duration 和 animation-delay 实现随机动画效果


animation-timing-function 缓动函数



缓动函数在动画中非常重要,它定义了动画在每一动画周期中执行的节奏。

缓动主要分为两类:


  1. cubic-bezier-timing-function 三次贝塞尔曲线缓动函数
  2. step-timing-function 步骤缓动函数(这个翻译是我自己翻的,可能有点奇怪)


三次贝塞尔曲线缓动函数


首先先看看三次贝塞尔曲线缓动函。在 CSS 中,支持一些缓动函数关键字。

/* Keyword values */
animation-timing-function: ease;  // 动画以低速开始,然后加快,在结束前变慢
animation-timing-function: ease-in;  // 动画以低速开始
animation-timing-function: ease-out; // 动画以低速结束
animation-timing-function: ease-in-out; // 动画以低速开始和结束
animation-timing-function: linear; // 匀速,动画从头到尾的速度是相同的

e8a88ee5ec99483fbc7e63de45e75c3b_tplv-k3u1fbpfcp-zoom-1.png


关于它们之间的效果对比:


aa0947cb563943489df21e412d50aad6_tplv-k3u1fbpfcp-zoom-1.gif


除了 CSS 支持的这 5 个关键字,我们还可以使用 cubic-bezier() 方法自定义三次贝塞尔曲线:


animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);


这里有个非常好用的网站 -- cubic-bezier 用于创建和调试生成不同的贝塞尔曲线参数。


三次贝塞尔曲线缓动对动画的影响


关于缓动函数对动画的影响,这里有一个非常好的示例。这里我们使用了纯 CSS 实现了一个钟的效果,对于其中的动画的运动,如果是 animation-timing-function: linear,效果如下:

146766119-1098b124-7dfe-4f80-8e4d-1daa2d743e52.gif


而如果我们我把缓动函数替换一下,变成 animation-timing-function: cubic-bezier(1,-0.21,.85,1.29),它的曲线对应如下:


d192a0618e0345cbbfe1fabfafd281e9_tplv-k3u1fbpfcp-zoom-1.png



整个钟的动画律动效果将变成这样,完全不一样的感觉:


146766093-2bc11c92-5a9e-4633-8e2a-5abd199e7db2.gif

CodePen Demo - 缓动不同效果不同


对于许多精益求精的动画,在设计中其实都考虑到了缓动函数。我很久之前看到过一篇《基于物理学的动画用户体验设计》,可惜如今已经无法找到原文。其中传达出的一些概念是,动画的设计依据实际在生活中的表现去考量。


譬如 linear 这个缓动,实际应用于某些动画中会显得很不自然,因为由于空气阻力的存在,程序模拟的匀速直线运动在现实生活中是很难实现的。因此对于这样一个用户平时很少感知到的运动是很难建立信任感的。这样的匀速直线运动也是我们在进行动效设计时需要极力避免的。

目录
相关文章
|
1月前
|
机器学习/深度学习 前端开发 JavaScript
|
3月前
|
前端开发
2s 利用 HTML+css动画实现企业官网效果
2s 利用 HTML+css动画实现企业官网效果
|
26天前
|
前端开发 搜索推荐 UED
实现 CSS 动画效果的兼容性
【10月更文挑战第16天】实现 CSS 动画效果的兼容性需要对不同浏览器的特性有深入的了解,并采取适当的策略和方法。通过不断的实践和优化,你可以在各种浏览器上创造出流畅、美观且兼容的动画效果,为用户带来更好的体验。在实际开发中,要密切关注浏览器的发展动态,及时掌握最新的兼容性技巧和解决方案,以确保你的动画设计能够在广泛的用户群体中得到良好的呈现。
103 58
|
5天前
|
Web App开发 前端开发 JavaScript
如何在不牺牲动画效果的前提下,优化 CSS3 动画的性能?
如何在不牺牲动画效果的前提下,优化 CSS3 动画的性能?
18 1
|
1月前
|
前端开发 JavaScript API
探索 CSS Houdini:轻松构建酷炫的 3D 卡片翻转动画
本文通过构建一个 3D 翻卡动画深入探讨了 CSS Houdini 的强大功能,展示了如何通过 Worklets、自定义属性、Paint API 等扩展 CSS 的能力,实现高度灵活的动画效果。文章首先介绍了 Houdini 的核心概念与 API,并通过构建一个动态星空背景、圆形进度条以及交互式 3D 翻卡动画的实际示例,展示了如何利用 CSS Houdini 赋予网页设计更多创造力。最后,还演示了如何将这种 3D 翻卡效果集成到公司网站中,提升用户体验。CSS Houdini 的创新能力为网页设计带来了前所未有的灵活性,推动了前端开发迈向新的高度。
26 0
探索 CSS Houdini:轻松构建酷炫的 3D 卡片翻转动画
|
2月前
|
JavaScript 前端开发
JS配合CSS3实现动画和拖动小星星小Demo
本文通过代码示例展示了如何使用JavaScript和CSS3实现动画效果和拖动小星星的交互效果,包括文字掉落动画和鼠标拖动产生小星星动画的实现方法。
46 0
JS配合CSS3实现动画和拖动小星星小Demo
|
1月前
|
前端开发
CSS 动画介绍及语法
CSS 动画介绍及语法
27 0
|
3月前
|
前端开发 UED 开发者
有趣的CSS - 文字加载动画效果
这个文本加载动画简单而有趣,可以在网站标题、广告标语或者关键信息的展示上吸引用户的注意力。开发者可以根据需要调整动画的持续时间、步骤数,或者光标颜色等,来适应特定的设计需求。使用这种动态元素,增强网站的互动性和用户体验,同时也为网站增添了一抹活泼的风格。
80 5
|
3月前
|
前端开发 JavaScript
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
|
3月前
|
前端开发
CSS动画霓虹灯闪烁效果
CSS动画霓虹灯闪烁效果