引言

在web应用中,前端同学在实现动画效果时往往常用的几种方案:

  1. css3 transition / animation - 实现过渡动画
  2. setInterval / setTimeout - 通过设置一个间隔时间来不断的改变图像的位置
  3. requestAnimationFrame - 通过一个回调函数来改变图像位置,由系统来决定这个回调函数的执行时机,比定时修改的性能更好,不存在失帧现象

在大多数需求中,css3的 transition / animation 都能满足我们的需求,并且相对于js实现,可以大大提升我们的开发效率,降低开发成本。

本篇文章将着重对 animation 的使用做个总结,如果你的工作中动画需求较多,相信本篇文章能够让你有所收获:

  • Animation 常用动画属性
  • Animation 实现不间断播报
  • Animation 实现回弹效果
  • Animation 实现直播点赞效果 ️
  • Animation 与 Svg 又会擦出怎样的火花呢?
    1. Loading 组件
    2. 进度条组件
  • Animation steps() 运用
    1. 实现打字效果
    2. 绘制帧动画

Animation 常用动画属性 参考资料

介绍完 animation 常用属性,为了将这些属性更好地理解与运用,下面将手把手实现一些DEMO具体讲述

Animation 实现不间断播报 Online Code

通过修改内容在父元素中的y轴的位置来实现广播效果

@keyframes scroll {
0%{
transform: translate(0, 0);
}
100%{
transform: translate(0, -$height);
}
} .ul {
animation-name: scroll;
animation-duration: 5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}

此处为了保存广播滚动效果的连贯性,防止滚动到最后一帧时没有内容,需要多添加一条重复数据进行填充

<div class="ul">
<div class="li">小刘同学加入了凹凸实验室</div>
<div class="li">小邓同学加入了凹凸实验室</div>
<div class="li">小李同学加入了凹凸实验室</div>
<div class="li">小王同学加入了凹凸实验室</div>
<div class="li">小刘同学加入了凹凸实验室</div>
</div>

Animation 实现回弹效果 Online Code

通过将过渡动画拆分为多个阶段,每个阶段的top属性停留在不同的位置来实现

@keyframes animation {
0% {
top: -100%;
opacity: 0;
}
25% {
top: 60%;
opacity: 1;
}
50% {
top: 48%;
opacity: 1;
}
75% {
top: 52%;
opacity: 1;
}
100% {
top: 50%;
opacity: 1;
}
}

为了让过渡效果更自然,这里通过 cubic-bezier() 函数定义一个贝塞尔曲线来控制动画播放速度

过渡动画执行完后,为了将让元素应用动画最后一帧的属性值,我们需要使用 animation-fill-mode: forwards

.popup {
animation-name: animate;
animation-duration: 0.5s;
animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
animation-iteration-count: 1;
animation-fill-mode: forwards;
}

Animation 实现点赞效果 Online Code

相信大多数同学都知道点赞效果,本文章会实现一个简易版的点赞效果,主要讲述一下实现思路:

1.为了让气泡可以向上偏移,我们需要先实现一个y轴方向上移动的 @keyframes 动画

@keyframes animation-y {
0%{
transform: translate(-50%, 100px) scale(0);
}
50%{
transform: translate(-50%, -100px) scale(1.5);
}
100%{
transform: translate(-50%, -300px) scale(1.5);
}
}

2.为了让气泡向上偏移时显得不太单调,我们可以再实现一个x轴方向上移动的 @keyframes 动画

@keyframes animation-x {
0%{
margin-left: 0px;
}
25%{
margin-left: 25px;
}
75%{
margin-left: -25px;
}
100%{
margin-left: 0px;
}
}

这里我理解:

  • 虽然是修改 margin 来改变x轴偏移距离,但实际上与修改 transform没有太大的性能差异
  • 因为通过 @keyframes animation-y 中的 transform 已经新建了一个渲染层 ( PaintLayers )
  • animation 属性 可以让该渲染层提升至 合成层(Compositing Layers) 拥有单独的图形层 ( GraphicsLayer ),即开启了硬件加速 ,不会影响其他渲染层的 paint、layout
  • 如下图所示:

如笔者这里理解有误,还请读者大佬指出,感激不尽~

3.给气泡应用上我们所实现的两个 @keyframes 动画

.bubble {
animation: animation-x 3s -2s linear infinite,animation-y 4s 0s linear 1;
}

4.在点赞事件中,通过 js 操作动态添加/移除气泡元素

function like() {
const likeDom = document.createElement('div');
likeDom.className = 'bubble';
document.body.appendChild(likeDom);
setTimeout( () => {
document.body.removeChild(likeDom);
}, 4000)
}

Animation 与 Svg 绘制 loading/进度条 组件 Online Code

1.首先,我们使用 svg 绘制一个圆周长为2 * 25 * PI = 157 的圆

<svg with='200' height='200' viewBox="0 0 100 100"  >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke="#0079f5" ></circie>
</svg>

2.将实线圆绘制成虚线圆,这里需要用 stoke-dasharray:50, 50 (可简写为50) 属性来绘制虚线, stoke-dasharray 参考资料

  • 它的值是一个数列,数与数之间用逗号或者空白隔开,指定短划线(50px)缺口(50px)的长度。
  • 由于50(短划线) + 50(缺口) + 50(段划线) = 150, 150 < 157,无法绘制出完整的圆,所以会导致右边存在缺口(7px)
<svg with='200' height='200' viewBox="0 0 100 100"  >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke-dasharray="50" stroke="#0079f5" ></circie>
</svg>

3.stroke-dashoffset 属性可以使圆的短划线和缺口产生偏移,添加 @keyframes 动画后能够实现从无到有的效果,stoke-dashoffset参考资料

  • 设置 stroke-dasharray="157 157",指定 短划线(157px)缺口(157px) 的长度。
  • 添加 @keyframes 动画 修改stroke-dashoffset值, 值为正数逆时针偏移,, 值为负数时,顺时针偏移
@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -157;
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}

4.修改短划线和缺口值

  • 为了让 loading 组件线条可见,我们需要一个50px的短划线,设置 stroke-dasharray="50"
  • 为了让短划线发生偏移后可以完全消失,缺口需要大于或等于圆周长157,设置 stroke-dasharray="50 157"
  • 添加 @keyframes 动画,为了让动画结束时仍处理动画开始位置,需要修改 stroke-dashoffset:-207(短划线+缺口长度)
  • 进度条也是类似原理,帮助理解 stroke-dashoffset 属性,具体实现请查看示例
@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -207;
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}

Animation steps()运用

steps()animation-timing-function 的属性值

animation-timing-function : steps(number[, end | start])
  • steps 函数指定了一个阶跃函数,它接受两个参数
  • 第一个参数接受一个整数值,表示两个关键帧之间分几步完成
  • 第二个参数有两个值 start or end。默认值为 end
  • step-start 等同于 step(1, start)。step-end 等同于 step(1, end)

steps 适用于关键帧动画,第一个参数将两个关键帧细分为N帧,第二个参数决定从一帧到另一帧的中间间隔是用开始帧还是结束帧来进行填充。

看下图可以发现:

  • steps(N, start)将动画分为N段,动画在每一段的起点发生阶跃(即图中的空心圆 → 实心圆),动画结束时停留在了第N帧
  • steps(N, end)将动画分为N段,动画在每一段的终点发生阶跃(即图中的空心圆 → 实心圆),动画结束时第N帧已经被跳过(即图中的空心圆 → 实心圆),停留在了N+1帧。

steps()参考资料

实践出真知!

Animation 实现打字效果 Online Code

  • 此处用英文字母(I'm an O2man.)举例,一共有13个字符。[经测试,多数中文字体每个字符宽高都相等]
  • steps(13)可以将 @keyframes 动画分为13阶段运行,且每一阶段运行距离相等

效果如下:

@keyframes animate-x {
0%{
width: 0;
}
} p {
width: 125px;
overflow: hidden;
border-right: 1px solid transparent;
animation: animate-x 3s 0s steps(13) 1 forwards;
}
  • 可以发现仅仅这样还不够,动画运行过程中出现了字符被截断的情况,为了保证每个阶段运行后能准确无误地显示当前所处阶段的字符,我们还需要保证每个字符的width与动画每一阶段运行的距离相等
  • 设置Monaco字体属性,用以保证每个字符的 width 相同,具体像素受fontSize属性影响,示例中的字体宽度约为 9.6px,9.6px * 13(段数) = 124.8px (125px),所以当我们设置容器宽度为 125px,即可的达成目的:每个字符的 width 与动画每一阶段运行的距离相等(约为 9.6px )
p {
font-family: Monaco;
width: 125px ;
font-size: 16px;
overflow: hidden;
border-right: 1px solid transparent;
animation: animate-x 3s 0s steps(13) 1 forwards,cursor-x 0.4s 0s linear infinite;
}

Animation 实现帧动画 Online Code

.main {
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
}
  • 添加 @keyframes 修改 background-position,让背景图移动
@keyframes animate {
0% {
background-position: 0 0;
} 100% {
background-position: 0 100%;
}
}
.main{
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
animation: animate 2s 1s steps(47) infinite alternate;
}
  • 同时, css 还提供了animation-play-state用于控制动画是否暂停
input:checked+.main{
animation-play-state: paused;
}

文章篇幅较长,感谢大家的阅读,希望各位看客能够有所收获~ ~ ~

如果这篇文章对你有帮助,欢迎关注我的博客

参考资料

CSS 参考手册

SVG学习之stroke-dasharray 和 stroke-dashoffset 详解

理解CSS3 Animation中的steps()

【译】css动画里的steps()用法详解

CSS Will Change

你可能不知道的Animation动画技巧与细节的更多相关文章

  1. 你所不知道的 CSS 动画技巧与细节

    怕标题起的有点大,下述技巧如果你已经掌握了看看就好,欢迎斧正,本文希望通过介绍一些 CSS 不太常用的技巧,辅以一些实践,让读者可以更加深入的理解掌握 CSS 动画. 废话少说,直接进入正题,本文提到 ...

  2. 你所不知道的 CSS 滤镜技巧与细节

    承接上一篇你所不知道的 CSS 动画技巧与细节,本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! OK,下面直接进入正文.本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE ...

  3. 你所不知道的 CSS 阴影技巧与细节

    关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow 的用法. 最近一个新的项目,CSS-Ins ...

  4. 你所不知道的 CSS 阴影技巧与细节 滚动视差?CSS 不在话下 神奇的选择器 :focus-within 当角色转换为面试官之后 NPOI 教程 - 3.2 打印相关设置 前端XSS相关整理 委托入门案例

    你所不知道的 CSS 阴影技巧与细节   关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow  ...

  5. 【CSS】346- 你所不知道的 CSS 阴影技巧与细节

    偷懒了1个多礼拜,在工作饱和的情况下,怎么坚持学习?今天的分享来自@Coco国服第一切图仔,我们聊聊CSS属性box-shadow- 关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 ...

  6. 你所不知道的 CSS 负值技巧与细节

    写本文的起因是,一天在群里有同学说误打误撞下,使用负的 outline-offset 实现了加号.嗯?好奇的我马上也动手尝试了下,到底是如何使用负的 outline-offset 实现加号呢? 使用负 ...

  7. css3 animation动画技巧

    一,css3 animation动画前言 随着现在浏览器对css3的兼容性越来越好,使用css3动画来制作动画的例子也越来越广泛,也随着而来带来了许多的问题值得我们能思考.css3动画如何让物体运动更 ...

  8. 【转载】14个你可能不知道的 JavaScript 调试技巧

    了解你的工具可以极大的帮助你完成任务.尽管 JavaScript 的调试非常麻烦,但在掌握了技巧 (tricks) 的情况下,你依然可以用尽量少的的时间解决这些错误 (errors) 和问题 (bug ...

  9. 14 个你可能不知道的 JavaScript 调试技巧

    了解你的工具可以极大的帮助你完成任务.尽管 JavaScript 的调试非常麻烦,但在掌握了技巧 (tricks) 的情况下,你依然可以用尽量少的的时间解决这些错误 (errors) 和问题 (bug ...

随机推荐

  1. 优化vue+springboot项目页面响应时间:waiting(TTFB) 及content Download

    优化vue+springboot项目页面响应时间:waiting(TTFB) 及content Download TTFB全称Time To First Byte,是指网络请求被发起到从服务器接收到地 ...

  2. 【九度OJ】题目1180:对称矩阵 解题报告

    [九度OJ]题目1180:对称矩阵 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1180 题目描述: 输入一个N维矩阵,判断是否对称 ...

  3. 【LeetCode】657. Judge Route Circle 解题报告

    [LeetCode]657. Judge Route Circle 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/judge-route- ...

  4. hdu-3833 YY's new problem(数组标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=3833 做这题时是因为我在网上找杭电的数论题然后看到说这道题是数论题就点开看了以下. 然后去杭电上做,暴力,超时了 ...

  5. 1105 第K大的数

    1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB  数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * B[0],A[0] * B[1] ...... ...

  6. 1076 - Get the Containers

    1076 - Get the Containers    PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...

  7. KISS原则

    Keep It Simple, Stupid 1. 模块性原则:写简单的,通过干净的接口可被连接的部件:2. 清楚原则:清楚要比小聪明好.3. 合并原则:设计能被其它程序连接的程序.4. 分离原则:从 ...

  8. Parallel.ForEach 之 MaxDegreeOfParallelism

    参考:Max Degree of Parallelism最大并行度配置 结论: 与设置的线程数有关 有设置的并行度有关 测试如下: @@@code System.Threading.ThreadPoo ...

  9. 04.python哈希表

    python哈希表 集合Set 集合,简称集.由任意个元素构成的集体.高级语言都实现了这个非常重要的数据结构类型. Python中,它是可变的.无序的.不重复的元素的集合. 初始化 set() -&g ...

  10. 第10组 Beta冲刺 总结(组长)

    1.基本情况 组长博客链接:https://www.cnblogs.com/cpandbb/p/14050808.html 答辩总结: ·因为alpha阶段的产品做得偏离了方向,所以beta冲刺大家非 ...