JS实现原生轮播

2,230 阅读5分钟

实现原理

  • 结构上:通过一个容器来包裹所有的图片、小圆点、左右翻页;包裹图片的元素和包裹小圆点的元素以及左右翻页为同级元素。

  • 样式上:容器需要用相对定位至我们需要的位置,设置容器的宽高和图片的宽高相同,超出部分隐藏;翻页同理定位至合适位置;小圆点的父元素定位至合适位置,依靠margin值来让小圆点之间有一定间距;需要给小圆点加一个激活后的样式。

  • 功能上:鼠标点击翻页可以实现图片翻页;鼠标点击某个小圆点,此点被激活并可以切换至对应图片;翻页的同时小圆点激活状态跟随变化;自动播放,小圆点激活样式跟随变化,鼠标移入自动播放暂停,移出自动播放开始。

实现步骤

1.html结构和css样式

 <!-- 容器 -->
  <div class="wrap">
    <!-- 图片容器 -->
    <ul class="slideshow">
      <li><img src="../img/1.jpg" alt=""></li>
      <li><img src="../img/2.jpg" alt=""></li>
      <li><img src="../img/3.jpg" alt=""></li>
      <li><img src="../img/4.jpg" alt=""></li>
      <li><img src="../img/5.jpg" alt=""></li>
    </ul>
    <!-- 左箭头 -->
    <i class="iconfont ............."></i>
    <!-- 右箭头 -->
    <i class="iconfont ............."></i>
    <!-- 小圆点导航 -->
    <div class="slide-nav">
    </div>
  </div>
/*清除默认样式*/
    * {
      margin: 0;
      padding: 0;
    }
    li {
      list-style: none;
    }
/*容器,设置轮播窗口大小*/
    .wrap {
      width: 800px;
      height: 450px;
      margin: 100px auto;
      position: relative;
      overflow: hidden;
      cursor: pointer;
    }
/*图片对齐*/
    img {
      /* 改变基线对齐方式 */
      vertical-align: top;
      /*display:block   也可以实现*/
    }
/*弹性盒子,让左右图片横向排列*/
    .slideshow {
      display: flex;
      position: absolute;
      left: 0;
      top: 0;
    }
/*左右箭头*/
    .icon-左,
    .icon-右 {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      font-size: 48px;
      color: #fff;
      background-color: rgba(0, 0, 0, .4);
      width: 55px;
      height: 70px;
      line-height: 70px;
      text-align: center;
    }
    .icon-左 {
      left: 0;
    }
    .icon-右 {
      right: 0;
      padding-left: 5px;
      box-sizing: border-box;
    }
/*小圆点导航*/
    .slide-nav {
      position: absolute;
      left: 50%;
      transform: translate(-50%);
      bottom: 20px;
    }

    .slide-nav span {
      display: inline-block;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      margin: 0px 5px;
      background-color: rgba(255, 255, 255, .8);
    }
/*小圆点激活状态的样式*/
    .slide-nav span.active {
      background-color: #00a1d6;
      border: 2px solid #fff;
      box-sizing: border-box;
      transform: scale(1.3);
    }

2.功能实现

2.0获取所用到的节点

 // 获取wrap
    var wrap = document.querySelector(".wrap")
    // 获取左右箭头
    var leftArrows = document.querySelector(".icon-youjiantou-cu")
    var rightArrows = document.querySelector(".icon-zuojiantou-cu")
    //  获取图片容器sshow
    var sshow = document.querySelector(".slideshow")
    // 获取所有图片元素的长度
    var imgnums = document.querySelectorAll(".slideshow li").length;
    // 获取图片的宽度(图片的宽度为li的宽度)
    var ulwidth = document.querySelector(".slideshow li").offsetWidth;
    // 获取小圆点导航
    var slide_nav = document.querySelector(".slide-nav")

2.1左右翻页箭头功能

实现原理: 我们这里定义一个全局变量img_order来记录图片的切换,每点击一次左翻页“img_order--”,点击一次右翻页“img_order++”;当在第一张图我们点击了左翻页需要让其切换至最后一张图,当在最后一张图我们点击了右翻页需要让其切换至第一页所以我们需要判断一下;

无缝衔接: 在最后的图片后边加上第一张图(colon-1),当至coon-1前面一张图时,点击下一页切换至colon-1,同时将定位属性left变为0;当翻页至第一张图片时,再次点击上一页,需要将left值改为:【-(非重复图片个数-1)*图片宽度px

2.2翻页同时小圆点跟随激活的状态

实现原理: 定义一个全局变量来控制圆点状态,这个状态是跟随鼠标点击左右箭头的状态,特殊的地方就是需要判断在第一张的时候和在最后一张时候的条件,已经对应对的参数和样式该如何改变;注意的地方就是排他思想

/*  此处在全局变量中声明了: img_order=0; clickdot=0;
一个用来记录点击翻页后图片的变化,一个用来控制小圆点的运动;
*/
    // 给左箭头添加点击事件
    leftArrows.onclick = function () {
      img_order--;
      #//是否在第一张点击了上一页(注意:此处是在点击了上一页之后判断的,样式会瞬间改变)
      if (img_order < 0) {
        sshow.style.left = -imgnums * ulwidth + "px"
        img_order = imgnums - 1;
      }
      console.log(img_order)
     /*引用封装好的运动函数 move*/
      move({
        el: sshow,
        target: sshow.offsetLeft + ulwidth,
        step: 20
      })
      // 点击左箭头 小圆圈跟随变化
      clickdot--;
      //点击左箭头如果是 从第一张图片切换,则给clickdot重新赋值imgnums-1
      if (clickdot < 0) {
        clickdot = imgnums - 1;
      }
           排他思想
    //遍历所有小圆点,然后清空所有的active类,再给当前元素添加active类。
      for (var i = 0; i < imgnums; i++) {
        slide_nav.children[i].className = '';
      }
      //当前小圆圈添加active类名
      slide_nav.children[clickdot].className = 'active'
    }
    // 给右箭头添加点击事件
    rightArrows.onclick = function () {
      img_order++;
      // 点击右箭头,如果是 从最后一张图片切换,则给clickdot重新赋值0
      if (img_order > imgnums - 1) {
        sshow.style.left = "0px"
        img_order = 0;
      }
        /*引用封装好的运动函数 move*/
      move({
        el: sshow,
        target: sshow.offsetLeft - ulwidth,
        step: 20
      })
      // 点击右箭头 小圆圈跟随变化
      clickdot++;
      // 点击右箭头:如果走到最后一张图片
      if (clickdot == slide_nav.children.length) {
        clickdot = 0;
      }
      for (var i = 0; i < slide_nav.children.length; i++) {
        slide_nav.children[i].className = '';
      }
      //当前小圆圈添加active类名
      slide_nav.children[clickdot].className = 'active'
    }

2.3自动化&小圆点点击事件

实现原理: for循环实现自动化创建小圆点,创建的个数和我们获取到图片的个数相等(注意:此处不包含克隆的那个图片);for循环实现点击小圆点事件(排他思想)

注意这里我们需要一个索引,来控制图片的切换,通过自定义属性来实现。

 for (var i = 0; i < imgnums; i++) {
      var span = document.createElement("span");
     # // 记录当前小圆圈索引号,通过自定义属性
      span.setAttribute('index', i)
      // 将span插入slide_nav中
      slide_nav.appendChild(span);
      // 小圆圈点击事件:小圆圈排他思想(点击某个小圆点其他小圆点active类都被清空)
      span.addEventListener('click', function () {
        // 这里的slide_nav.children.length数值等于imgnums
        for (var i = 0; i < imgnums; i++) {
          slide_nav.children[i].className = "";
        }
        this.className = 'active'
       # // 当我们点击了某个小圆点,就拿到这个小圆点的索引
        var index = this.getAttribute('index')
# bug1解决: 把这个索引值index给 img_order和 clickdot
        clickdot = index;
        img_order = index;
      #  // 小圆圈激活图片移动(移动距离为小圆圈的索引号乘以图片宽度)
        move({
          el: sshow,
          target: -index * ulwidth,
          step: 20,
        })
      })
    }

2.4鼠标移入移出自动播放(开启/关闭)

实现原理: 开启一个定时器每个一段时间执行点击下一页事件;鼠标移入区域,定时器关闭,设为空;鼠标移出定时器开启。

 //  自动播放(自动调用事件)
    var timers = setInterval(function () {
        /*自动调用事件*/
      rightArrows.click();
    }, 2000)
    // 鼠标移入面板,自动播放停止
    wrap.onmouseenter = function () {
      clearInterval(timers);
      timers = null;
    }
    //鼠标移出,开启定时器
    wrap.onmouseleave = function () {
      timers = setInterval(function () {
        rightArrows.click();
      }, 2000)
    }

优化

  • 1、点击小圆点后在点击翻页出现错误(错误情况是小圆点没有跟随图片变化)

  • 2、克隆第一张图片&默认第一个圆点激活

  • 3、代码优化(请君细品😊,自己可以试着优化)

  //小圆点点击事件后,获取到索引index后加上入下代码(比如当我们点击了第5个小圆点,索引为4,而这时我们的clickdot、 img_order都为0,因为他们没有被触发,所以我们要给他同样的值 让他们同步)
    clickdot = index;
    img_order = index;
    // 默认第一个小圆点激活
    slide_nav.children[0].className = "active"
    //复制第一张图片插入到图片容器的末尾(这一块要放到获取图片长度后边,要不然我们复用的很多值都要更改)。
    var firstImg = sshow.firstElementChild.cloneNode(true);
    sshow.appendChild(firstImg);