功能需求
- 点击右侧按钮一次,图片往左播放一张,左侧一样。
- 图片播放的同时,下面的小圆圈也跟随它一起变化。
- 点击小圆圈,可以播放相应图片。
- 鼠标不经过轮播图,轮播图也会自动播放图片。
- 鼠标经过轮播图,自动播放停止。
滚动图片的核心算法
- 点击某个小圆圈,就让图片滚动,小圆圈的索引号乘以图片的宽度作为ul的移动距离
- 声明一个变量,点击右侧按钮,自增1,让这个变量乘以图片宽度,就是ul的滚动距离
图片无缝滚动原理
- 把ul第一个li复制一份,放到ul的最后面
- 当图片滚动到克隆的最后一张图片时,让ul快速的、不做动画的跳到最左侧:left为0
- 同时num重新赋值为0,以便于开始新的滚动
点击右侧按钮,小圆圈会跟随变化
- 声明一个全局变量circle,每次点击自增1,
- 但是图片有5张,而小圆圈只有4个,所以加一个判断条件
- 如果小圆圈下标circle == 4就重新复原为0
自动播放
- 添加一个定时器
- 自动播放,实际就类似于点击啦右侧按钮
- 手动调用事件arrow_r.click()
节流阀
防止轮播图按钮连续点击造成播放过快的问题
逻辑:
- 当上一个函数动画内容执行完毕,再去执行下一个函数动画,达到让事件无法连续触发。
思路:
- 利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
开始设置一个变量 var flag=true; if(flag){flag=false; 动画内容} //关闭了水龙头 利用回调函数当动画执行完毕后再flag=true 打开水龙头
案例
<script> var focus=document.querySelector('.focus'); var arrow_l=document.querySelector('.arrow_l'); var arrow_r=document.querySelector('.arrow_r'); var ul=document.querySelector('ul'); var ulli=ul.querySelector('li'); var ol=document.querySelector('.circle'); var focusWidth=ulli.offsetWidth;//图片宽度 //鼠标经过focus,就停止自动播放 focus.addEventListener('mouseenter',function(){ clearInterval(timer); }); focus.addEventListener('mouseleave',function(){ timer = setInterval(function () { //手动调用点击事件 arrow_r.click(); }, 1500); }) //动态生成小圆圈 for(var i=0;i<ul.children.length;i++){ var li = document.createElement('li'); //记录当前小圆圈的索引号 li.setAttribute('index',i); ol.appendChild(li); li.addEventListener('click',function(){ //排他思想 clearcurrent(); this.className='current'; //滚动图片的核心算法:点击某个小圆圈,就让图片滚动,小圆圈的索引号乘以图片的宽度作为ul的移动距离 //点击小圆圈,移动ul,即移动图片 //ul的移动距离=当前小圆圈的索引号 * 图片的宽度,负值 var index=this.getAttribute('index');//拿到当前点击的索引号 //当点击了某个小li,就要把这个li的索引号给num num=index; // 再给小圆圈的下标circle circle=num; animate(ul,-index*focusWidth); }) } //首次是第一个显示小圆圈 ol.children[0].className='current'; //图片无缝滚动_克隆第一张图片:把ul第一个li复制一份,放到ul的最后面 var first=ul.children[0].cloneNode(true); ul.appendChild(first); //点击右侧按钮 // 声明一个变量,点击右侧按钮,自增1,让这个变量乘以图片宽度,就是ul的滚动距离 var num=0; //点击右侧按钮,小圆圈会跟随变化:声明一个全局变量,控制小圆圈的播放 var circle=0; var flag=true; //节流阀 arrow_r.addEventListener('click',function(){ if(flag){ flag=false;//关闭节流阀 //图片无缝滚动 // 把ul第一个li复制一份,放到ul的最后面 // 当图片滚动到克隆的最后一张图片时,让ul快速的、不做动画的跳到最左侧:left为0 // 同时num重新赋值为0,以便于开始新的滚动 //如果走到了最后复制的一张图片,此时ul要快速把left改为0 if (num == ul.children.length - 1) {//此时孩子多一个复制的,所以要减去 ul.style.left = 0; num = 0;//并且从0开始,下面会自增1,继而直接播放了第二张 } num++; animate(ul, -num * focusWidth,function(){ flag=true;//动画内容执完毕后再执行回调函数,即打开节流阀 }); circle++; // 但是图片有5张,而小圆圈只有4个,所以加一个判断条件 // 如果circle == 4 说明走到最后克隆的最后一个图片啦,所以就重新复原为0 if (circle == ol.children.length) { circle = 0; } clearcurrent(); ol.children[circle].className = 'current'; } }) //左侧按钮 arrow_l.addEventListener('click', function () { if(flag){ flag=false; if (num == 0) { num = ul.children.length - 1;//从4开始,下面会自减1,继而直接播放了第3张 ul.style.left = -num * focusWidth + 'px'; } num--; animate(ul, -num * focusWidth, function () { flag = true; }); circle--; // 如果circle < 0 说明是第四张图片,则小圆圈要改为第四个小圆圈 if (circle < 0) { circle = ol.children.length - 1; } clearcurrent(); ol.children[circle].className = 'current'; } }) function clearcurrent(){ for(var i=0;i<ul.children.length-1;i++){ ol.children[i].className=''; } } function animate(obj, target,callback) { clearInterval(obj.timer); obj.timer = setInterval(function() { //把步长值改为整数(往上取整),不然小数会出现走不到目标位置的问题 var step = (target - obj.offsetLeft) / 10; //当步长大于0就往上取整(即取大值的整数),小于0就往下取整(即取小值的整负数) step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { clearInterval(obj.timer); if(callback){ callback(); } } obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } //自动播放轮播图 var timer=setInterval(function(){ //手动调用点击事件 arrow_r.click(); },1500); </script>结果演示