学习了轮播,知道轮播有好多种,还有很多插件,但是这种东西,就和学习原生JS与jQuery一样,废话不多说;今天要总结的是轮播之 DOM搬运
,因为阿里用的DOM Clone篇
我后一篇再来讲,当然有时间也会讲讲京东的Z-index
篇;
首先看看效果图,有一个直观的了解
Setp0: HTML构建及CSS的要点
首先,我是用的这种结构
<div class="wrap">
<ul class="ct clearfix">
<li><img data-img='0' src="img/tifa.png"></li>
<li><img data-img='1' src="img/cloud.png"></li>
<li><img data-img='2' src="img/yuffie.png"></li>
<li><img data-img='3' src="img/barret.png"></li>
</ul>
<a class="arrow pre" href="#"><</a>
<a class="arrow next" href="#">></a>
<ul class="bullet clearfix">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
那么CSS中需要注意的是,
.wrap
的position:relative因为他是镜头,是不能变化的,同时宽高都是你的图的大小,最后overflow:hidden,作用是让其他的图片都不要出现,只留下镜头内的;这里注意overflow:hidden对position:absolute的子元素都是有效的;还有就是.ct
的position:absolute,我称之为图片队列,如果不设置这样,图片就不能横过来,就竖着成了一条了,还有图片要float:left,之后还要记得清除浮动啊~~
如果你不上overflow:hidden,就会更加直观的看到这些图如何在运作
Setp1: JavaScript 声明 和 对DOM进行一些操作
var $wrap = $('.wrap'),
$ct = $('.ct'),
$pre = $('.pre'),
$next = $('.next'),
$items = $ct.children(),
$bullet = $('.bullet'),
imgWidth = $items.width(),
imgCount = $ct.children().length;
var isAnimate = false,//状态锁
nowIdx = 0;//意思是现在是第几张,需要展现哪个图,后续会多次提到
对DOM的一些操作就是
$ct.css({width: imgWidth * imgCount});
//这里就是让我们的图片队列的宽度根据你有多少内容来,免得CSS写死了
Setp2: 点击上一个如何解决?
$pre.on('click',function () {
playPre();
});
function playPre (idx) {
var idx = idx || 1;//如果有点击就有idx,放着让他自动就是1
if(!isAnimate){
isAnimate = true;
//用了遍历,正好符合挪动的次数
for(var i = 0;i < idx;i++){
$ct.children().last().prependTo($ct);
}
$ct.css('left',0-(imgWidth*idx));
$ct.animate({ left:'+=' + (imgWidth*idx) },function () {
nowIdx = (imgCount+nowIdx-idx)%imgCount;
setBullet();
isAnimate = false;
});
}
}
请注意:这里 有一个我认为第一重要的问题:
因为
.wrap
是一个镜头,是不动的,这个镜头一开始对准了nowIdx
图,要发生向前移动时,会先抽走.ct
的最后一个li的DOM,添加到最前面的时候,相当于将原来镜头对准的图向后顺延了一样,其实这里就已经够了,css
操作和animate
操作都可以不要了,就是动画效果是闪现的;
为什么是闪现的?
这类似插队一样,后面的跑到前面来,本来一个固定的镜头看着你,就会因为顺位变化,镜头就会看着你的前面一个人但是这种效果是是DOM操作,特别快,造成闪现,所以需要用.css这种也很快的方法给修补回来这种修补类似与把你的整个队伍向前推动一个距离,让你再次回到镜头下面,一切发生的太快,镜头依旧看着你,仿佛没有插队接下来运行到animate操纵整个队伍,向右边缓慢移动,让镜头慢慢对准你前面的那一位,就出现了一个过渡的动画
Setp3: 点击下一个如何解决?
$next.on('click',function () {
playNext();
});
function playNext(idx){
var idx = idx || 1;
if(!isAnimate){
isAnimate = true;
$ct.animate({ left:'-=' + (imgWidth*idx) },function () {
nowIdx = (nowIdx+idx)%imgCount;
//这里和上面一样,都是为了让nowIdx正确的显示
for(var i = 0; i < idx; i++){
$ct.children().first().appendTo($ct);
}
$ct.css('left',0);
setBullet();
isAnimate = false;
});
}
}
这里也有一个第二重要的问题:
animate
把整个图片队列向左边推动之后,需要重新用css操作DOM极快的把队伍拉回来如果不拉回来,镜头里面就会显示,动画效果挪动到你需要的图片上,但是瞬间闪到下idx个图上,因为DOM在appendTo
之后会重新组合,镜头会对准重组之后的队列里面本应该对着的下idx个图,如果不修正,图就会跑没了为了避免这种状况,需要重新将队伍给拉回来,让nowIdx
的图回到固定镜头.wrap
下面
Setp4: 如何解决点击下面,产生连续过几张图的问题?
$bullet.find('li').on('click',function(){
var idx = $(this).index();
if (idx < nowIdx){
playPre(nowIdx-idx);
}
else if (idx > nowIdx){
playNext(idx-nowIdx);
}
});
利用不同的大小来判断,是前进多少,还是后退多少,那么上面那么多setBullet(),这是干嘛的呢?
Setp5: 下面小长条的问题
function setBullet(){
$bullet.find('li').removeClass('active').eq(nowIdx).addClass('active');
}
这里和tab切换的思路有一点类似的地方
Setp6: 怎么让界面自己就开始动呢?
就是setInterval();
function autoPlay () {
setInterval(function(){
playNext();
}, 2500);
}
应该还有很多纰漏,我的 Github 上有这个;如果这篇博客有幸被别人看到的话: