前端开发日常——CSS动画无限轮播
近来没有什么值得写的东西,空闲的时候帮前端的同学做了些大屏上的展示模块,就放在这里写写吧,手把手“需求->设计-> 实现”,受众偏新手向。

为了直观便于理解, 直接把结果贴在上面。
如上所示,基本需求比较简单明了, “分页显示供应商、供应占比列表,自动轮播”。
一、需求评审
该有的环节还是要有,尽管需求简单,评审不能省略,无论形式。开发的同学千万不要真的相信需求就这么简单,否则南辕北辙,出力不讨好,那必定是日常-_-||。
于是有丰富填坑经验的开发同学,对于这个简单的模块需求,可能会提出如下的一些问题
1. 如果只有一页,要不要轮播?
2.每页的轮播间隔频率是多少?
3.如果列表没有数据,如何显示这个模块?
4.数据的刷新时机?是翻页刷新,轮播一圈刷新,还是其他?
5.这个绿色的比值是什么含义? 是不是还有红色?
6.百分比的小数位?
7.如果接口异常比如网络不通,如何表示这种异常?
8.供应商的名字会不会有500字那么长? 放不下如何布局?
……等等
以上任何一个未明确的需求,都可能成为你编码完成后的一个bug或优化建议。 o(* ̄︶ ̄*)o。
二、设计评审
关于上面待确认的每一个问题,我们伟大的产品经理都一一耐心的给出了“令人信服的”回答后。还是不能马上开始编码。下面我们需要进行一些技术方案的设计讨论,由技术leader把关。例如:
1. 数据流,这个列表的数据,是从数据库中的哪几个表取出的? 确认下查询逻辑。
2.接口设计,是一次返回前端所有数据,还是支持分页查询。
3.性能考虑,查询频率是不是较高,并发是不是大,缺不缺索引,要不要上缓存?
4.轮播如何实现? 有没有已经集成的轮播控件,是否满足要求,还是需要自己写一个。
5.如何进行模块化开发,作为一个模块集成嵌入到整体页面中。
……等等
明确了以上的问题后,作为前端同学的我,是不是可以开始撸代码了?
三、想清楚再写
说到这里,
一类同学已经开始着手编码了, 第一个想到需要写的方法可能是,ajax 去后台请求数据列表的接口。
另一类同学,可能仍在构思,如何组织代码,提炼主要的数据结构和功能方法。
这里我们显然应该向“另外一类”同学学习。想清楚再写,是一个毫无疑问的好习惯。
技术预研
实现一个功能,首先要扫除其中的未知技术点,扫除了所有未知之后,才能够优化的组织实现方案。
上面的需求对于我这种半吊子前端来说,比较关键的两个技术问题是。
1)用什么方案来实现滑动动画。 2)如何实现“无限滚动”。
滑动动画——经过一番百度,总结下动画可能的实现方案,包括用JS实现或者用CSS实现。 各有优劣,js 兼容性好,控制灵活;CSS性能高,平滑流畅。因为我们的动画非常线性,简单,于是这里我们决定采用CSS动画作为动画的实现方案。
通过简单的研究,我们已经弄清楚了, 想让一个页面元素具有一个动画效果,可以通过向他添加一个包含了动画关键真的选择器来实现,比如定义一个滑出动画类,把这个css类加到元素上,元素就可以实现滑出的动画效果。
无限滚动——思考下滚动页面,虽然对于数据来说可能会分成很多页,但对于屏幕展示来说,实际上最多同时出现两个页面,一个是前一页,一个是当前页。在不滚动的时候只有当前页需要显示。
顺着这个思路, 滚动这个动作对应,“当前页飞入”“前一页飞出”这两个细分动作,特别的情况是,初始显示时,是没有“前一页”的。
那么滚动这个动作大概思路就是,
1. 根据当前页号取得对应数据,绘制HTML页面,append到滚动区域,对其添加“飞入”动画
2. 根据当前页号取得上一页页面元素,对其添加“飞出”动画,动画结束后将其移除, 仅显示当前页。
四、编码实现
终于到了编码的时间了。
用到的 css 动画类选择器,以及关键帧
.slip_in_animation{
animation: slip_in 1s;
}
.slip_out_animation{
animation: slip_out 1s;
}
/*右侧滑入*/
@keyframes slip_in
{
from {transform:translateX(100%);}
to {transform:translateX(0);}
}
/*右侧滑入*/
@keyframes slip_out
{
from {transform:translateX(0);}
to {transform:translateX(-100%);}
}
js应用于页面元素,飞入飞出, 飞出后删除,*动画在结束后并不会改变元素实际位置。所以要在动画结束前,移除元素,避免它回到之前位置,挡住当前页,发生“闪烁”
//页面滑入,要显示的页面
this.slipIn = function(pageNo){
$("#supplierListPage_"+pageNo).addClass("slip_in_animation");
}; //页面滑出,
this.slipOut = function(pageNo){
$("#supplierListPage_"+pageNo).addClass("slip_out_animation"); //移除上一页,定时比动画稍短,避免闪烁
setTimeout(function(){
$("#supplierListPage_"+pageNo).remove();
},900);
};
翻页的逻辑,第一次不滚动;滚到头,把最后一页飞出,第一页飞入。
this.switchNext = function(pageNo){
//附加生成新的页面
var newPageHtml = _this.makePageHtml(pageNo);
$("#"+ _this.containerId).append(newPageHtml);
//多于一页的情况
if(_this.firtshow){
_this.firtshow= false;
//第一次换页 不需要移除之前页面。
}else{
//前面已经有显示过的页面,需要把前面的页面滚动出去。
var olderPage = pageNo -1;
if(olderPage <=0){
//当前页是第一个,前一页就是最后一页
olderPage = _this.totalPage;
}
_this.slipOut(olderPage);
}
_this.slipIn(pageNo);
};
定时滚动到下一页。如果是最后一页,重新开始第一页。
this.startRolling = function(){
_this.switchNext(_this.curPage);
//按间隔轮播
_this.switchTimer = setInterval(function(){
if(_this.totalPage == 1)
return;
if(_this.curPage < _this.totalPage) {
_this.curPage++;
}else{
_this.curPage = 1;
}
_this.switchNext(_this.curPage);
},_this.switchInterval);
};
写到这里,下面是完整代码,需要的可以参考。
完整的代码CSS:

.slip_in_animation{
animation: slip_in 1s;
}
.slip_out_animation{
animation: slip_out 1s;
}
/*右侧滑入*/
@keyframes slip_in
{
from {transform:translateX(100%);}
to {transform:translateX(0);}
}
/*右侧滑入*/
@keyframes slip_out
{
from {transform:translateX(0);}
to {transform:translateX(-100%);}
}
完整JS:

function SupplierListTable(){
var _this = this;
//echart 图表对象。
//轮播间隔 毫秒
this.switchInterval = 5000;
//当前轮播的页,从1开始
this.curPage=1;
//每页条数
this.pageSize = 5;
//当前数据对应总页数
this.totalPage = 0;
//数据列表
this.chartDataList = new Array();
//第一次展示标志
this.firtshow =true;
this.containerId = null;
//轮播定时器
this.switchTimer = null;
this.init = function(containerId){
_this.containerId = containerId;
//初始化图表
$("#"+containerId).html("");
_this.reloadData(containerId);
};
this.getTotalPage = function(){
var totalPage = Math.ceil(_this.chartDataList.length/_this.pageSize);
return totalPage;
};
this.reloadData =function(containerId){
//从网络请求数据。
setTimeout(function(){
_this.chartDataList= [
{name:"供应商1",percent:"12%"},
{name:"供应商2",percent:"13%"},
{name:"供应商3",percent:"14%"},
{name:"供应商4",percent:"15%"},
{name:"供应商5",percent:"16%"},
{name:"供应商6",percent:"13%"},
{name:"供应商7",percent:"14%"},
{name:"供应商8",percent:"15%"},
{name:"供应商9",percent:"16%"}
];
_this.totalPage = _this.getTotalPage();
_this.curPage = 1;
_this.stopRolling();
_this.startRolling();
},300);
};
this.stopRolling= function(){
if(_this.switchTimer != null){
clearInterval(_this.switchTimer);
_this.switchTimer = null;
_this.curPage = 0;
}
};
this.startRolling = function(){
_this.switchNext(_this.curPage);
//按间隔轮播
_this.switchTimer = setInterval(function(){
if(_this.totalPage == 1)
return;
if(_this.curPage < _this.totalPage) {
_this.curPage++;
}else{
_this.curPage = 1;
}
_this.switchNext(_this.curPage);
},_this.switchInterval);
};
this.switchNext = function(pageNo){
//附加生成新的页面
var newPageHtml = _this.makePageHtml(pageNo);
$("#"+ _this.containerId).append(newPageHtml);
//多于一页的情况
if(_this.firtshow){
_this.firtshow= false;
//第一次换页 不需要移除之前页面。
}else{
//前面已经有显示过的页面,需要把前面的页面滚动出去。
var olderPage = pageNo -1;
if(olderPage <=0){
//当前页是第一个,前一页就是最后一页
olderPage = _this.totalPage;
}
_this.slipOut(olderPage);
}
_this.slipIn(pageNo);
};
//生成指定页的html。
this.makePageHtml = function(pageNo){
var startRecIndex= _this.pageSize * (pageNo - 1);
var endRecIndex = _this.pageSize * pageNo ;
if(endRecIndex > _this.chartDataList.length){
endRecIndex = _this.chartDataList.length;
}
var html = "<div style='width: 100%; box-sizing: border-box;position: absolute;padding: 20px;' id='supplierListPage_" +pageNo+"'>";
for (var i = startRecIndex; i < endRecIndex; i++) {
html+= "<div style=' margin-bottom: 10px ;border-bottom: 1px solid #484752;'><span style='color: white'>" +_this.chartDataList[i].name+"</span> <span style='float: right;color: #0c9c6e'>"+_this.chartDataList[i].percent+"</span></div>"
}
html+="</div>"
return html;
};
//页面滑入,要显示的页面
this.slipIn = function(pageNo){
$("#supplierListPage_"+pageNo).addClass("slip_in_animation");
};
//页面滑出,
this.slipOut = function(pageNo){
$("#supplierListPage_"+pageNo).addClass("slip_out_animation");
//移除上一页,定时比动画稍短,避免闪烁
setTimeout(function(){
$("#supplierListPage_"+pageNo).remove();
},900);
};
}
$(document).ready(function(){
var containerId = 'supplierListChart';
var supplierListTable = new SupplierListTable();
supplierListTable.init(containerId);
});
HTML页面容器:

<div style="height: 300px;width:400px;overflow-x: hidden;position: relative" id="supplierListChart" >
</div>
前端开发日常——CSS动画无限轮播的更多相关文章
- css动画属性--轮播图效果
通过css的动画属性实现轮播图的显示效果 代码如下: 主体部分: <div id="move"> <ul> <li><img src=&q ...
- iOS开发UI篇—无限轮播(功能完善)
iOS开发UI篇—无限轮播(功能完善) 一.自动滚动 添加并设置一个定时器,每个2.0秒,就跳转到下一条. 获取当前正在展示的位置. [self addNSTimer]; } -(void)addNS ...
- iOS开发UI篇—无限轮播(循环利用)
iOS开发UI篇—无限轮播(循环利用) 一.无限轮播 1.简单说明 在开发中常需要对广告或者是一些图片进行自动的轮播,也就是所谓的无限滚动. 在开发的时候,我们通常的做法是使用一个UIScrollV ...
- iOS开发UI篇—无限轮播(新闻数据展示)
iOS开发UI篇—无限轮播(新闻数据展示) 一.实现效果 二.实现步骤 1.前期准备 (1)导入数据转模型的第三方框架MJExtension (2)向项目中添加保存有“新闻”数据的pli ...
- iOS开发UI篇—无限轮播(循环展示)
iOS开发UI篇—无限轮播(循环展示) 一.简单说明 之前的程序还存在一个问题,那就是不能循环展示,因为plist文件中只有五个数组,因此第一个和最后一个之后就没有了,下面介绍处理这种循环展示问题的小 ...
- ViewPager无限轮播与自定义切换动画
一直在寻求一个能用得长久的ViewPager,寻寻觅觅终于发现,ViewPager有这一个就够了. 注:并非完全原创 先看一下效果: 淡入淡出: 旋转: 无限轮播的ViewPager 主要设计思路(以 ...
- iOS项目开发之实现无限轮播
简介 分析 实现 代码下载 一.简介 在实际的开发当中,会经常有界面需要实现图片的无限轮播这样的需求.比如新闻app,或者其他app的广告位 实现的方式有很多种,最先想动的一定是scrollView, ...
- iOS开发之三个Button实现图片无限轮播(参考手机淘宝,Swift版)
这两天使用Reveal工具查看"手机淘宝"App的UI层次时,发现其图片轮播使用了三个UIButton的复用来实现的图片循环无缝滚动.于是乎就有了今天这篇博客,看到“手机淘宝”这个 ...
- Android之仿京东淘宝的自动无限轮播控件
在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于Re ...
随机推荐
- MyBatis 02 配置
导入jar包 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</a ...
- [游记]CSP 2021 J/S
这一次,也许是我的OI生涯的转折点了--能过,学习OI的时间就不会减少:但不能过,就会减少学习OI的时间-- 上午(S组) 6:00起床.去吃早餐,结果因为边喝粥边喝牛奶导致肚子疼.(我在这里劝大家, ...
- DevOps落地实践点滴和踩坑记录-(2) -聊聊平台建设
很久没有写文章记录了,上一篇文章像流水账一样,把所见所闻一个个记录下来.这次专门聊聊DevOps平台的建设吧,有些新的体会和思考,希望给正在做这个事情的同学们一些启发吧. DevOps落地实践点滴和踩 ...
- Mybatis核心配置文件中的标签介绍
0. 标签顺序 Mybatis核心配置文件中有很多标签,它们谁谁写在前写在后其实是有顺序要求的: 从前到后: properties?,settings?,typeAliases?,typeHandle ...
- Java SE 13 新增特性
Java SE 13 新增特性 作者:Grey 原文地址:Java SE 13 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- 逐层阅读 research paper:Dmitry Berenson 的方法论
本博客翻译了 这篇文章,包含很实用的 读论文的方法论. 读论文的四个 layers 在读论文之前,要首先搞清楚,自己读论文的目的是什么,或者 希望读到什么程度. 下表列出了常见的读论文目的,以及相应的 ...
- 员工离职困扰?来看AI如何解决,基于人力资源分析的 ML 模型构建全方案 ⛵
作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 机器学习实战系列:https://www.showmeai.tech/t ...
- Unity-编辑器拓展之GUILayout,EditorGUILayout布局 { }
Unity 脚本 API 中文版 链接: https://docs.unity3d.com/cn/2019.4/ScriptReference/ 创建自定义窗口 public class MyWind ...
- 0.web理解
web前后端 网站的前端:通过用户肉眼看到的网站的布局内容,对网站的操作的功能,可以让用户可以直接接触与操作的部分. 用户通过访问前端的功能,前端分为 静态功能+动态功能 静态功能:静态功能则不会和后 ...
- VLAN的配置
1 vlan的概念和作用 虚拟局域网(VLAN)是一组逻辑上的设备和用户,这些设备和用户并不受物理位置的限制,可以根据功能.部门等因素将它们组织起来.相互之间的通信就好像它们在同一个网段中一样. 虚拟 ...