平时中我习惯用jquery写轮播效果,实现过程不是很难,也很方便,为了加深对js面向对象的理解,我打算用面向对象实现一个简单的轮播,这里采用了字面量的方式实现。为了实现这个过程,我们要自己动手封装一个运动函数animate,在这里我采用的是匀速运动的方式,这种方式可能体验不是很好,后面分析js代码我在详细解释。废话不多说,先上代码。页面布局可以根据自己的习惯来。
html代码:
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="./css/slide .css"> <script src="./js/slide.js"></script> </head> <body> <div class="slide"> <ul class="img-box"> <li> <img src="./img/1.jpg" > </li> <li> <img src="./img/2.jpg" > </li> <li> <img src="./img/3.jpg" > </li> <li> <img src="./img/4.jpg" > </li> <li> <img src="./img/5.jpg" > </li> <div class="clear"></div> </ul> <div class="icon"> <span class="on"></span> <span></span> <span></span> <span></span> <span></span> </div> </div> </body> </html>
css代码:
*{ padding:0; margin: 0; list-style-type: none; text-decoration: none; } .clear{ clear: both; } a:hover{ text-decoration: none; } .slide{ position: relative; width: 500px; height: 300px; margin:20px auto; overflow: hidden; } .slide .img-box{ width: 10000px; position: absolute; left: 0; top: 0; } .slide .img-box li{ float: left; width: 500px; height: 300px; } .slide .img-box li img{ width:100%; height: 100%; } .icon{ position: absolute; right:8%; bottom: 6%; } .icon span{ display: block; float: left; width: 15px; height: 15px; border-radius: 50%; background: white; opacity: 0.7; margin-left: 5px; } .icon .on{ background: orange; opacity: 0.7; }
js代码:
window.onload = function () { function animate(ele, xTarget, time) { var xPos = ele.offsetLeft, //每次执行一次运动得到ele元素相对于父容器左边界偏移的距离。 speed = 25; //匀速运动的速度 if (Math.abs(xTarget - xPos) <= speed) {//接近目标位置时候进行矫正,因为移动的距离不一定是speed的整数倍,矫正后终止animate的执行。 xPos = xTarget; ele.style.left = xPos + ‘px‘; return false; } xPos = xPos > xTarget ? xPos - speed : xPos + speed; //轮播方向向左或者向右时的处理 if (ele.movement) { //保证每次只有一个定时器运行 clearTimeout(ele.movement); } ele.style.left = xPos + ‘px‘; ele.movement = setTimeout(function () { //采用递归执行animate函数直到满足程序终止条件Math.abs(Xtarget - xPos)<=speed才停止。 animate(ele, xTarget, time); },time); } function moveIndex(spanList,index) { //根据索引让右下方对应的索引加上名称为on的class,实现高亮。 for(var i = 0,len = spanList.length;i < len;i++){ spanList[i].className = ‘‘; } spanList[index].className = ‘on‘; } function autoPlay(obj){ //自动轮播函数 if(++obj.index >= obj.aSpan.length){ obj.index = 0; } moveIndex(obj.aSpan,obj.index); animate(obj.oUl,-obj.index * 500,10); } var slide = {//将轮播的方法的实现封装在slide的对象中。 init:function(){ //初始化方法 this.oUl = document.querySelector(‘.img-box‘); this.aSpan = document.querySelectorAll(‘.icon span‘); this.index = 0;//为轮播定义一个总索引 this.timer = null; //页面加载自动轮播的定时器 }, play:function(){//通过选取右下角的小图标展示对应索引的图片。 var that = this; for(var i = 0;i < this.aSpan.length;i++){ (function(j){ that.aSpan[j].onmouseover = function(){ that.index = j; moveIndex(that.aSpan,that.index); animate(that.oUl,-that.index * 500,10); } })(i) } }, autoSlide:function(){ //页面加载完即开始自动轮播 var that = this; this.timer = setInterval(function(){ autoPlay(that); },3000); }, hover:function(){ //该方法主要为了实现箭头放在轮播区域停止自动轮播,移开继续自动轮播的功能。 var that = this; var oSlide = document.querySelector(‘.slide‘); oSlide.onmouseover = function(){ clearInterval(that.timer); } oSlide.onmouseout = function(){ that.timer = setInterval(function(){ autoPlay(that); },3000); } } } //通过对象调用对象上的函数 slide.init(); slide.play(); slide.autoSlide(); slide.hover(); }
1.animat函数
该函数有三个参数:
ele:要移动的目标元素,我这里是ul。
xTarget:目标位置,是指ele要移动到的目标位置。
time:指animate函数中的定时器的时间间隔,这里我用的是20ms。
animate函数中采用了递归,每次执行animate函数,ele都会相对于原来的位置移动speed的距离,speed我上面给定的是25,所以整个移动过程是一个匀速运动过程,但这样会有一个不好的体验,就是目前位置和目标位置距离过大时,整个滑动过程耗时较长,因为匀速嘛,距离越长耗时越多,所以这里还给出一种算法,
speed =Math.ceil(Math.abs(xTarget - xPos) / 10),这是速度逐渐递减的,由快到慢,距离越长,前面滑动的速度越快,这种体验会更好一些,这里我就不给出具体写法了。
2.moveIndex函数
这个函数应该很好理解,就是根据输入的index参数改变对应索引的元素class名称。
3.var that = this
这样的做的目的其实是用that变量保存调用对象中函数的那个对象本身,因为在后续的处理中,可能会用到对象slide的属性和方法,而在事件处理程序和定时器处理程序中this的指向又发生了改变,所以就率先用that变量保存好对象,以便需要的时候使用。
这样就基本实现了一个面向对象的简单轮播效果。