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

🎉 一、前言

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 前端性能优化清单

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux - 第23节 - Linux高级IO(一)

目录 1.IO的基本概念 2.钓鱼五人组 3.五种IO模型 3.1.阻塞IO 3.2.非阻塞IO 3.3.信号驱动IO 3.4.IO多路转接 3.5.异步IO 4.高级IO重要概念 4.1.同步通信 VS 异步通信 4.2.阻塞 VS 非阻塞 5.其他高级IO 6.阻塞IO 7.非阻塞IO 7.1.fcntl函数介绍 7.2.fcntl函数的使…

MobPush 推送查询API

IP绑定 工作台可以绑定服务器IP地址,未绑定之前所有IP均可进行REST API的调用,绑定后进仅绑定的IP才有调用权限。 设备信息查询接口 根据RegistrationId查询设备信息 接口地址 http://api.push.mob.com/device-v3/getById/{registrationId} 请求方式…

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

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

一个小时入门 Android Compose 动画

0. 前言 前段时间对于Android中的Compose动画做了系统性的学习,相关文章发布在 Compose 动画 专栏里。系统性学完Compose动画后,又对此做了系统性的回顾,抽取其比较重要的部分,希望能帮助大家快速入门Compose动画,所…

ChatGPT新突破:打造自己的智能机器人控制系统

💖 作者简介:大家好,我是Zeeland,全栈领域优质创作者。📝 CSDN主页:Zeeland🔥📣 我的博客:Zeeland📚 Github主页: Undertone0809 (Zeeland) (github.com)&…

【论文速览】根据人脑fMRI信号重建图像 Image Reconstruction from human brain activity

文章目录 前言文章一研究背景主要方法部分实验结果总结与思考参考资料 文章二研究背景主要方法部分实验结果总结与思考 前言 人类的视觉神经系统对于真实世界的视觉刺激有着非凡的感知与理解能力,比如我们能够准确地识别物体距离和三维几何关系等,这是当…

三维数字沙盘交互大数据可视化GIS地理信息系统第十课

三维电子沙盘交互无人机倾斜摄影大数据可视化GIS地理信息系统第十课 设置system.ini 如下内容 Server122.112.229.220 userGisTest Passwordchinamtouch.com 该数据库中只提供 成都市火车南站附近的数据请注意,104.0648,30.61658 在SDK中自带了一个自定义的基础面…

pycharm和virtualBox虚拟机的安装(包括本地环境和远程环境配置)

目录 一、安装时需要的软件二、安装virtualBox三、安装pycharm四、创建pycharm本地环境五、创建pycharm远程环境 一、安装时需要的软件 Pycharm,jetbrains-agent-latest破解包(破解pycharm);镜像文件ubuntu20,虚拟机virtualBox …

Zellij – 颜值爆表,比tmux、screen更好用的多窗口终端

如果你曾经使用过多窗口终端,如tmux、screen,那么你可能对Zellij上手会更快。下面将介绍这个惊艳出众的多窗口终端利器。 一、Zellij 特点 Zellij最大的特点是支持插件,与WebAssembly编译兼容。与screen和tmux相比,Zellij是以细…

Linux 之Python 定制篇-APT 软件管理和远程登录

Linux 之Python 定制篇-APT 软件管理和远程登录 apt 介绍 apt 是Advanced Packaging Tool 的简称,是一款安装包管理工具。在Ubuntu 下,我们可以使用apt 命令进行软件包的安装、删除、清理等,类似于Windows 中的软件管理工具。 unbuntu 软件…

LVS-DR负载群集的优势和部署实例(我们都会在各自喜欢的事情里变得可爱)

文章目录 一、DR模式数据包流向分析二、DR模式的特点三、DR模式中需要解决的问题问题1解决方式 问题2解决方式 四、LVS-DR部署实例1.配置NFS共享存储器2.配置节点web服务(两台的配置相同)3.配置LVS负载调度器 一、DR模式数据包流向分析 1.Client 客户端…

《计算机网络——自顶向下方法》精炼——3.7(2)

读书有三到:谓心到,眼到,口到。——明朱熹 文章目录 对链接吞吐量的简化描述高带宽路径的TCP公平性 对链接吞吐量的简化描述 为了简化对一条TCP连接吞吐量的描述,我们首先忽略连接过程中处于慢启动状态的时间,因为这一…

chatgpt赋能python:Python将yyyymmdd转换成yyyy-mm-dd的方法

Python将yyyymmdd转换成yyyy-mm-dd的方法 Python语言不仅易于学习,而且是一种功能强大的语言,广泛应用于数据分析、人工智能和Web开发等领域。在实际开发过程中,我们经常遇到需要将日期格式转换为其他格式的需求。本文将介绍如何使用Python将…

Nginx rewrite

目录 一、location 1.location 匹配规则介绍 2. 实际网站使用中匹配规则 2.1第一个必选规则 2.2第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项 2.3第三个规则就是通用规则 3.location 匹配规则演示 2.1一般前缀匹配 2.2正则匹配 2.3正则…

电池状态估计 | Matlab实现利用卡尔曼滤波器估计电池充电状态

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 电池状态估计 | Matlab实现利用卡尔曼滤波器估计电池充电状态 研究内容 目前,常用的电池模型有:数

斐波那契数列题解(非递归c++方法实现)

在做信奥赛(信息学奥赛)中的for循环题目时,有一道斐波那契数列,想到的第一个方法是使用递归求解;因为以往题目最多使用的就是递归形式,但鉴于该题目在for循环题目堆,所以就思考了一些新方法&…

仙境传说RO:添加限购物品刷新物品库存教程

仙境传说RO:添加限购物品刷新物品库存教程 大家好我是艾西,在游戏中我们会有普通的基础装备那么必然就会有到顶的套装,往往可能一套到顶的套装就可能霸服。那么就需要GM去做游戏的设定以及限制,上一篇文章中我给大家讲述了如果创…

RabbitMQ的基本概念

目录 1、MQ 的基本概念 1.1 MQ概述 1.2 MQ 的优势和劣势 1.3 MQ 的优势 1. 应用解耦 2. 异步提速 3. 削峰填谷 小结: 1.4 MQ 的劣势 1.5 常见的 MQ 产品 1.6 RabbitMQ 简介 1.7 JMS 1、MQ 的基本概念 1.1 MQ概述 MQ全称 Message Queue(消息队列&#…

火山引擎DataLeap的Catalog系统搜索实践(三):Learning to rank与后续工作

Learning to rank Learning to rank主要分为数据收集,离线训练和在线预测三个部分。搜索系统是一个Data-driven system,因此火山引擎DataLeap的Catalog系统设计之初就需要考虑数据收集。收集的数据可以用来评估和提升搜索的效果。数据收集和在线预测前面…

Augmentation Matters:一种简单而有效的半监督语义分割方法(CVPR2023)

文章目录 Augmentation Matters: A Simple-yet-Effective Approach to Semi-supervised Semantic Segmentation摘要本文方法Random Intensity-based AugmentationsAdaptive Label-aided CutMix 实验结果 Augmentation Matters: A Simple-yet-Effective Approach to Semi-superv…