【JS】原生淘宝轮播图实现总结

一.实现思路

 实现效果:

1. css

将垂直排列的多张图片水平排列,可以使用浮动;或将包裹图片的盒子设置为行内块元素inline-block,并消除空白折叠。

2. js

1) 如何让图片水平移动?

将包裹所有图片的总容器设置为绝对定位,通过修改left属性展示需要的图片,切换left属性时一般使用过渡效果transition;

2) 首尾如何无缝切换图片?

最后一张图片之后加上第一张轮播图,当显示添加的第一张轮播图后将left属性修改为真正第一张轮播图的left值,切换时取消过渡效果;同理在第一张轮播图之前加上最后一张轮播图...

3) 轮播图切换细节?

每次切换一张轮播图是以一张轮播图的宽度为单位,改变容器left值;通过设置全局属性index,指定偏离量,如:显示第一张图即index=1,left = '-' + index * picWidth + 'px',图片左移一张需要将index++,右移一张图片需要将index--。

4) 自动播放和圆点切换原理? 

将左移一张图片和右移一张图片各封装成函数leftMoveSwiper()和rightMoveSwiper(),自动播放时设置定时器,定时执行leftMoveSwiper(),鼠标进入轮播图区域时取消定时器clearInterval(timer),改为手动切换模式;

随后获取圆点的下标索引,找到原点下标和index之间的对应关系,修改index值,随后调用一次leftMoveSwiper()切换到指定的位置。

5) 圆点切换如何使用事件委托?

使用事件委托,将点击事件绑定给原点的父容器wrapper,通过事件对象event.target获取点击的目标元素,通过event.target.classList.contains(‘指定类名’)判断是否为需要操作的目标元素(即圆点)。

3.代码

html部分:

<div class="app">
    <ul class="wrapper">
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p5.jpg" alt="" class="img">
            </a>
        </li>
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p1.jpg" alt="" class="img">
            </a>
        </li>
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p2.jpg" alt="" class="img">
            </a>
        </li>
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p3.jpg" alt="" class="img">
            </a>
        </li>
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p4.jpg" alt="" class="img">
            </a>
        </li>
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p5.jpg" alt="" class="img">
            </a>
        </li>
        <li class="liWrapper">
            <a href="#" class="link">
                <img src="./img/p1.jpg" alt="" class="img">
            </a>
        </li>

    </ul>
    <i class="iconfont icon-arrow-left"></i>
    <i class="iconfont icon-arrow-right"></i>
    <div class="dot">
        <span></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
</div>
<script src="./index.js"></script>

  css部分:


   * {
       margin:0;
       padding:0;
       box-sizing:border-box;
       /* overflow: hidden; */
   }
   .app{
       position: absolute;
       top:50%;
       left:50%;
       transform: translate(-50%,-50%);
       height: 280px;
       width: 520px;
       overflow: hidden;
       border-radius: 8px;
       /* display: block; */
   }
   .app:hover .iconfont{
       display:block;
   }
   .wrapper{
       z-index:1;
       display: block;
       position: absolute;
       list-style:none;
       /* 处理空白折叠 */ 
       font-size: 0; 
   }
   .liWrapper{
       display:inline-block;
   }
   
   .iconfont {
       position:absolute;
       z-index:2;
       font-size:24px;
       height:24px;
       color: blanchedalmond;
       background-color: rgba(0,0,0,0.3);
       cursor:pointer;
       display:none;
   }
   
   .icon-arrow-left{
       top:50%;
       left:-5px;
       border-radius: 0 12px 12px 0;
       transform:translateY(-50%);
   }
   .icon-arrow-right{
       top:50%;
       right:-5px;
       border-radius: 11px 0 0 11px;
       transform:translateY(-50%);
   }
   .dot {
       z-index:2;
       position:absolute;
       bottom:15px;
       left:50%;
       transform: translateX(-50%);
       background-color: rgba(255,255,255,.3);
       border-radius: 6px;
       font-size: 0;
   }
   .dot span {
       display: inline-block;
       width: 8px;
       height: 8px;
       margin: 3px;
       border-radius: 4px;
       background-color: #fff;
   }
   
   .dot-active {
       background-color: #ff5500!important;
   }

 js部分:

   let perWidth = 520; // 一张图片的宽度
   let wrapper = document.querySelector('.wrapper');
   let app = document.querySelector('.app');
   let liWrapper = document.querySelectorAll('.liWrapper');
   let dots = document.querySelector('.dot').children; 
   let preTime = 0; // 上一刻时间,处理防抖
   wrapper.style.width = perWidth * liWrapper.length + 'px'; // 获取并设置图片容器的总宽度
   // 当前是第几张图片
   let index = 1;
   // 定时器标识
   let timer;
   
   // wrapper 初始化
   function swiperInit() {
       wrapper.style.left = '-' + perWidth * index + 'px';  
   }
   
   // 左移轮播图
   function leftMoveSwiper() {
       index ++;
       wrapper.style.left = '-' + perWidth * index + 'px';
       wrapper.style.transition = 'left 1s'; 
       if(index >= liWrapper.length - 1) {
           setTimeout(() => {
               index = 1;
               wrapper.style.transition = 'none';
               wrapper.style.left = '-' + perWidth * index + 'px'; 
               setDotColor();
           },1000)
       }
       setDotColor();
       
   }
   
   // 右移轮播图
   function rightMoveSwiper() {
       index --;
       wrapper.style.left = '-' + perWidth * index + 'px'; 
       wrapper.style.transition = 'left 1s'; 
       if(index <= 0) {
           setTimeout(() => {
               index = 5;
               wrapper.style.transition = 'none';
               wrapper.style.left = '-' + perWidth * index + 'px'; 
           },1000)
       }
       setDotColor();
   }
   
   // 自动播放
   function autoplaySwiper() {
       timer = setInterval(() => {
           leftMoveSwiper();
       },2000);
   }
   
   // 事件绑定
   function handleBind(){
       // 利用事件委托,给箭头绑定点击事件
       app.addEventListener('click',function(e){
           if(e.target.classList.contains('icon-arrow-left')) {
               throttle(rightMoveSwiper,1000);
           } else if(e.target.classList.contains('icon-arrow-right')) {
               throttle(leftMoveSwiper,1000);
           }
       });
       // 鼠标进入暂停自动轮播
       app.addEventListener('mouseenter',function(){
           clearInterval(timer);
       });
   
       // 鼠标离开继续自动轮播
       app.addEventListener('mouseleave',function(){
           autoplaySwiper();
       })
   
   }
   
   // 防抖处理
   function throttle(fn,delay) {
       let now = Date.now();
       if(now - preTime >= delay) {
           fn();
           preTime = now;
       }
   }
   
   // dot颜色设置
   function setDotColor() {
       for (let i = 0; i < dots.length; i++) {
           if(index === i + 1){
               dots[i].classList.add('dot-active');
           } else {
               dots[i].classList.remove('dot-active')
           }
   
           if(index === dots.length + 1) {
               dots[0].classList.add('dot-active');
           } else if(index === 0) {
               dots[dots.length - 1].classList.add('dot-active');
           }
       }
   }
   
   // 点击原点切换轮播图
   function pointDotChangePic(){
       for (let i = 0; i < dots.length; i++) {
           dots[i].addEventListener('click',function(){
               index = i;
               leftMoveSwiper();
           })        
       }
   }
   
   // 初始化设置
   function init(){
       swiperInit();
       autoplaySwiper();
       handleBind();
       setDotColor();
       pointDotChangePic();
   }
   
   init();

二.问题

z-index无效原因

这种情况发生的条件有三个:

1、父标签 position属性为relative;

2、问题标签无position属性(不包括static);

3、问题标签含有浮动(float)属性。

空白折叠

display为inline的元素之间,若这些元素标签之间不写在同一行上,浏览器会在这些元素之间加上一格空白,空白大小视font-size值大小,去除空白只需将这些元素的共同父元素font-size值设置为0

line-height 无效原因

已知父元素dots,子元素dot,子元素设为inline-block,为解决子元素出现的空白折叠,将父元素font-size设为0,此时为了让子元素垂直居中,设置line-height无效,原因是字体font-size为0

解决办法是将子元素的margin-top和margin-bottom设置为一个相同的值,如4px

猜你喜欢

转载自blog.csdn.net/weixin_43655896/article/details/122998240