一个菜鸟的互联网技术分享博客
您的位置: 主页 > JS实现无缝切换轮播图(自动+手动)
advertisement

JS实现无缝切换轮播图(自动+手动)

一、背景

说起轮播图,大家应该都不陌生,各大购物网站和面试题里都能看到它的身影。
实现上也并不困难,而写这篇文章是想整理一下自己心血来潮写的代码,以及实现过程中的一些思考,大家也可以顺便复习巩固一下。
今天给大家带来的是过渡动画等效果都由JS实现的无缝轮播图。CSS实现轮播图等以后再写。

二、概述

(一) 实现的效果
①自动播放
②鼠标停留时停止播放,并显示左右切换按钮
③点击左右按钮或者圆形下标时可手动切换
④图片可无缝切换,首尾图片切换时无违和感
(二)布局

基本布局
所有图片横向排列,然后依次向左移动至显示区域内(红框),借助 overflow: hidden; 让显示区域以外的内容不显示,基本布局就成型了。

(三) 动画效果

通过JS实现动画效果,要借助定时器setInterval()固定的时间间隔等距移动图片(如10ms移动10px),直至达到目标位置。

(四) 无缝切换

所谓无缝切换就是轮播图翻页时,用户不会感受到明显的跳动,而是均匀、平缓的变化。
首先,将第一张图片复制一份,添加至所有图片的末尾(即图⑥),这张图片将起到过渡作用:

  • 当要从图①翻至图⑤时【向左翻页】,改变偏移量 -> 将当前图片变为图⑥,再执行翻页动作;
  • 当要从图⑥翻至图②时【向右翻页】,改变偏移量 -> 将当前图片变为图①,再执行翻页动作;
    无缝切换方案
也就是首尾图片更替时,要多做一些处理。文字描述起来有点绕,结合代码实际效果会好理解一些。
 

三、实现(详细代码见文末链接)

(一) HTML

这部分代码比较简单:

  1. <!DOCTYPE html>  
  2. <html>  
  3.     <head>  
  4.         <title>Auto Image Silder</title>  
  5.         <link href="css/slider.css" rel="stylesheet" type="text/css" />  
  6.         <script src="js/slider.js" type="text/javascript"></script>  
  7.     </head>  
  8.     <body>  
  9.         <div id="slider">  
  10.             <ul class="slieder-item-container">  
  11.                 <li><a href="#"><img src="images/1.jpg" /></a></li>  
  12.                 <li><a href="#"><img src="images/2.jpg" /></a></li>  
  13.                 <li><a href="#"><img src="images/3.jpg" /></a></li>  
  14.                 <li><a href="#"><img src="images/4.jpg" /></a></li>  
  15.                 <li><a href="#"><img src="images/5.jpg" /></a></li>  
  16.             </ul>  
  17.             <div class="arrow-container">  
  18.                 <span class="left-arrow"><</span>  
  19.                 <span class="right-arrow">></span>  
  20.             </div>  
  21.             <div class="indicator-container">  
  22.                 <span class="indicator active"></span>  
  23.                 <span class="indicator"></span>  
  24.                 <span class="indicator"></span>  
  25.                 <span class="indicator"></span>  
  26.                 <span class="indicator"></span>  
  27.             </div>  
  28.         </div>  
  29.     </body>  
  30. </html>  

注:一般来说点击轮播图,会跳转到该图片对应的详情页面,所以用 <a> 标签包裹图片

(二) 部分CSS

  1. #slider, ul, a {  
  2.     width: 600px;  
  3.     height: 400px;  
  4. }  
  5.   
  6. #slider {  
  7.     position: absolute;  
  8.     border: 2px solid black;  
  9.     /*padding: 3px;*/  
  10.     margin: 10px 0 0 10px;  
  11.     overflow: hidden;  
  12.     -webkit-user-select:none;  
  13.     -moz-user-select:none;  
  14.     -ms-user-select:none;  
  15.     user-select:none;  
  16. }  
  17.   
  18. ul {  
  19.     position: absolute;  
  20.     list-style-type: none;  
  21.     width: 6000px;  
  22.     /*transition-duration: 0.3s;*/  
  23. }  
  24.   
  25. li {  
  26.     float: left;  
  27. }  
  28.   
  29. a {  
  30.     display: inline-block;  
  31. }  
  32.   
  33. img {  
  34.     width: 100%;  
  35.     height: 100%;  
  36. }  

(三) 动画效果

调用 animation() 函数,传入的形参为要移动的元素及移动的目标值。
默认每10ms移动10px,当跨序翻页时(如点击轮播图下方的圆形下标,直接从第1页跳到最后一页),则移动的时间会缩短,每次移动的step值会增大。

  1. function animate(element, target) {  
  2.     var step = 10;  
  3.     var time = 10;  
  4.     var gap = (Math.abs(target - element.offsetLeft) / slider_item_width);  
  5.     if (gap > 1) {  
  6.         step = step * gap;  
  7.         time = time / gap;  
  8.     }  
  9.     if (element) {  
  10.         step = (element.offsetLeft > target) ? -step : step;  
  11.         clearInterval(intervalId);  
  12.         setCurrentActiveIndicator(curIndex);  
  13.         intervalId = setInterval(function () {  
  14.             if (Math.abs(element.offsetLeft + step) < Math.abs(target)) {  
  15.                 element.style.left = element.offsetLeft + step + "px";  
  16.             } else {  
  17.                 if (Math.abs(target - element.offsetLeft) > Math.abs(step)) {  
  18.                     element.style.left = element.offsetLeft + step + "px";  
  19.                 } else {  
  20.                     clearInterval(intervalId);  
  21.                     intervalId = -1;  
  22.                     element.style.left = target + "px";  
  23.                     // 移动到目标位置,继续自动播放  
  24.                     if (autoplay) {  
  25.                         startAnimation(element);  
  26.                     }  
  27.                 }  
  28.             }  
  29.         }, time);  
  30.     }  
  31. }  

(四) 无缝切换及自动播放

概述中提到过,轮播图首尾图片图片更替时,通过改变轮播图的 left 值,改变当前显示的图片,再进行翻页动作,使用户感受不过明显的跳转变化,这也就是 prev() 和 next() 函数中所做的事。

  • 点击左、右翻页按钮,也就是单次调用 prev() 和 next() 函数;
  • 点击小圆点,也是单次调用 next() 函数,但需将要跳转的下标值传入;
  • 而自动播放,则是每次轮播图移动到目标位置后,持续调用 startAnimation() 函数,而其内部也是调用 next() 函数。
  1. function prev() {  
  2.     var element = slider_item_container;  
  3.     var li = element.children;  
  4.     curIndex = curIndex - 1;  
  5.     if (curIndex < 0) {  
  6.         element.style.left = -((li.length-1)*slider_item_width) + "px";  
  7.         curIndex = li.length-2;  
  8.     }  
  9.     animate(element, -(curIndex*slider_item_width));  
  10. }  
  11.   
  12. function next(nextIndex) {  
  13.     var element = slider_item_container;  
  14.     var li = element.children;  
  15.     if ((nextIndex != null) && (typeof(nextIndex) != "undefined")) {  
  16.         curIndex = nextIndex;  
  17.     } else {  
  18.         curIndex = curIndex + 1;  
  19.         if (curIndex > (li.length-1)) {  
  20.             element.style.left = 0 + "px";  
  21.             curIndex = 1;  
  22.         }  
  23.     }  
  24.     animate(element, -(curIndex*slider_item_width));  
  25. }  
  26.   
  27. function startAnimation(element) {  
  28.     if (autoplayId) {  
  29.         clearTimeout(autoplayId);  
  30.     }  
  31.     autoplayId = setTimeout(function () {  
  32.         next();  
  33.     }, autoplay_Delay);  
  34. }  

四、总结

以上就是实现JS动画效果的无缝轮播图的要点,大家有疑问或者有更好的实现方式,也请提出来一起探讨。
最后和大家分享一下仅针对本文代码的一些小知识点(如下),更深层次的内容就留给大家挖掘了。

  1. <span> 设宽高无效,但设了 position: absolute; 或者 display: inline-block; 就有效了
  2. 子元素设置了 float:left,父元素的 text-align 就失效了
  3. 圆形:border-radius: 50%;
  4. 不脱离文档流,或者相对布局可使用 margin; 0 auto; 水平居中
  5. 元素上下左右居中:
  1. .content {  
  2.     positon: absolute;  
  3.     width: 200px;  
  4.     height: 100px;  
  5.     top: 50%;  
  6.     left: 50%;  
  7.     margin-top: -50px;  
  8.     margin-left: -100px;  
  9.     /*transform: translate(-50%, -50%);*/  
  10. }  
  1. 字上下居中
    line-height 设置和 height 一样的值
  2. 文字水平居中
    text-align: center;

五、完整代码

点击这里下载
zhangren.online
上一篇:CSS气泡对话框
下一篇:鼠标点击时出现小心心

您可能喜欢

​es6常用数组操作及技巧汇总

​es6常用数组操作及技巧汇总

​如何将自己写的代码上传到github上

​如何将自己写的代码上传到github上

​jQuery数字字母组合验证码

​jQuery数字字母组合验证码

回到顶部