JS实现焦点图轮播效果
大家平时逛淘宝网的时候,在首页就能看到焦点图轮播的效果,就是这个样子的:
PS:想起每每打开淘宝,总会被这个玩意先夺眼球,偶尔还去点进去溜溜,幸好我定力好,总能控制住自己的购买欲望,为自己不用剁手感到欣慰 ! 好吧,其实说白了就是穷,就是没钱,就是不能好好地任性,所以只能先去慕课网找教程学习把它给做出来!
OK,首先将HTML结构搭建好先:
<div id="container"> <div id="list" style="left: -600px;"> <img src="img/5.jpg" alt="1"/> <img src="img/1.jpg" alt="1"/> <img src="img/2.jpg" alt="2"/> <img src="img/3.jpg" alt="3"/> <img src="img/4.jpg" alt="4"/> <img src="img/5.jpg" alt="5"/> <img src="img/1.jpg" alt="5"/> </div> <div id="buttons"> <span index="1" class="on"></span> <span index="2"></span> <span index="3"></span> <span index="4"></span> <span index="5"></span> </div> <a href="javascript:;" id="prev" class="arrow"><</a> <a href="javascript:;" id="next" class="arrow">></a> </div>
最外层div就是容器啦,然后其子元素分别就是存放图片的id为list的div,存放小圆圈按钮的id为buttons的div,最后两个a标签就是左右切换的按钮。还有一个问题需要注意,此焦点图轮播器其实只有五张图,但是在id为list的div里却放了七张图,这是为啥呢?其原理是:第一张图片(5.jpg)和最后一张图片(1.jpg)的作用是为了实现无限滚动的效果,因为此效果是通过设置id为list的div容器的left值来实现图片切换的,所以当轮播到第五张图片(5.jpg)的时候,再进行向右切换的时候,这时最后一张图片被切换进来,此时left值已经为-3600px,并且同时我们又将其left值改为-600px,这样就回到了真正的第一张图。由于最后一张图片就是第一张图片(1.jpg),所以用户肉眼看上去没有什么变化,就这样实现了无限滚动的效果,其他同理!那么如果没有那两张图片作为过渡的话,效果就会是这样,当轮播到最后一张的时候会闪一下就没有了:
设置CSS样式:
*{ margin: 0; padding: 0; } a{ text-decoration: none; } body { padding: 20px; } #container { width: 600px; /*这里600x400是图片的宽高*/ height: 400px; border: 3px solid #333; overflow: hidden; /*隐藏溢出的图片,因为图片左浮动,总宽度为4200*/ position: relative; } #list { width: 4200px; /*这里设置7张图片总宽度*/ height: 400px; position: absolute; /*基于父容器container进行定位*/ z-index: 1; } #list img { float: left; } #buttons { position: absolute; height: 10px; width: 100px; z-index: 2; /*按钮在图片的上面*/ bottom: 20px; left: 250px; } #buttons span { cursor: pointer; float: left; border: 1px solid #fff; width: 10px; height: 10px; border-radius: 50%; background: #333; margin-right: 5px; } #buttons .on { background: orangered; /*选中的按钮样式*/ } .arrow { cursor: pointer; display: none; /*左右切换按钮默认先隐藏*/ line-height: 39px; text-align: center; font-size: 36px; font-weight: bold; width: 40px; height: 40px; position: absolute; z-index: 2; top: 180px; background-color: RGBA(0,0,0,.3); color: #fff; } .arrow:hover { background-color: RGBA(0,0,0,.7); } #container:hover .arrow { display: block; /*当鼠标放上去容器上面就显示左右切换按钮*/ } #prev { left: 20px; } #next { right: 20px; }
样式不难,主要就是根据实际情况修改一下图片尺寸就行了。因为图片组都左浮动,所以宽度远远大于父容器的宽度,如果没有设置overflow: hidden; 效果就是这样子:
好了,最重要的还是JS实现轮播效果:
首先来实现最简单的通过左右按钮来实现切换:
window.onload = function () { var container = document.getElementById('container'); var list = document.getElementById('list'); var buttons = document.getElementById('buttons').getElementsByTagName('span'); var prev = document.getElementById('prev'); var next = document.getElementById('next'); //切换动画 function animate (offset) { list.style.left = parseInt(list.style.left) + offset+ 'px'; } next.onclick = function () { animate(-600); } prev.onclick = function () { animate(600); } }
这样就能简单的实现了切换效果,但是当切换到最后一张再向右切换时就会出现上面所讲的空白的现象,所以呢,就需要通过判断list的left值如果大于-600(-600是默认设置的,为了显示第一张图片[1.jpg])就将其设置为-3000,如果小于-3000,就将其设置为-600,这样就能实现无线滚动了,但是又会发现当图片切换滚动的时候,小按钮并没有跟着改变,这时我们就需要通过一个index值(默认为1)来索引当前是哪个小按钮被选中,并为其添加.on的类,在添加之前需要将原先有.on的小按钮的class移除掉,最后一点是由于小按钮只有五个,想要实现无限切换,就需要判断边界值,当index为1时,如果还想往左切换的话,就将其设置为5,这样就会回到第五个小按钮上,其他同理。
window.onload = function () { var container = document.getElementById('container'); var list = document.getElementById('list'); var buttons = document.getElementById('buttons').getElementsByTagName('span'); var prev = document.getElementById('prev'); var next = document.getElementById('next'); var index = 1; //用于索引当前按钮 function animate (offset) { var newLeft = parseInt(list.style.left) + offset;
list.style.left = newLeft+ 'px';
if(newLeft < -3000){
list.style.left = –600 + 'px';
}
if(newLeft > -600){
list.style.left = –3000 + 'px';
}
} //用于为按钮添加样式 function showButton() { //先找出原来有.on类的按钮,并移除其类 for (var i = 0; i < buttons.length ; i++) { if( buttons[i].className == 'on'){ buttons[i].className = ''; break; } } //为当前按钮添加类,索引下标从0开始,故需减1 buttons[index - 1].className = 'on'; } next.onclick = function () { if (index == 5) { index = 1; } else { index += 1; } animate(-600); showButton(); } prev.onclick = function () { if (index == 1) { index = 5; } else { index -= 1; } animate(600); showButton(); } }
接下来需要通过点击小按钮来实现切换效果,不像左右切换,按钮是可以随意点击进行切换的,比如从第一个按钮直接点击第五个按钮,这样的话,就不是每次都是-600的间隔了,我们因此还需要获取当前点击的按钮和之前的按钮的index值的差值,然后乘以-600得到的才是真正的偏移量,并且同时点击的时候,为该按钮添加选中样式类。但是如何知道当前点击的是哪个按钮呢,还记得我们在按钮的span标签里设置了自定义属性index吗,其值分别对应每个按钮的索引值,这样当点击按钮时通过获取该按钮的index属性值即可知道是哪个按钮,最后一点就是当继续点击当前按钮时,比如此时轮播到第一张图片,你再点击对应的第一个按钮,应该阻止再次切换,做到优化。
window.onload = function () { var container = document.getElementById('container'); var list = document.getElementById('list'); var buttons = document.getElementById('buttons').getElementsByTagName('span'); var prev = document.getElementById('prev'); var next = document.getElementById('next'); var index = 1; //用于索引当前按钮 function animate (offset) {
var newLeft = parseInt(list.style.left) + offset;
list.style.left = newLeft+ 'px';
if(newLeft < -3000){
list.style.left = –600 + 'px';
}
if(newLeft > -600){
list.style.left = –3000 + 'px';
}
} //用于为按钮添加样式 function showButton() { //先找出原来有.on类的按钮,并移除其类 for (var i = 0; i < buttons.length ; i++) { if( buttons[i].className == 'on'){ buttons[i].className = ''; break; } } //为当前按钮添加类 buttons[index - 1].className = 'on'; } next.onclick = function () { if (index == 5) { index = 1; } else { index += 1; } animate(-600); showButton(); } prev.onclick = function () { if (index == 1) { index = 5; } else { index -= 1; } animate(600); showButton(); } //通过循环为按钮添加点击事件 for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = function () { //当继续点击当前按钮的时候,不进行切换 if(this.className == 'on') { return; } //通过获取按钮标签的自定义属性index,得到索引值,再而计算差值 var myIndex = parseInt(this.getAttribute('index')); //真正的便宜量 var offset = -600 * (myIndex - index); animate(offset); //将点击按钮的index属性值设置为当前的index值 index = myIndex; showButton(); } } }
接着实现平滑切换的效果,之前已经实现的效果是直接切换,而我们想要的是能够平滑过渡,体验会好一些。主要实现方法是通过定时器setTimeout。设置切换需要的总时间,每次间隔多少时间,然后求出每次切换过渡的位移量,判断是否到达目标值,若否,则继续执行定时器进行位移。还有一点就是,如果连续点击切换按钮,图片会立刻不停地切换, 但我们想要的效果是等当前图片切换完成之后再进行下一次切换,这个可以优化一下。最后实现自动播放效果,当鼠标不点击时,它能自动播放,这里用到setInterval定时器,每次3秒执行一次点击事件,而当鼠标移上去的时候清除该事件,离开的时候又自动播放。OK,整理一下代码:
window.onload = function () { var container = document.getElementById('container'); var list = document.getElementById('list'); var buttons = document.getElementById('buttons').getElementsByTagName('span'); var prev = document.getElementById('prev'); var next = document.getElementById('next'); var index = 1; //用于索引当前按钮 var len = 5; //图片的数量 var animated = false; //用于判断切换是否进行 var interval = 3000; //自动播放定时器秒数,这里是3秒 var timer; //定时器 function animate (offset) { animated = true; //切换进行中 var time = 300; //位移总时间 var inteval = 10; //位移间隔时间 var speed = offset/(time/inteval); //每次位移量 var left = parseInt(list.style.left) + offset; //目标值 var go = function (){ //这两种情况表示还在切换中 if ( (speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left)) { list.style.left = parseInt(list.style.left) + speed + 'px'; setTimeout(go, inteval); //继续执行切换go()函数 } else { list.style.left = left + 'px'; if(left>-600){ list.style.left = -600 * len + 'px'; } if(left<(-600 * len)) { list.style.left = '-600px'; } animated = false; //切换完成 } } go(); } //用于为按钮添加样式 function showButton() { //先找出原来有.on类的按钮,并移除其类 for (var i = 0; i < buttons.length ; i++) { if( buttons[i].className == 'on'){ buttons[i].className = ''; break; } } //为当前按钮添加类 buttons[index - 1].className = 'on'; } //自动播放 function play() { timer = setTimeout(function () { next.onclick(); play(); }, interval); } //清除定时器 function stop() { clearTimeout(timer); } //右点击 next.onclick = function () { if (animated) { //如果切换还在进行,则直接结束,直到切换完成 return; } if (index == 5) { index = 1; } else { index += 1; } animate(-600); showButton(); } //左点击 prev.onclick = function () { if (animated) { //如果切换还在进行,则直接结束,直到切换完成 return; } if (index == 1) { index = 5; } else { index -= 1; } animate(600); showButton(); } for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = function () { if (animated) { //如果切换还在进行,则直接结束,直到切换完成 return; } if(this.className == 'on') { //如果点击的按钮是当前的按钮,不切换,结束 return; } //获取按钮的自定义属性index,用于得到索引值 var myIndex = parseInt(this.getAttribute('index')); var offset = -600 * (myIndex - index); //计算总的位移量 animate(offset); index = myIndex; //将新的索引值赋值index showButton(); } } container.onmouseover = stop;//父容器的移入移出事件 container.onmouseout = play; play(); //调用自动播放函数 }
OK, 这样就做完了,如果还不理解,可以直接去慕课网看一下教程:http://www.imooc.com/learn/18