一、效果预览:
由于只能上传2M以下的图片,这里只截取了自动切换的效果:
二、编写语言
HTML、CSS、原生JS
三、编写思路
(一)HTML部分
1、.slide意为滑槽,里面存放所有图片;
2、.prev存放向左的箭头,.next存放向右的箭头;
3、pointer意为指示器,存放下方的五个切换按钮,每个切换按钮用span来表示;
4、.m-view,意为视窗,即每次看到图片的窗口,它存放以上所有的部件;
(二)CSS部分
1、.m-view设为相对定位,他的后代元素可以以它作为绝对定位的参照;
2、.slide、.prev、.next、pointer全都用绝对定位放到合适位置;
3、.slide的所有图片水平排列,且视窗.m-view的宽度设为只有一张图片那么宽,这样默认情况.slide还是会全部显示;当给.m-view设置overflow:hidden后子元素超出它的部分就会隐藏,就实现了只显示一张图片的效果;
(三)JS部分
1、切换功能:
设置一个切换函数toggle实现左切或者右切一张图,toggle有两个子函数leftToggle和rightToggle分别实现向左、向右切换一张图,将他们分别绑定到.prev和.next按钮的clik事件;
2、切换功能的淡入动画效果
只有1的话切换是立即产生的,没有过渡效果;这里利用定时器和步长将切换功能细化到更小的滑动操作leftStep和rightStep,leftToggle和rightToggle通过多次调用滑动操作来实现一次切换,这样就会产生动画效果;
3、跳转功能
对指示器的每个圆形按钮绑定跳转功能,跳转实际上是将.slide进行移动;
4、自动播放
只需要设置定时器,每隔一定时间执行切换即可;
四、我的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>轮播图</title>
<style>
.m-view,.m-view .slide img{
position: relative;/*作为绝对定位的父元素*/
800px;
height: 600px;
}
.m-view{
overflow: hidden;/*将超出该div的子元素隐藏*/
}
.m-view .slide{
position: absolute;
8000px;
height: 600px;
}
.m-view .slide img{
margin-right: -5px;
}
.m-view .prev,.m-view .next{
position: absolute;
top: 40%;
font: 60px/60px Microsoft YaHei;
color: #00BFFF;
}
.m-view .prev{
left: 10px;
}
.m-view .next{
right: 10px;
}
.m-view .pointer{
position: absolute;
bottom: 40px;
left: 33%;
}
.m-view .pointer span{
display: inline-block;/*水平排列*/
40px;
height: 40px;
border-radius: 20px;
margin-right: 10px;
background-color: #00FF00;
}
.m-view .pointer .on{/*点亮当前图片对应的圆圈*/
background-color: #1E90FF;
}
</style>
</head>
<body>
<div class="m-view">
<div class="slide" style="left: -800px">
<img src="../lunbo/5.jpg" alt="4">
<img src="../lunbo/1.jpg" alt="0">
<img src="../lunbo/2.jpg" alt="1">
<img src="../lunbo/3.jpg" alt="2">
<img src="../lunbo/4.jpg" alt="3">
<img src="../lunbo/5.jpg" alt="4">
<img src="../lunbo/1.jpg" alt="0">
</div>
<div class="prev"><</div>
<div class="next">></div>
<div class="pointer">
<span class="button on" index="0"></span>
<span class="button" index="1"></span>
<span class="button" index="2"></span>
<span class="button" index="3"></span>
<span class="button" index="4"></span>
</div>
</div>
<script type="text/javascript">
var view=document.getElementsByClassName('m-view')[0];
var slide=document.getElementsByClassName('slide')[0];
var prev=document.getElementsByClassName('prev')[0];
var next=document.getElementsByClassName('next')[0];
var button=document.getElementsByClassName('button');
var curIndex=0;//当前图片的索引位置
var toggled=true;//是否正在切换,true表明切换已完成,此时才能切换
/* Toggle函数实现切换一张图片的功能 */
function Toggle () {
var TIMER=50;//滑动一次所用的时间,它是setInterval的第二个参数
var time=800;//每切换一张图片总共用的时长
var times=time/TIMER;//每切换一张图片需滑动的次数
var stepLenth=800/times;//每次滑动的步长
var leftToggle=function () {
var t1=times;
function leftStep(){
slide.style.left=parseInt(slide.style.left)+stepLenth+"px";
t1--;
if (!t1) {
clearInterval(interval);
curIndex--;
if (curIndex<0) {
slide.style.left=parseInt(slide.style.left)-4000+"px";
curIndex=4;
};
toggled=true;
};
};
if (toggled==true) {
toggled=false;
button[curIndex].className="button";
if (curIndex!=0) {
button[curIndex-1].className="button on";
}else{
button[curIndex+4].className="button on";
}
var interval=setInterval(leftStep,TIMER);
};
};
var rightToggle=function () {
var t2=times;
function leftStep(){
slide.style.left=parseInt(slide.style.left)-stepLenth+"px";
t2--;
if (!t2) {
clearInterval(interval);
curIndex++;
if (curIndex>4) {
slide.style.left=parseInt(slide.style.left)+4000+"px";
curIndex=0;
};
toggled=true;
};
};
if (toggled==true) {
toggled=false;
button[curIndex].className="button";
if (curIndex!=4) {
button[curIndex+1].className="button on";
}else{
button[curIndex-4].className="button on";
};
var interval=setInterval(leftStep,TIMER);
};
}
this.leftToggle=leftToggle;//输出对外的接口
this.rightToggle=rightToggle;
};
var toggle=new Toggle();
prev.onclick=function () {
toggle.leftToggle();
};
next.onclick=function () {
toggle.rightToggle();
};
/* 点击圆圈跳转功能 */
for (var i = 0; i < button.length; i++) {
button[i].onclick=function () {
var newIndex=parseInt(this.getAttribute("index"));
if (newIndex!=curIndex) {
var distance=-800*(newIndex-curIndex);
slide.style.left=parseInt(slide.style.left)+distance+"px";
button[curIndex].className="button";
button[newIndex].className="button on";
curIndex=newIndex;
};
};
}
/* 自动播放功能,鼠标移上去停止播放,移开再次播放 */
var intervalo=setInterval(toggle.rightToggle,3000);
view.onmouseover=function () {
clearInterval(intervalo);
}
view.onmouseout=function () {
intervalo=setInterval(toggle.rightToggle,3000);
}
</script>
</body>
</html>
五、一些总结
1、本次采用了面向对象和封装的思路,这是因为个人体会到确实面向对象的设计能使代码编写思路更加清晰,还能够免去很多冗余重复的代码,也尝试过其他书写思路,但都会使代码变得不太直观;要注意的一点就是封装后要向外提供接口,且如果是封装在一个函数中,需要实例化一个对象才能调用;
2、在.slide中设置了一个内联样式,这是因为在后面要获取并改变它的left属性,如果不采用内联样式的方法,将无法设置;因为初始时.style.left只能获取内联样式,即使采用内部样式和外部样式也会使得获取的值为undefined。当然,肯定也可以采用其他方法,但是似乎其他方案都更为复杂一些,没找到更简便的方法。
3、在前后各多放置一张图片的作用:
比如,当前是图片1,现在向左切换,可以和其他位置一样先执行统一的左移操作,这时视窗显示额外放置的图片5,再将.slide整体左移使真正的图片5显示在视窗中,这样是先出现了动画效果再“暗中移动”了.slide,就好像没移动一样,真正做到了无缝切换,逻辑也很简单;如果不放置额外的图片,就需要先将视窗左移,使图片5显示在视窗中,这样动画效果难以设置。
4、在获取每个span在它父元素的索引位置时,采用了getAttribute获取自定义的index属性的方法,其他方法肯定也有不少,但是肯定不能在循环中把i的值直接当成span的索引位置。
5、在跳转功能中,如果要跳转的正是当前的页面,应该什么也不做,这样可以优化性能 。
6、在点击左右箭头切换时,先判断上一次动画是否完成,没完成就不切换,这样可以优化性能,否则连续点击可能导致卡顿、切换效果不佳。
7、代码似乎还有可以优化的地方;
8、这个只是制作了一个轮播图,接下来考虑做一个轮播组件,似乎难度要大些,还有3D的轮播效果也想要尝试下了。