js实现轮播图
1.普通轮播图
html
页面展示区为wrap,里面第一部分是大图,第二部分是索引点,第三部分是向前向后按钮。
<div class="wrap">
<ul class="list">
<li class="item active"><img src="./images/images/1.jpg"></li>
<li class="item"><img src="./images/images/2.jpg"></li>
<li class="item"><img src="./images/images/3.jpg"></li>
<li class="item"><img src="./images/images/4.jpg"></li>
<li class="item"><img src="./images/images/5.jpg"></li>
</ul>
<ul class="pointList">
<li class="point active"></li>
<li class="point"></li>
<li class="point"></li>
<li class="point"></li>
<li class="point"></li>
</ul>
<button class="button prev"><</button>
<button class="button next">></button>
</div>
css
布局:让五张照片叠在一起。
<style>
* {
margin: 0;
padding: 0;
box-sizing: content-box;
}
.wrap {
position: relative;
width: 400px;
height: 320px;
}
.list {
width: 400px;
height: 320px;
list-style: none;
position: relative;
}
.item {
width: 400px;
position: absolute;
} /*五张照片叠在一起。*/
.button {
width: 20px;
height: 40px;
position: absolute;
top: 140px;
z-index: 100; /*按钮显示优先级最高*/
opacity: 0;
}
.prev {
left: 5px;
}
.next {
right: 5px;
}
.item.active {
z-index: 10; /*哪张图片被加了active,哪张图片的显示优先级最高。*/
}
.pointList {
list-style: none;
position: absolute;
right: 10px;
bottom: 10px;
z-index: 30; /*要设置z-index,否则默认为0,显示不出来。*/
}
.point{
width: 20px;
height: 20px;
background-color: darkred;
border-radius: 50%;
float: left;
margin-left: 5px;
cursor: pointer;
}
.point.active {
background-color: red;
}
</style>
JavaScript
原理:给哪张图片添加类active,哪张图片就在最上面。(设置z-index)
<script>
window.onload = function(){
//1.获取元素
var wrap = document.getElementsByClassName('wrap')[0];
var items = document.getElementsByClassName('item');
var prev = document.getElementsByClassName('prev')[0];
var next = document.getElementsByClassName('next')[0];
var pointList = document.getElementsByClassName('pointList')[0];
var points = pointList.getElementsByClassName('point');
/*2.按钮控制的向左向右*/
/*整个逻辑主要是在操作index*/
var index= 0; /*index表示第几张图片在展示。*/
var clearActive = function(){
for(var i = 0;i<items.length;i++)
{
items[i].className = 'item';
points[i].className = 'point'; /*先清除掉所有的active*/
}
};
var goIndex = function (){
clearActive();
items[index].className = 'item active';/*设置第index张图片有active这个类名。*/
points[index].className = 'point active';/*设置第index个索引点有active这个类名*/
};
var goNext = function(){
if(index >= 4)
{
index = 0
}else{
index++;
}
goIndex();
};
var goPrev = function(){
if(index <= 0)
{
index = 4
}else{
index--;
}
goIndex();
};
next.onclick = function(){
goNext();
};
prev.onclick = function(){
goPrev();
};
/*3.索引点控制的轮播图*/
for(var i=0; i<points.length;i++)
{
points[i].index = i;/*给point[i]一个index属性,表示索引点对应的图片的index*/
points[i].onmouseover = function(){
index = this.index;
goIndex();
}
}
/*4.定时器控制的轮播图*/
var timer;
var autoSlide = function() {
timer = setInterval(function(){
goNext();
},2000)
};
autoSlide();
wrap.onmouseover = function(){
clearInterval(timer);
prev.style.opacity = '1';
next.style.opacity = '1';
};
wrap.onmouseout = function(){
autoSlide();
prev.style.opacity = '0';
next.style.opacity = '0';
}
}
</script>
2.无缝滚动轮播
html
<div id="box">
<div id="slider">
<div class="item"><img src="./images/images/5.jpg"></div>
<div class="item"><img src="./images/images/1.jpg"></div>
<div class="item"><img src="./images/images/2.jpg"></div>
<div class="item"><img src="./images/images/3.jpg"></div>
<div class="item"><img src="./images/images/4.jpg"></div>
<div class="item"><img src="./images/images/5.jpg"></div>
<div class="item"><img src="./images/images/1.jpg"></div>
</div>
<span id="prev"><</span>
<span id="next">></span>
<ul id="nav">
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
css
#slider相对#box进行定位。
<style>
* {
padding: 0;
margin: 0;
box-sizing: content-box;
}
#box {
width: 400px;
height: 320px;
position: relative;
overflow: hidden;
}
#slider {
width: 2800px;
height:320px;
position: absolute;
left: -400px;
}
.item {
width: 400px;
height: 320px;
float: left;
}
#prev {
font-size: 2em;
position: absolute;
top: 140px;
left: 2px;
background-color: red;
cursor: pointer;
opacity: 0;
}
#next {
font-size: 2em;
position: absolute;
top: 140px;
right: 2px;
background-color: red;
opacity: 0;
cursor: pointer;
}
#nav {
position: absolute;
bottom: 5px;
left: 125px;
list-syle: none;
}
#nav li {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #ccc;
float: left;
margin-left: 15px;
}
#nav li.active {
background-color: red;
}
</style>
JavaScript
原理:slider相对box的定位left发生改变,每次移动的值是一张图片的宽度。
- 首先封装animate函数。animate函数是一个多目标缓冲运动框架。这个函数定义了对象obj朝向目标json的缓冲运动。
//获取非内联样式。
function getStyle(obj,name){
if(obj.currentStyle){
return oDiv1.currentStyle[name];
}else{
return getComputedStyle(obj,null)[name];
}
}
//animate(odiv,{width: 100,height: 200,opacity: 100},)
//封装一个animate函数,用于动画。
function animate(obj,json,callback){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
for(var attr in json)
{
var isStop = true; //一开始假设所有属性都到了目标值,因为有好几个属性。这里是设置一个状态标志。
var now;
if(attr === 'opacity')
{
now = parseFloat(getStyle(obj,attr))*100;
}
else{
now = parseInt(getStyle(obj,attr));
}
var speed = (json[attr]-now)/10;
speed = speed>0?Math.ceil(speed):Math.floor(speed);/*Math.ceil():向上取整,Math.floor():向下取整。*/
if(attr === 'opacity')
{
obj.style.opacity = (now + speed)/100;
}else{
obj.style[attr] = now +speed+'px';
}
if(now!== json[attr])
{
isStop = false; /*只要有一个不到目标值,就为false*/
}
}
if(isStop) /*所有的值都到了目标值才能清除定时器*/
{
clearInterval(obj.timer);
if(callback){
callback();
}
}
},50)
}
-
通过调用animate函数,设置目标left为对应的值,就可以移动一次。要实现自动轮播,在外面加一个定时器就可以了。
但实现难点在于:怎么实现无缝轮播。
办法:
当图片1向前切换到图片5时,迅速切换到后面的图片5;
当图片5向后切换到图片1时,迅速切换到前面的图片1。/*要实现自动轮播,就要给图片一个索引值*/ var index = 0; /*一开始默认left是-400*/ setInterval(function () { index++; animate(slider,{left: -400*(index+1)},function(){ if(index === 5) { slider.style.left = '-400px';/*每次运动完用回调函数判断index*/ index = 0; } }) }, 2000) //这样实现了向下一张的无缝轮播
var timer; var index = 0; var slideNext = function(){ index++; animate(slider,{left: -400*(index+1)},function(){ if(index === 5) { slider.style.left = '-400px'; index = 0; } }) } var slidePre = function(){ index --; animate(slider,{left: -400*(index+1)},function(){ if(index === -1) { slider.style.left = '-2000px'; index = 4; } }) } timer = setInterval(slideNext,2000); box.onmouseover = function(){ animate(prev,{opacity:50}); animate(next,{opacity:50}); clearInterval(timer); }; box.onmouseout = function(){ animate(prev,{opacity:0}); animate(next,{opacity:0}); timer = setInterval(slideNext,2000) }; next.onclick = slideNext; prev.onclick = slidePre;
- 导航点的点击事件
功能:导航点点击,left定位到对应的图片
for(var i= 0;i<lis.length;i++) { lis[i].idx = i;/*给每个导航点一个属性idx*/ lis[i].onclick = function(){ index = this.idx; animate(slider,{left:-400*(index+1)}) } }
- 导航点的点击事件
-
当图片发生变化,要对应的导航点变化。
var change = function(){ for(var i = 0;i<lis.length;i++) { lis[i].className = ''; } lis[index].className = 'active'; } //将change方法在slideNext、slidePre和导航点击事件中调用。
但是出现了问题: 当图片变化到index为5和-1时,图片是可以继续变化但是导航点并没有这个索引点。所以将这两个特殊情况列出来。
var change = function(){ for(var i = 0;i<lis.length;i++) { lis[i].className = ''; //清除之前的active } if(index === 5) { lis[0].className = 'active' }else if(index === -1) { lis[4].className = 'active' }else{ lis[index].className = 'active'; } }
优化
如果还没运动到对应的位置,就频繁点击左右按钮,会出现意想不到的结果,所以要优化。
实现功能:如果还在运动时,点击左右按钮时无效的
是否在运动这个状态我们可以用true和false来标记。var isMoving = false; var timer; /*要实现自动轮播,就要给图片一个索引值*/ var index = 0; /*一开始默认left是-400*/ var slideNext = function(){ if(!isMoving){ isMoving = true; index++; change(); animate(slider,{left: -400*(index+1)},function(){ if(index === 5) { slider.style.left = '-400px';/*每次运动完用回调函数判断index*/ index = 0; } isMoving = false; }) } }