虽然网上已经多如牛毛关于这个特效实现的介绍,但今天还是想自己撸一份加上自己的理解。
首先来看下什么是无缝轮播什么是非无缝轮播
这是某腾体育的首页轮播图,可以看到当到最后一张返回第一张轮播或者第一张到最后一张时会有一个回拉的动作
这种视觉用户体验比较不友好有种晃眼的感觉。
下面看看无缝轮播效果
可以看到无缝轮播当最后一张到第一张或是第一张到最后一张切换时是一种很平滑的效果,是一种较好的用户体验
下面就来看看用原生的JS是怎么完成的
css:
a, ul, li { list-style: none; text-decoration: none; margin: 0; padding: 0; } .wrap { width: 600px; height: 400px; margin: 100px auto; position: relative; overflow: hidden; } .wrap .left { position: absolute; top: 142px; left: -18px; } .wrap .left img { width: 80px; height: 80px; } .wrap .right { position: absolute; top: 142px; right: -16px; } .wrap .right img { width: 80px; height: 80px; } .navs { width: 4200px; height: 100%; position: absolute; top: 0; left: -600px; /*transition: all .3s;*/ } .navs li { width: 600px; height: 100%; float: left; } .navs li img { width: 100%; height: 100%; } #bots { display: inline-block; width: 600px; height: 40px; background: rgba(0, 0, 0, .3); text-align: center; position: absolute; bottom: 0; left: 0; } #bots li { width: 20px; height: 20px; border-radius: 50%; background: #cccccc; position: relative; left: 220px; top: 10px; margin-left: 10px; float: left; } #bots .active { background: red; }
dom:
<div class="wrap" id="box"> <ul id='navs' class="navs" style="left: -600px"> <li><a href="javascript:;"><img src="image/banner5.png"/></a></li> <li><a href="javascript:;"><img src="image/banner1.png"/></a></li> <li><a href="javascript:;"><img src="image/banner2.png"/></a></li> <li><a href="javascript:;"><img src="image/banner3.png"/></a></li> <li><a href="javascript:;"><img src="image/banner4.png"/></a></li> <li><a href="javascript:;"><img src="image/banner5.png"/></a></li> <li><a href="javascript:;"><img src="image/banner1.png"/></a></li> </ul> <a id="pre" class="left"><img src="image/left1.png"/></a> <a id="nex" class="right"><img src="image/right1.png"/></a> <ul id="bots"> <!--<li class="bot active"></li>--> <!--<li class="bot"></li>--> <!--<li class="bot"></li>--> <!--<li class="bot"></li>--> <!--<li class="bot"></li>--> </ul> </div>
上面的布局在第一张克隆一个最后一张的副本,在最后一张克隆一张第一张的副本
当我们切换到最后一张的时候点击下一张时移动到第一张副本的同时利用js设置css样式迅速切换到真正的第一张这个过程是肉眼无法看到的来达到无缝的目的
下面是鼠标每次点击就改变一点点位置,所以我们可以利用定时器来设计很小的时间不断移动位置来实现过渡切换的效果。
js:
<script> window.onload = function () { var pre = document.getElementById('pre'); // 上一张 var nex = document.getElementById('nex'); // 下一张 var list = document.getElementById('navs'); // 轮播图 var bots = document.getElementById('bots'); // 小圆点 var box = document.getElementById('box'); // 最外层容器用来判断鼠标移入移除停止自动轮播 var index = 0; // 记录当前小圆点下标 var isanimate = true; // 是否自动播放 var interval; // 自动播放定时器 var disable = true; // 用来控制快速点击导致页面错乱 //初始化小圆点 for (let i = 0; i < list.children.length - 2; i++) { let li = document.createElement('li') bots.appendChild(li) } bots.children[0].className = 'active' // 默认第一个为初始圆点高亮 // 上一张 pre.onclick = function () { if(disable){ disable = false // 这里设置为false表示进入切换动画未完成时就不能点击 index--; // 小圆点下标-- changebots() //改变高亮 animate(600) // 切换轮播图动画 } } // 下一张 nex.onclick = function () { if(disable){ disable = false index++; changebots() animate(-600) } } // 改变圆点高亮 function changebots() { if (index < 0) { // 如果小于0图片到最后一张高亮也对应到最后一个圆点 index = 4 } else if (index > 4) { // 如果大于于4图片到第一张一张高亮也对应到第一个圆点 index = 0 } for (let i = 0; i < bots.children.length; i++) { bots.children[i].className = '' } bots.children[index].className = 'active' } // 图片切换动画 function animate(offset) { let newLeft = parseInt(list.style.left) + offset; // 下一张轮播图应该位移到的位置 let interval = 10; // 图片位移的时间 let speed = (offset / 10) / 3 //每10ms移动的位置这里是设置20px 这里可以根据自己需求改动 // 自动轮播小圆点自动切换 if (isanimate) { index++; changebots(index) } // 利用定时器递归的模拟动画效果切换图片 function change() { if (parseInt(list.style.left) === -3600) { list.style.left = -600 + 'px' newLeft = -1200 } if (parseInt(list.style.left) > 0) { list.style.left = -3000 + 'px' newLeft = -2400 } this.timer = setTimeout(() => { list.style.left = list.offsetLeft + speed + 'px' if (parseInt(list.style.left) != newLeft) { // 判断是否到了应该到的位移位置,到达就清除计时器停止递归 change() } else { clearTimeout(this.timer) disable = true //动画完成进行下一次点击 console.log(disable) console.log(list.style.left) } }, interval) } change() } // 小圆点切换 bots.onclick = function (ev) { var ev = ev || window.event; let target = ev.target || ev.srcElement; if (target.nodeName.toLowerCase() == 'li') { for (let i = 0; i < bots.children.length; i++) { if (bots.children[i] === target) { index = i; console.log(index) break; } } changebots() // 切换下标 list.style.left = ((index + 1) * -600) + 'px' // 切换轮播图 } } // 自动轮播 function autoplay() { interval = setInterval(() => { animate(-600) }, 2000) } // 鼠标移入停止自动轮播 box.onmouseover = function () { isanimate = false console.log('in') clearInterval(interval) } //鼠标移出开始轮播 box.onmouseleave = function () { isanimate = true autoplay() console.log('out') } autoplay() } </script>
上面是原生JS去实现那么怎么用JQ实现呢,用JQ 来实现就简单的多了
<script> $(function () { var index = 0; // 记录当前小圆点下标 var isanimate = true; // 是否自动播放 var interval; // 自动播放定时器 //初始化小圆点 for (let i = 0; i < 5; i++) { let li = $('<li></li>') $('#bots').append(li) } $('#bots li').first().addClass('active') // 上一张 $('#pre').click(function () { index--; if (index < 0) { $('#navs').css('left', -3600) index = 4 } manimate(index) changebots(index) }) //下一张 $('#nex').click(function () { index++; if (index >5) { $('#navs').css('left', -600) index = 1 } manimate(index) changebots(index) }) //小圆点切换 $('#bots').click(function (ev) { var ev = ev || window.event; let target = ev.target || ev.srcElement; if (target.nodeName.toLowerCase() == 'li') { for (let i = 0; i < 5; i++) { if ($('#bots')[0].children[i] === target) { index = i; console.log(index) break; } } } $('#navs').css('left', (index + 1) * -600) changebots(index) }) // 切换动画效果 function manimate(i) { i +=1; // console.log(i) $('#navs').stop().animate({left: -i * 600}, 500) } // 切换圆点 function changebots(i) { if (i < 0) { i = 4 } else if (i > 4) { i = 0 } $('#bots li').eq(i).addClass('active').siblings().removeClass('active') } // 自动轮播 function autoplay() { interval = setInterval(() => { index++; if (index >5) { $('#navs').css('left', -600) index = 1 } changebots(index) manimate(index) }, 2000) } // 鼠标移入停止自动轮播 $('#box').mouseover(function () { console.log('in') clearInterval(interval) }) //鼠标移出开始轮播 $('#box').mouseleave(function () { console.log('out') autoplay() }) autoplay() }) </script>