玩转css逐帧动画,努力成为更优质的Ikun~

news2024/11/9 9:54:50

🎉 一、前言

css3的animation想必大家都知道吧,那 steps 逐帧动画你知道吗?对于我来说,实际工作及练习中也很少用到这种跳跃式变化的动画,而它startend的解释又比较“不说人话”,以前用到steps动画的时候,常常是靠调试,来回设置startend,主打的就是瞎猫碰上死耗子。虽然之前也看过关于他们区别的文章,但都是半知半解,过两天就剩零知零解了。最近忙里偷闲,我终于打算一探究竟了,我倒要看看startend到底有什么区别!😠😠😠 顺便写几个小demo造福一方~

🔥 二、逐帧动画介绍

animation的工作原理是通过将元素的CSS样式从一个状态改变为另一个状态时(我们称为线性变化),浏览器会在每个关键帧之间插入补间动画,所以动画效果是连贯性的,这也就是我们常用的 补间动画

steps()逐帧动画则是跳跃式变化,如果说补间动画是一个滑坡式的变化,那么逐帧动画就是阶梯式变化,它的变化没有中间过程。补间动画就像你看的普通动画片,而逐帧动画就像是那种定格动画。

语法:

  animation-timing-function: steps(number, [end | start])

参数说明:

  • number参数指定了时间函数中的间隔数量(必须是正整数)

  • 第二个参数是可选的,可设值:startend,表示在每个间隔的起点或是终点发生阶跃变化,如果忽略,默认是end。

🌈 三、图解图解 step-startstep-end 区别

什么叫在间隔的起点或终点发生变化呢?光看文字十有八九看不懂,下面就用示例代码来说明。

数字.png

上图是我ps的一张图,尺寸为200*750,共5个色块,每个色块高度150。
在示例代码中我将以这张图为背景,每一帧将背景上升一个色块的高度。关键代码如下:

animation: ani 5s 2s steps(5,start) infinite backwards;

@keyframes ani{
  100%{
    background-position:0px -750px;
  }
}

🍀 在设置动画前的初始状态:

image.png

🍀 再直接来看看动画末态的情况:
一个色块150px,所以动画末态是背景图片向上移动750px。

image.png

为了完整的看到动画效果,我设置了2秒的动画延迟

🍀 我们设置的steps的第一个参数number5 ,也就是把整个动画过程切割成5个片段,如下图:

image.png

在实验之前先来分析一下,既然是片段,那必然有片段的起点和终点,可以把补间动画看作点,而逐帧动画则是面。那么这五个片段的起点终点是哪呢,如下图:

image.png

你会发现,动画是由6个点切成段五段,带着这个思路开始下面的实验。

🍀 先来看一下设置 start 的效果:

tutieshi_640x395_9s (2).gif

你会发现色块1怎么不显示了,甚至在动画没开始前,也就是延时阶段直接就显示了【2】,变化过程为: 2 - 3 - 4 - 5 - 空
分析一下就可以想到,start是在间隔的起点发生阶越变化,即开始直接就发生变化了,第一段直接阶越到了第一段结束的位置。

🍀 再来看下设置 end 的效果:

tutieshi_640x395_10s.gif

你发现动画变正常了,动画过程是从【1】到【5】。
再分析一下,因为end是在间隔终点发生阶越变化,即每一段都会在其开始阶段进行停留,这一段结束后才会发生变化直接阶越到下一段的开始状态。

🍀 总结:

可以将补间动画和 steps 逐帧动画类比于点和线的区别,steps切割开的每个动画片段就是一条样式不变的线,而线都有首尾两个点。
设置 startsteps 的动画总是在开始发生变化,即逐帧显示每一段的终点;
而设置 endsteps 的动画总是在结束发生变化,即逐帧显示每一段的起点;

其实很简单的道理,为什么总是记不住呢,因为他和人的惯性思维恰好相反。设置start总觉得是显示每一段的开头,可它恰好相反,start是开头发生变化,显示的都是每一段的结尾。

🍀 另一种理解思路:

image.png

steps(number, [end | start]) 是将动画分为number段,共有number + 1帧画面。start就是抛弃第一帧画面执行动画,end就是抛弃最后一帧画面执行动画。

注意: 第二个参数还有两个内置值,step-start等同于steps(1,start),动画分成1步,2个节点,抛弃第一个节点,即显示结尾节点的状态;同理step-end等同于steps(1,end)

jump-start:在每个时间间隔开始的时候跳1步到下一状态位置;
jump-end:在每个时间间隔结束的时候跳1步到下一状态位置;
jump-both:在每个时间间隔开始和结束的时候跳1步到下一状态位置,跳步次数会比预设的多一次;
jump-none:在每个状态位置停留够一个时间间隔才跳到下一位置,跳步次数会比与预设的少一次

🔑 四、思考

上面我只设置了动画100%时的状态,那如果我设置了多个关键帧的状态呢,那还是以整个动画过程切割成number段吗?

我们再来做几个实验:

实验1:

我们将动画时间由5秒改成10秒(为了方便观察,我们设置steps第二个参数为end,放弃第一帧画面),然后将原先的动画末态改到50%,并在动画100%时增加边框。·

animation: ani 10s 2s steps(5,end) infinite backwards;

@keyframes ani{
  50%{
    background-position:0px -750px;
  }
  100%{
    border: 100px solid red;
  }
}

结果如下图:

tutieshi_640x395_13s.gif

观察后发现,在10秒的完整动画期间:background-position的变化过程是图像显示由1到5,再由5到1,共变化了 【10】 次,而我设置的steps的number参数是 【5】,这就打破了上面我说的以整个动画过程切割成number段的假说。
同时可以观察到,border的变化过程共进行了5次,因为我们只在100%的时候设置了border

得出结论: stepsnumber参数并不是将整个动画过程切割成number段,而是对于某个css样式来说,每一段关键帧的变化切割成number段。

实验2:

假想:上面我们只在动画100%的时候设置了100px的boder,如果我们在50%的时候也设置border,并且状态恰好是100%的一半,这样对于动画0%到100%是一个流畅的线性变化。请问这时候动画还会被切成5段吗?

tutieshi_640x395_12s.gif

观察发现,动画被切成了10段。

得出结论: 即使将几个关键帧的css变化设置的具有规律性,但是steps仍然会将每段关键帧的变化切割成number段,即只要在这个关键帧里设置了某个css,那么对于这个css来说,这个关键帧就会被视为steps动画的端点。

实验3:

那既然每段关键帧都会被steps切割成number段,那每段的steps动画执行的时间怎么划分呢?其实想想就能想到,应该是按照关键帧占整个动画过程的比例分割整个动画时间。
如下图设置boder:【0%-50%】宽度由0到100,【50%-75%】宽度由100到0,【75%-100%】宽度由0到100

tutieshi_640x395_10s.gif

很明显可以观察到,border宽度变化的时间为 2:1:1,即验证了我上面的推论。

⚔ 五、steps() 动画实践

下面我举几个steps() 动画的使用场景。

1. 动物或人物的动作变化–铁山靠

用一张人物动作关键帧的长图,和上面的案例一样,通过修改背景图片位置,实现动物或人物的动作变化。作为一名蒸爱粉,我给哥哥做了一个跳舞的动画:

jcode

2. 打字机效果–“只因你太美”

打字机的原理是用一个和文字总宽度一样的div覆盖文字,并用这个div的边框设置steps()动画实现光标效果,然后减小div宽度(每一帧减小一个文字的宽度),让下面文字漏出来就好了~\

点击运行查看效果~

jcode

3. 纯css实现倒计时

我这里提供了两种实现方案,准确来说是三种:

方案1: var() css变量 + counter-reset计数器 + @property规则 + steps()逐帧动画
使用css变量和counter-reset计数器来实现倒计时的数字,只要设置动画,在5秒内将变量由5变为0即可实现倒计时,但是变量的变化是不会被浏览器添加补间动画的,即只会在5秒后直接变成0,而不会有中间,5-4-3-2-1-0的过程,这时我们再利用@property关键字为这个变量配置规则,实现数字变化的动态过程!
而最后出现的 “Go” 可以利用step-end逐帧动画,在5秒后将文字修改成 “Go”,或者利用@counter-style关键字自定义计数器规则,在变量变化到0的时候,定义一个symbols符号。

如果你不了解counter-reset@property@counter-style,可以查看以下两篇文章:
CSS counter-reset 属性
mdn 关于@property API 说明
mdn 关于@counter-style 说明

点击运行查看效果~

jcode

方案2: 只用steps()逐帧动画
其实这个就很简单了,所有的数字和最后的 “GO” 都在html里写死并设置等高,然后就可以向上面移动图片位置一样移动这些数字进行显示了。

点击运行查看效果~

jcode

4. 其他应用场景

平常工作中可以用到steps()逐帧动画的场景也有很多:

  • 例如在延迟n秒后修改元素某个样式,常规可能需要用js写个延时器动态修改它的css,这完全可以用step-start动画代替;
  • 再比如除了上面那种大屏的倒计时,普通的时分秒倒计时也可以用steps代替js实现,实现原理也简单,就是将 0-9 制作成一张精灵图,然后时分秒每个单位都各自用这个精灵图当作背景,例如对于秒的数字,可以设置动画时长为10s,动画函数为steps(10,start),这样每次数字变化都是 1s,同理对于分的数字,设置动画时长为 600s,动画函数为steps(10,start),这样每次数字变化都是 60s。

💥 六、写在最后

我是喜欢归纳总结前端相关知识的前端阿彬,尽力持续输出原创优质文章,欢迎点赞关注😘

往期文章
# 🕸2023 前端 SEO 无死角解读
# 我给自己搭建的前端导航网站,你们都别用🤪
# 2023 最新最细 vite+vue3+ts 多页面项目架构,建议收藏备用!
# 浅谈 强制缓存/协商缓存 怎么用?
# 2023 前端性能优化清单

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/624136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FL Studio21水果软件各个版本功能区别对比

作为音乐人,在电脑上进行编曲,混音,合成是家常便饭,而市面上大家常用的音乐编曲制作软件很多,小编在这里就给大家做一个推荐。 大家常听到的音乐编曲制作软件大多是Cubase、Nuendo、Pro Tools、 SONAR等等&#xff0c…

Qt中QFile类读取ansi编码格式txt文件,在QTextEdit控件中显示乱码

系列文章目录 文章目录 系列文章目录前言一、依然无法解决乱码问题二、解决办法1.方法一:使用QString的fromLocal8Bit()函数2.读取utf-8编码格式的文件 总结 前言 使用Qt中的QFile类读取ANSI编码格式的文本文件,并在QTextEdit控件中显示乱码&#xff0c…

适配器模式的运用

文章目录 一、适配器模式的运用1.1 介绍1.2 适配器模式结构1.3 类适配器模式1.3.1 类适配器模式类图1.3.2 代码 1.4 对象适配器模式1.4.1 对象适配器模式类图1.4.2 代码 1.5 应用场景1.6 JDK源码解析1.6.1 字节流到字符流的转换类图1.6.2 部分源码分析1.6.3 总结 一、适配器模式…

MyBatis的使用、Spring AOP、Spring事务

一、MyBatis 的使用 1、环境配置 1.1、建库建表 -- 创建数据库 drop database if exists mycnblog; create database mycnblog DEFAULT CHARACTER SET utf8mb4;-- 使⽤数据数据 use mycnblog;-- 创建表[⽤户表] drop table if exists userinfo; create table userinfo(id in…

智能算法终极大比拼,以CEC2017测试函数为例,十种智能算法直接打包带走,不含任何套路!

包含人工蜂群(ABC)、灰狼(GWO)、差分进化(DE)、粒子群(PSO)、麻雀优化(SSA)、蜣螂优化(DBO)、白鲸优化(BWO)、遗传算法(GA)、粒子群算法(PSO),基于反向动态学习的差分进化算法,共十种算法,直接一文全部搞定! 还是老规矩&#xff…

Android MaterialComponents主题下Button设置background无效

问题描述 使用的主题代码如下图&#xff1a; <!-- Base application theme. --><style name"Base.Theme.MyApplication" parent"Theme.Material3.DayNight.NoActionBar"><!-- Customize your light theme here. --><!-- <item na…

JAVA面向对象(二)

第二章 方法与方法重载 目录 第二章 方法与方法重载 带参方法的使用 构造方法 构造方法重载 成员变量和局部变量 总结 内容仅供学习交流&#xff0c;如有问题请留言或私信&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 有空您就点点赞 带参方法的使用…

Java代码的运行过程

我们来聊一聊java代码是如何运行的。大家都知道java是运行在JVM上的&#xff0c;那它是怎么结合操作系统去控制那些硬件设备的呢&#xff1f; 其实想要知道这个问题我们可以跟踪一行代码的整个生命周期来解释&#xff0c;我把它抽象为这么五个步骤。 首先这行代码会被编译成字节…

最强攻略 | 1分钟带你了解内测,成为BUG小能手!

「百度产品内测」招募内测体验官啦&#xff01;&#xff01; 参与百度内测&#xff0c;不仅可以直接接触百度运营官&#xff0c;还能拿礼物拿京东卡拿百度大礼包&#xff01; 什么你说你没接触过内测&#xff1f;贴心如我&#xff0c;给大家带来一份史上最全的新手入门指南&am…

​DMBOK知识梳理for CDGA/CDGP——第五章 数据模型与设计(附常考知识点)

关 注gzh“大数据食铁兽”&#xff0c;回复“知识点”获取《DMBOK知识梳理for CDGA/CDGP》常考知识点&#xff08;第五章 数据模型与设计&#xff09; 第五章 数据模型与设计 第五章是CDGA|CDGP考试的重点考核章节之一&#xff0c;分值占比高&#xff0c;知识点比较密集…

【大数据之路4】分布式计算模型 MapReduce

4. 分布式计算模型 MapReduce 1. MapReduce 概述1. 概念2. 程序演示1. 计算 WordCount2. 计算圆周率 π 3. 核心架构组件4. 编程流程与规范1. 编程流程2. 编程规范3. 程序主要配置参数4. 相关问题1. 为什么不能在 Mapper 中进行 “聚合”&#xff08;加法&#xff09;&#xff…

MATLAB入门教程||MATLAB决策制定||MATLAB if...end 语句

MATLAB决策制定 本节内容&#xff1a;了解MATLAB提供的决策类型&#xff0c;及使用它们进行决策制定。 决策结构用来做什么&#xff1f;决策结构要求程序员能够使用一个或者多个的条件来对程序进行评估或者测试&#xff0c;沿着一条或多条语句执行&#xff0c;如果该条件被确定…

docker启动rabbitmq无法访问15672端口

1.问题说明 使用rabbitmq:3.8.14版本启动了rabbitmq容器&#xff0c;5672、25672端口都可以连接&#xff0c;唯独15672仅在服务器本地可被连接。 2.问题原因 rabbitmq:3.8版本开始&#xff0c;管理插件包含在RabbitMQ发行版中。与其他任何插件一样&#xff0c;必须先启用它&am…

SpringCloud_微服务基础day2(Eureka简介与依赖导入,服务注册与发现)

p6:Eureka简介与依赖导入 前面我们了解了如何对单体应用进行拆分&#xff0c;并且也学习了如何进行服务之间的相互调用&#xff0c;但是存在一个问题&#xff0c;就是虽然服务拆分完成&#xff0c;但是没有一个比较合理的管理机制&#xff0c;如果单纯只是这样编写&#xff0c;…

实战:Spring Cloud Stream集成兼容多消息中间件kafka、rabbitmq

文章目录 前言实战要点技术积累Spring Cloud Stream简介集成kafka要点集成rabbitmq要点 实战演示Maven依赖版本号选择Spring及MQ主要配置基础信道绑定信道消息发送集成兼容多mq演示Rabbitmq演示Kafka演示 写在最后 前言 前面的博文我们介绍并实战演示了Spring Cloud Stream整合…

Java 使用 VisualVM 排查内存泄露

文章目录 1. 问题发生2. 排查过程2.1 初步排查2.2 Visual VM 内存分析2.3 代码分析 1. 问题发生 线上突发告警&#xff0c;笔者负责的一个服务老年代内存使用率到达 75% 阈值&#xff0c;于是立即登录监控系统查看数据。拉长时间周期&#xff0c;查看最近 7 天的 GC 和老年代内…

Transformer【ViT】

参考 导师&#xff01;博主的复现太细了。做个记录。 层神经网络学习小记录67——Pytorch版 Vision Transformer&#xff08;VIT&#xff09;模型的复现详解 计算机视觉中的transformer模型创新思路总结_Tom Hardy的博客-CSDN博 Vision Transformer详解 ViT 前处理 网络结…

2核4G轻量应用服务器性能测评(腾讯云PK阿里云)

阿里云轻量应用服务器2核4G4M带宽297.98元12个月&#xff0c;腾讯云轻量2核4G5M服务器168元一年&#xff0c;628元3年&#xff0c;2核4G轻量应用服务器阿里云和腾讯云怎么选择&#xff1f;哪个性能比较好&#xff1f;阿腾云分享轻量应用服务器2核4G配置阿里云和腾讯云CPU、带宽…

三种编码方式(费诺曼编码,霍夫曼编码,哈夫曼树编码)的简单解释和介绍

一. 费诺曼(Fano)编码是一种前缀编码&#xff0c;其基本原理是将出现频率较高的符号用短的编码表示&#xff0c;而出现频率较低的符号则用长的编码表示。通过这种方式进行编码&#xff0c;可以达到更好的压缩效果。 费诺曼编码的具体过程如下&#xff1a; 将要编码的符号按照…

书籍《银河帝国11:曙光中的机器人》观后感

这本书其实看完有段时间了&#xff0c;《银河帝国11:曙光中的机器人》是阿西莫夫写的《基地》系列第11本书&#xff0c;整个系列不是完全连贯的&#xff0c;本书是《银河帝国10》的后续。 先让我们来回忆一下前奏和背景吧&#xff0c;未来随着人类科技发展&#xff0c;遨游太空…