文字轮播与图片轮播?CSS 不在话下
今天,分享一个实际业务中能够用得上的动画技巧。
巧用逐帧动画,配合补间动画实现一个无限循环的轮播效果,像是这样:
看到上述示意图,有同学不禁会发问,这不是个非常简单的位移动画么?
我们来简单分析分析,从表面上看,确实好像只有元素的 transform: translate()
在位移,但是注意,这里有两个难点:
- 这是个无限轮播的效果,我们的动画需要支持任意多个元素的无限轮播切换
- 因为是轮播,所以,运行到最后一个的时候,需要动画切到第一个元素
到这里,你可以暂停思考一下,如果有 20 个元素,需要进行类似的无限轮播播报,使用 CSS 实现,你会怎么去做呢?
逐帧动画控制整体切换
首先,我需要利用到逐帧动画效果,也被称为步骤缓动函数,利用的是 animation-timing-function
中,的 steps,语法如下:
{
/* Keyword values */
animation-timing-function: step-start;
animation-timing-function: step-end;
/* Function values */
animation-timing-function: steps(6, start)
animation-timing-function: steps(4, end);
}
如果你对 steps
的语法还不是特别了解,强烈建议你先看看我的这篇文章 -- 深入浅出 CSS 动画,它对理解本文起着至关重要的作用。
好的,还是文章以开头的例子,假设我们存在这样 HTML 结构:
<div class="g-container">
<ul>
<li>Lorem ipsum 1111111</li>
<li>Lorem ipsum 2222222</li>
<li>Lorem ipsum 3333333</li>
<li>Lorem ipsum 4444444</li>
<li>Lorem ipsum 5555555</li>
<li>Lorem ipsum 6666666</li>
</ul>
</div>
首先,我们实现这样一个简单的布局:
在这里,要实现轮播效果,并且是任意个数,我们可以借助 animation-timing-function: steps()
:
:root {
// 轮播的个数
--s: 6;
// 单个 li 容器的高度
--h: 36;
// 单次动画的时长
--speed: 1.5s;
}
.g-container {
width: 300px;
height: calc(var(--h) * 1px);
}
ul {
display: flex;
flex-direction: column;
animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
}
ul li {
width: 100%;
}
@keyframes move {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(0, calc(var(--s) * var(--h) * -1px));
}
}
别看到上述有几个 CSS 变量就慌了,其实很好理解:
calc(var(--speed) * var(--s))
:单次动画的耗时 * 轮播的个数,也就是总动画时长steps(var(--s))
就是逐帧动画的帧数,这里也就是steps(6)
,很好理解calc(var(--s) * var(--h) * -1px))
单个 li 容器的高度 * 轮播的个数,其实就是 ul 的总体高度,用于设置逐帧动画的终点值
上述的效果,实际如下:
如果给容器添加上 overflow: hidden
,就是这样的效果:
这样,我们就得到了整体的结构,至少,整个效果是循环的。
但是由于只是逐帧动画,所以只能看到切换,但是每一帧之间,没有过渡动画效果。所以,接下来,我们还得引入补间动画。
利用补间动画实现两组数据间的切换
我们需要利用补间动画,实现动态的切换效果。
这一步,其实也非常简单,我们要做的,就是将一组数据,利用 transform
,从状态 A 位移到 状态 B。
单独拿出一个来演示的话,大致的代码如下:
<div class="g-container">
<ul style="--s: 6">
<li>Lorem ipsum 1111111</li>
<li>Lorem ipsum 2222222</li>
<li>Lorem ipsum 3333333</li>
<li>Lorem ipsum 4444444</li>
<li>Lorem ipsum 5555555</li>
<li>Lorem ipsum 6666666</li>
</ul>
</div>
:root {
--h: 36;
--speed: 1.2s;
}
ul li {
height: 36px;
animation: liMove calc(var(--speed)) infinite;
}
@keyframes liMove {
0% {
transform: translate(0, 0);
}
80%,
100% {
transform: translate(0, -36px);
}
}
非常简单的一个动画:
基于上述效果,我们如果把一开始提到的 逐帧动画 和这里这个 补间动画 结合一下,ul 的整体移动,和 li 的 单个移动叠在在一起:
:root {
// 轮播的个数
--s: 6;
// 单个 li 容器的高度
--h: 36;
// 单次动画的时长
--speed: 1.5s;
}
.g-container {
width: 300px;
height: calc(var(--h) * 1px);
}
ul {
display: flex;
flex-direction: column;
animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
}
ul li {
width: 100%;
animation: liMove calc(var(--speed)) infinite;
}
@keyframes move {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(0, calc(var(--s) * var(--h) * -1px));
}
}
@keyframes liMove {
0% {
transform: translate(0, 0);
}
80%,
100% {
transform: translate(0, calc(var(--h) * -1px));
}
}
就能得到这样一个效果:
Wow,神奇的化学反应产生了!基于 逐帧动画 和 补间动画 的结合,我们几乎实现了一个轮播效果。
当然,有一点瑕疵,可以看到,最后一组数据,是从第六组数据 transform 移动向了一组空数据:
末尾填充头部第一组数据
实际开发过轮播的同学肯定知道,这里,其实也很好处理,我们只需要在末尾,补一组头部的第一个数据即可:
改造下我们的 HTML:
<div class="g-container">
<ul>
<li>Lorem ipsum 1111111</li>
<li>Lorem ipsum 2222222</li>
<li>Lorem ipsum 3333333</li>
<li>Lorem ipsum 4444444</li>
<li>Lorem ipsum 5555555</li>
<li>Lorem ipsum 6666666</li>
<!--末尾补一个首条数据-->
<li>Lorem ipsum 1111111</li>
</ul>
</div>
这样,我们再看看效果:
Beautiful!如果你还有所疑惑,我们给容器加上 overflow: hidden
,实际效果如下,通过额外添加的最后一组数据,我们的整个动画刚好完美的衔接上,一个完美的轮播效果:
完整的代码,你可以戳这里:CodePen Demo -- Vertical Infinity Loop
横向无限轮播
当然,实现了竖直方向的轮播,横向的效果也是一样的。
并且,我们可以通过在 HTML 结构中,通过 style 内填写 CSS 变量值,传入实际的 li 个数,以达到根据不同 li 个数适配不同动画:
<div class="g-container">
<ul style="--s: 6">
<li>Lorem ipsum 1111111</li>
<li>Lorem ipsum 2222222</li>
<li>Lorem ipsum 3333333</li>
<li>Lorem ipsum 4444444</li>
<li>Lorem ipsum 5555555</li>
<li>Lorem ipsum 6666666</li>
<!--末尾补一个首尾数据-->
<li>Lorem ipsum 1111111</li>
</ul>
</div>
整个动画的 CSS 代码基本是一致的,我们只需要改变两个动画的 transform
值,从竖直位移,改成水平位移即可:
:root {
--w: 300;
--speed: 1.5s;
}
.g-container {
width: calc(--w * 1px);
overflow: hidden;
}
ul {
display: flex;
flex-wrap: nowrap;
animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
}
ul li {
flex-shrink: 0;
width: 100%;
height: 100%;
animation: liMove calc(var(--speed)) infinite;
}
@keyframes move {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(calc(var(--s) * var(--w) * -1px), 0);
}
}
@keyframes liMove {
0% {
transform: translate(0, 0);
}
80%,
100% {
transform: translate(calc(var(--w) * -1px), 0);
}
}
这样,我们就轻松的转化为了横向的效果:
完整的代码,你可以戳这里:CodePen Demo -- Horizontal Infinity Loop
轮播图?不在话下
OK,上面的只是文字版的轮播,那如果是图片呢?
没问题,方法都是一样的。基于上述的代码,我们可以轻松地将它修改一下后得到图片版的轮播效果。
代码都是一样的,就不再列出来,直接看看效果:
完整的代码,你可以戳这里:CodePen Demo -- Horizontal Image Infinity Loop
掌握了这个技巧之后,你可以将它运用在非常多只需要简化版的轮播效果之上。
再简单总结一下,非常有意思的技巧:
- 利用 逐帧动画,实现整体的轮播的循环效果
- 利用 补间动画,实现具体的 *状态A 向 状态B 的动画效果
- 逐帧动画 配合 补间动画 构成整体轮播的效果
- 通过向 HTML 结构末尾补充一组头部数据,实现整体动画的衔接
- 通过 HTML 元素的 style 标签,利用 CSS 变量,填入实际的参与循环的 DOM 个数,可以实现 JavaScript 与 CSS 的打通
最后
OK,本文到此结束,希望本文对你有所帮助
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
文字轮播与图片轮播?CSS 不在话下的更多相关文章
- Bootstrap3.0学习第二十六轮(JavaScript插件——图片轮播)
详情请查看http://aehyok.com/Blog/Detail/32.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...
- 33个好用的图片轮显 jquery图片轮显
原文发布时间为:2011-05-28 -- 来源于本人的百度文章 [由搬家工具导入] 我个人还是喜欢 jquery.recycle,比较通用。因为由美工设计好的轮显结构,如果套用下面,就感觉不是很方便 ...
- Flexslider图片轮播、文字图片相结合滑动切换效果
Flexslider是一款基于的jQuery内容滚动插件.它能让你轻松的创建内容滚动的效果,具有非常高的可定制性.开发者可以使用Flexslider轻松创建各种图片轮播效果.焦点图效果.图文混排滚动效 ...
- 2017年10月21日 CSS常用样式&鼠标样式 以及 jQuery鼠标事件& jQuery图片轮播& jQuery图片自动轮播代码
css代码 背景与前景 background-color:#0000; //背景色,样式表优先级高 background-image:url(路径); //设置背景图片 background-atta ...
- 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结
史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...
- 图片轮播(bootstrap)与 圆角搜索框(纯css)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- 纯CSS 多图片轮播
今天做东西的时候,遇到一个问题关于图片轮播的问题,以前也接触过(百度 人家的demo改改..),再次遇到这个问题的时候,根据以前的印象找到了demo正信心满满的准备改一下嵌进去,发现 jquery.m ...
- Jquery图片轮播和CSS图片轮播
学习Jquery以后,很多时候觉得比写源生代码要简单一点.我们用JQuery做了一个图片轮播的动画,感觉比写CSS要简单一些.下面我来具体讲一下是怎么用JQuery来写. <body> & ...
- CSS快速制作图片轮播的焦点
来源:http://www.ido321.com/858.html 效果图: 演示地址:http://jsfiddle.net/Web_Code/q5qfd8aL/embedded/result/ 代 ...
随机推荐
- java继承时能包括静态的变量和方法吗?举例说明!
子类继承了超类定义的所有实例变量和方法包括静态的变量和方法(马克-to-win见下例),并且为它自己增添了独特的元素.子类只能有一个超类.Java不支持多超类的继承. 子类拥有超类的所有成员,但它不能 ...
- ubuntu下安装typora、pycharm、搜狗拼音、MySQL、docker
安装typora # or run: # sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE ...
- Struts2-EL表达式为什么能获取值栈数据
1.EL表达式能获取域对象值 2.向域对象里面放值使用setAttribute方法,获取使用getAttribute方法 3.底层增强request对象里面的方法getAttribute方法 (1)首 ...
- linux磁盘分区fdisk命令操作(实践)
写这篇的目的,还是要把整个过程完整的记录下来,特别是小细节的地方,通常很多情况是一知半解,平时不实践操作只凭看是没有用的,所以做这个行业就是要多动手,多学习,多思考慢慢你的思路也会打开.练就自己的学习 ...
- 【转载】Java密钥库及keytool使用详解
---------------- 版权声明:本文为CSDN博主「adrninistrat0r」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https: ...
- 基于kubernetes的分布式限流
做为一个数据上报系统,随着接入量越来越大,由于 API 接口无法控制调用方的行为,因此当遇到瞬时请求量激增时,会导致接口占用过多服务器资源,使得其他请求响应速度降低或是超时,更有甚者可能导致服务器宕机 ...
- eBPF Cilium实战(2) - 底层网络可观测性
在之前的平台中,对于组件之间的网络流向不具备直接的可观测性,用户组件间通信出现问题,只能通过传统命令行工具进行手动排查,而 cilium 的 Hubble 服务可以提供 UI 界面向用户展示实时的流量 ...
- Java学习day17
继续学习了IO流的一些常用类以及GUI基础 做了自己的第一个Frame窗口 在做第一个Frame窗口时程序报错:java: 无法从静态上下文中引用非静态 变量 this 查看后发现不小心把MyFram ...
- 2021.08.30 前缀函数和KMP
2021.08.30 前缀函数和KMP KMP算法详解-彻底清楚了(转载+部分原创) - sofu6 - 博客园 (cnblogs.com) KMP算法next数组的一种理解思路 - 挠到头秃 - 博 ...
- react实战系列 —— 起步(mockjs、第一个模块、docusaurus)
其他章节请看: react实战 系列 起步 本篇我们首先引入 mockjs ,然后进入 spug 系统,接着模仿"任务计划"模块实现一个类似的一级导航页面("My任务计划 ...