上一篇说了瀑布流,今天说一下小小幻灯片的故事。
幻灯片学名又叫 轮播。应该算是一种最常用的页面展示信息。以前由于ie6/7的拖累,导致我们只能使用,很古老的方式去兼容。(我最爱的css3啊~~~)。不过今年真的是前端的幸福年,各种 polyfill 和 shim,而且现在各大公司已经对ie6/7不予理睬,直接给他一个提醒页面(老子让你用ie6/7)。而且IE的爸爸,ms已经表态了,我当初是怎么生下你来的,太tm丑了,由于开放二胎,ms已经孵化了edge(原名斯巴达),现在基本上是前端的黄金时代了。这里我主要介绍一种比较实用的轮播效果。
简单轮播
轮播,在各大网站都是使用,比如在淘宝首页(兼容性比较好), 网易云音乐首页等等。 可以说,写轮播应该算是前端的一个必修课程吧。 我这里就挑一个最简单的实现。
这里实现轮播的技术,主要依赖与css3,js只是作为一个切换class名的作用(只要不写js都简单)。
轮播原理
这里先说一下基本原理吧, 就是将图片 向左或向右移,然后接着显示下一张,或者上一张。
特么,逗我呢。你不说我也知道哎喂。
咳咳~
我们来看一下,html部分吧。
<div class="sliderCon">
<ul>
<li class="current"><img src="http://www.w2bc.com/demo/201510/2015-10-20-html5-css3-focus-change/img/1.jpg" alt=""></li>
<li><img src="http://www.w2bc.com/demo/201510/2015-10-20-html5-css3-focus-change/img/2.jpg" alt=""></li>
<li><img src="http://www.w2bc.com/demo/201510/2015-10-20-html5-css3-focus-change/img/3.jpg" alt=""></li>
<li><img src="http://www.w2bc.com/demo/201510/2015-10-20-html5-css3-focus-change/img/4.jpg" alt=""></li>
<li><img src="http://www.w2bc.com/demo/201510/2015-10-20-html5-css3-focus-change/img/5.jpg" alt=""></li>
</ul>
</div>
这里就是通过ul包裹多个li实现的轮播。(这里需要感谢一下爱编程提供的图片)
接着重头戏就是css3。
看~
.sliderCon {
width: 100%;
max-width: 100%;
height: 100%;
position: relative;
text-align: center;
ul {
display: inline-block;
position: relative;
width: 450px;
padding: 0;
perspective: 1400px;
li {
width: 450px;
height: 290px;
position: absolute;
list-style: none;
top: 0;
left: 0;
opacity: 0;
pointer-events: none;
z-index: 1000;
text-align: center;
&.navOutNext {
animation: rotate3DSlideOutLeft 0.3s forwards;
}
&.navInNext {
animation: rotate3DSlideInRight 0.3s 0.1s forwards;
}
&.navOutPre{
animation: rotate3DSlideOutLeft 0.3s forwards;
}
&.navInPre{
animation: rotate3DSlideInRight 0.3s forwards;
}
&.current {
opacity: 1;
pointer-events: auto;
z-index: 1000;
}
}
}
}
我这里只贴出主要部分的。 其实,贴出来根本没用,需要结合js来看。
js原理解析
好吧,我继续贴哈。
js部分:
var slider = (function() {
var order = 0,
lis = $('.sliderCon li');
var toggle = (function() { //通过flag来进行切换
var current,
next,
isAnimated = false, //标识是否正在执行动画
mark = 0, //用来表示多个动画是否都结束
len = lis.length - 1; //获得总的图片框
var changeState = function() {
mark++;
if (mark === 2) {
isAnimated = false;
mark = 0;
}
}
var nextExe = (function() {
var setCurrentAnimate = function() {
this.removeEventListener(transitionName, setCurrentAnimate);
this.classList.remove("current");
this.classList.remove("navOutNext");
changeState(); //检测是否动画都执行完整
}
var setNextAnimate = function() {
this.removeEventListener(transitionName, setNextAnimate);
this.classList.add("current");
this.classList.remove('navInNext');
changeState();
}
return function() {
var current = lis[order];
order = order + 1 > len ? 0 : order + 1;
var next = lis[order]; //获取下一个元素
if (!transitionName) {
alert("你浏览器怎么这么垃圾,赶紧换一个吧");
} else {
current.addEventListener(transitionName, setCurrentAnimate);
next.addEventListener(transitionName, setNextAnimate);
}
current.classList.add('navOutNext'); //开始执行动画
next.classList.add('navInNext');
}
})();
var preExe = (function(){
var setCurrentAnimate = function() {
this.removeEventListener(transitionName, setCurrentAnimate);
this.classList.remove("current");
this.classList.remove("navOutPre");
changeState(); //检测是否动画都执行完整
}
var setPreAnimate = function(){
this.removeEventListener(transitionName, setPreAnimate);
this.classList.add("current");
this.classList.remove("navInPre");
changeState(); //检测是否动画都执行完整
}
return function(){
var current = lis[order];
order = order-1<0 ? len: order-1;
var pre = lis[order]; //获得下一个切换的元素
if (!transitionName) {
alert("你浏览器怎么这么垃圾,赶紧换一个吧");
} else {
current.addEventListener(transitionName, setCurrentAnimate);
pre.addEventListener(transitionName, setPreAnimate);
}
current.classList.add('navOutPre'); //开始执行动画
pre.classList.add('navInPre');
}
})();
return function(flag) { //入口函数
if (isAnimated) return; //如果正在执行动画则退出
isAnimated = true; //标识正在执行动画
if (flag === "next") {
nextExe();
}else if(flag==="pre"){
preExe();
}
}
})();
setInterval(function() {
toggle("pre");
}, 1000);
})();
由于我过度的使用了闭包和高阶函数,所以看起来会有点累哈。不急,同样,一个程序我们先找入口函数。
可以看出。入口函数就是toggle(就是使用return 的那部分);
return function(flag) { //入口函数
if (isAnimated) return; //如果正在执行动画则退出
isAnimated = true; //标识正在执行动画
if (flag === "next") {
nextExe();
}else if(flag==="pre"){
preExe();
}
}
isAnimated只是个标识符,用来表示是否正在执行动画。通过传入的flag来表示向前切换还是向后切换。如果向后接环则执行nextExe函数。好,我们来看一下nextExe函数。
切换动画函数
var nextExe = (function() {
var setCurrentAnimate = function() {
this.removeEventListener(transitionName, setCurrentAnimate);
this.classList.remove("current");
this.classList.remove("navOutNext");
changeState(); //检测是否动画都执行完整
}
var setNextAnimate = function() {
this.removeEventListener(transitionName, setNextAnimate);
this.classList.add("current");
this.classList.remove('navInNext');
changeState();
}
return function() {
var current = lis[order];
order = order + 1 > len ? 0 : order + 1;
var next = lis[order]; //获取下一个元素
if (!transitionName) {
alert("你浏览器怎么这么垃圾,赶紧换一个吧");
} else {
current.addEventListener(transitionName, setCurrentAnimate);
next.addEventListener(transitionName, setNextAnimate);
}
current.classList.add('navOutNext'); //开始执行动画
next.classList.add('navInNext');
}
})();
对不起,吓到大家了,我这里又写了一个闭包。。。 当然,主要入口函数还是在return 后面。
order用来标识当前的元素的序号。 需要注意的是添加动画监听的那一部分。我这里使用了一个tricks(from moderniz),我贴出来吧。
动画支持检测
var transitionName = (function() {
var t;
var el = document.createElement('fakeelement');
//其实使用animated完全可以取代transition
var transitions = {
//这里是aniamted事件
'WebkitAnimation': 'webkitAnimationEnd',
'OAnimation': 'oAnimationEnd',
'msAnimation': 'MSAnimationEnd',
'animation': 'animationend'
//下面是transition事件
// 'transition':'transitionend',
// 'OTransition':'oTransitionEnd',
// 'MozTransition':'transitionend',
// 'WebkitTransition':'webkitTransitionEnd',
// 'MsTransition':'msTransitionEnd'
}
for (t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
})();
其实这个IIFE主要的功能就是检测,你的浏览器到底支持哪一个动画监听函数。 好,pass.
我们回到刚才的主函数nextExe. 接着,我们给current和next添加监听,监听函数先放着。 接着我们给current和next添加动画(就是添加class). 就这样。然后他会触发监听函数。 这里就不过多介绍了, 唯一需要提及的就是,需要在后面对监听进行解绑,避免重复绑定。
废话说完了。 直接看个实例吧。
slider实例
这应该算是最原始的轮播。 接着我们可以在上面加上一些我们想要的功能。这里我加上了一些比较常用的,比如,轮播标识符,左右翻页。
由于比较简单,我这里直接把实例贴出来。其实主要的干货就是最原始的轮播,其余的都是花花草草。
好了,大部分内容我也差不多介绍完了。
说说轮播
上面基本上把简单轮播的原理介绍一遍,虽说低版本的SB IE可能会不支持。 但这个主要取决于你产品leader的规范,如果他要求是ie9+那么你使用这个应该问题不大,就是需要处理一下动画结束事件的支持。如果甚者需要将ie8考虑进来,那么,这个应该使用css的基本属性,而不能使用css3,或者直接使用js进行改变。还是那句话,站在你的角度去造一个unique轮子,就是最好的学习。