zoukankan      html  css  js  c++  java
  • 淘宝轮播图功能

    一、概念

    现在一般的电商网站的首页都会有一个轮播图,如下图这样

    这幅图可以拆分为三个功能

    1、通过点击数字切换图片。
    2、通过点击左右按钮切换图片。
    3、鼠标没有停留在相框范围内时,自动轮询切换图片。
    

    下面针对这三个功能,一个个单独讲解。


    二、点击数字切换图片

    效果

    代码

    公共common.js,下面所有的代码都会引用这个js。

    //根据id获取元素对象
    function my$(id) {
        return document.getElementById(id);
    }
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            * {
                margin: 0;
                padding: 0
            }
    
            ul {
                list-style: none
            }
    
            .box { /*设置最外层div的大小 对齐方式 边框*/
                 730px;
                height: 454px;
                margin: 100px auto;
                padding: 5px;
                border: 1px solid #ccc;
            }
    
            .inner { /*相框大小设置*/
                 730px;
                height: 454px;
                background-color: pink;
                overflow: hidden;
                position: relative;
            }
    
            /* 这里width的宽度一定要比图片的总宽度要宽,这里一共有5张图,设置600%也是没有问题的。
             不然因为图片设置左浮动,如果宽度不够那么就会溢出换行。如果父元素设置 overflow: hidden;那么也无法实现轮播效果*/
            .inner ul {
                 1000%;
                position: absolute;
            }
    
            .inner li { /*图片左浮动*/
                float: left;
            }
    
            .square { /*绝对定位*/
                position: absolute;
                right: 10px;
                bottom: 10px;
            }
    
            .square span { /*行转块*/
                display: inline-block;
                 16px;
                height: 16px;
                background-color: #fff;
                text-align: center;
                line-height: 16px;
                cursor: pointer;
            }
    
            .square span.current { /*设置当前按钮颜色*/
                background-color: orangered;
                color: #fff;
            }
    
        </style>
    </head>
    <body>
    <div class="box" id="box">
        <div class="inner"><!--相框-->
            <ul>
                <li><a href="#"><img src="images/1.jpg" alt=""/></a></li>
                <li><a href="#"><img src="images/2.jpg" alt=""/></a></li>
                <li><a href="#"><img src="images/3.jpg" alt=""/></a></li>
                <li><a href="#"><img src="images/4.jpg" alt=""/></a></li>
                <li><a href="#"><img src="images/5.jpg" alt=""/></a></li>
                <li><a href="#"><img src="images/6.jpg" alt=""/></a></li>
            </ul>
            <div class="square"> <!-- 按钮,这里写死6个按钮并不合理 因为上面图片不是固定的,应该根据上面进行设置个数 会优化 -->
                <span class="current">1</span>
                <span>2</span>
                <span>3</span>
                <span>4</span>
                <span>5</span>
                <span>6</span>
            </div>
        </div>
    </div>
     <!-- 引用公共js -->
    <script src="common.js"></script>
    <script>
        //获取最外面的div
        var box = my$("box");
        //获取相框
        var inner = box.children[0];
        //获取相框的宽度
        var imgWidth = inner.offsetWidth;
        //获取ul
        var ulObj = inner.children[0];
        //获取所有的span标签
        var spanObjs = inner.children[1].children;
        //循环遍历所有的span标签,注册鼠标进入的事件
        for (var i = 0; i < spanObjs.length; i++) {
            //循环的时候把索引值保存在每个span的自定义属性中
            spanObjs[i].setAttribute("index", i);
            //注册鼠标进入事件
            spanObjs[i].onmouseover = function () {
                //先干掉所有的span的背景颜色
                for (var j = 0; j < spanObjs.length; j++) {
                    //移除了每个span的类样式
                    spanObjs[j].removeAttribute("class");
                }
                //设置当前的span的背景颜色
                this.className = "current";
                //移动ul(每个图片的宽*鼠标放在这个按钮的索引值)
                //获取当前鼠标进入的span的索引
                var index = this.getAttribute("index");
                // 为什么这里是负数
                animate(ulObj, -index * imgWidth);
            };
        }
    
        //设置任意的一个元素,移动到指定的目标位置
        function animate(element, target) {
            clearInterval(element.timeId);
            //定时器的id值存储到对象的一个属性中
            element.timeId = setInterval(function () {
                //获取元素的当前的位置,数字类型
                // 如果第一次进定时任务这里值为0 因为d当前元素的父类设置了position属性,
                // 那么offsetLeft为元素边框外侧到父元素边框内侧的距离,那么这里就为0
                var current = element.offsetLeft;
                //每次移动的距离 指的是切换图片每次移动10px,定时任务为20毫米执行一次,就是20毫秒移动10px
                var step = 10;
                //这里设计到是左移动图片还是右移动图片 如果1跳到2就是左移动 2跳到1就是右移动
                step = current < target ? step : -step;
                console.log("target=" + target);
                console.log("current=" + current);
                //当前移动到位置
                current += step;
                //如果当前移动的绝对值小于10 那么就要关闭定时器 好比从1点到2 已经移动到第二张图片了那么就需要关闭定时器
                if (Math.abs(current - target) > Math.abs(step)) {
                    element.style.left = current + "px";
                } else {
                    //清理定时器
                    clearInterval(element.timeId);
                    //直接到达目标
                    element.style.left = target + "px";
                }
            }, 20);
        }
    </script>
    </body>
    </html>
    

    上面代码中的注释说明的已经挺清楚的了。,这里再详细解释下面这段代码

    animate(ulObj, -index * imgWidth)   // 为什么这里传入的是负数
    

    画了这幅图应该把这里原理讲的蛮清楚的。


    三、点击左右按钮切换图片

    效果

    这里的效果主要有两点

    1、在鼠标没有移动到相框里时候,左右按钮消失(焦点事件)
    2、点击左按钮切换到下一张图片,点击右按钮时候切换到上一张图片(这里注释掉了overflow: hidden;属性 所以所有图片都会显示)
    

    代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title></title>
      <style>
        body, ul, ol, li, img {
          margin: 0;
          padding: 0;
          list-style: none;
        }
    
        #box {
           520px;
          height: 280px;
          padding: 5px;
          position: relative;
          border: 1px solid #ccc;
          margin: 100px auto 0;
        }
    
        .ad {
           520px;
          height: 280px;
          /*overflow: hidden;*/
          position: relative;
        }
    
        #box img {
           520px;
        }
    
        .ad ol {
          position: absolute;
          right: 10px;
          bottom: 10px;
        }
    
        .ad ol li {
           20px;
          height: 20px;
          line-height: 20px;
          border: 1px solid #ccc;
          text-align: center;
          background: #fff;
          float: left;
          margin-right: 10px;
          cursor: pointer;
          _display: inline;
        }
    
        .ad ol li.current {
          background: yellow;
        }
    
        .ad ul li {
          float: left;
        }
    
        .ad ul {
          position: absolute;
          top: 0;
           2940px;
        }
    
        .ad ul li.current {
          display: block;
        }
    
        #focusD {
          display: none;
        }
    
        #focusD span {
           40px;
          height: 40px;
          position: absolute;
          left: 5px;
          top: 50%;
          margin-top: -20px;
          background: #000;
          cursor: pointer;
          line-height: 40px;
          text-align: center;
          font-weight: bold;
          font-family: '黑体';
          font-size: 30px;
          color: #fff;
          opacity: 0.3;
          border: 1px solid #fff;
        }
    
        #focusD #right {
          right: 5px;
          left: auto;
        }
      </style>
    </head>
    <body>
    <div id="box" class="all">
      <div class="ad">
        <ul id="imgs">
          <li><img src="images/01.jpg"/></li>
          <li><img src="images/02.jpg"/></li>
          <li><img src="images/03.jpg"/></li>
          <li><img src="images/04.jpg"/></li>
          <li><img src="images/05.jpg"/></li>
        </ul>
      </div><!--相框-->
      <div id="focusD"><span id="left">&lt;</span><span id="right">&gt;</span>
      </div>
    </div>
    <script src="common.js"></script>
    <script>
    
      //获取最外面的div
      var box = my$("box");
      //获取相框
      var ad = box.children[0];
      //获取相框的宽度
      var imgWidth = ad.offsetWidth;
      //获取ul
      var ulObj = ad.children[0];
      //获取左右焦点的div
      var focusD = my$("focusD");
    
      //显示和隐藏左右焦点的div----为box注册事件
      box.onmouseover = function () {
        focusD.style.display = "block";
      };
      box.onmouseout = function () {
        focusD.style.display = "none";
      };
    
      //点击右边按钮
      var index=0;
      my$("right").onclick = function () {
         //index最终等于 0,1,2,3,4
        if(index<ulObj.children.length-1){
          index++;
          animate(ulObj,-index*imgWidth);
        }
    
      };
      //点击左边按钮
      my$("left").onclick = function () {
        //idex最终等于 4,3,2,1,0
        if(index>0){
          index--;
          animate(ulObj,-index*imgWidth);
        }
      };
    
    
      //设置任意的一个元素,移动到指定的目标位置
      function animate(element, target) {
        clearInterval(element.timeId);
        //定时器的id值存储到对象的一个属性中
        element.timeId = setInterval(function () {
          //获取元素的当前的位置,数字类型
          var current = element.offsetLeft;
          //每次移动的距离
          var step = 10;
          step = current < target ? step : -step;
          //当前移动到位置
          current += step;
          if (Math.abs(current - target) > Math.abs(step)) {
            element.style.left = current + "px";
          } else {
            //清理定时器
            clearInterval(element.timeId);
            //直接到达目标
            element.style.left = target + "px";
          }
        }, 20);
      }
    </script>
    </body>
    </html>
    

    四、自动轮询切换图片

    效果

    这里的效果主要有两点

    1、当鼠标不在相框范围内,相框中的图片进行自动切换图片
    2、当鼠标进入相框范围内,此时相框中的图片停止不再移动
    

    代码

    <!DOCTYPE html>
    <html>
    <head lang="en">
      <meta charset="UTF-8">
      <title></title>
      <style>
        * {
          margin: 0;
          padding: 0;
        }
    
        ul {
          list-style: none;
    
        }
    
        img {
          vertical-align: top;
        }
    
        /*取消图片底部3像素距离*/
        .box {
           300px;
          height: 200px;
          margin: 100px auto;
          background-color: pink;
          border: 1px solid red;
          position: relative;
          overflow: hidden;
        }
    
        .box ul li {
          float: left;
        }
    
        .box ul {
           1500px;
          position: absolute;
          left: 0;
          top: 0;
        }
      </style>
    </head>
    <body>
    <div class="box" id="screen">
      <ul>
        <li><img src="imagess/01.jpg" alt=""/></li>
        <li><img src="imagess/02.jpg" alt=""/></li>
        <li><img src="imagess/03.jpg" alt=""/></li>
        <li><img src="imagess/04.jpg" alt=""/></li>
        <li><img src="imagess/04.jpg" alt=""/></li>
      </ul>
    </div>
    <script src="common.js"></script>
    <script>
      var current = 0;//只声明了一次
      function f1() {
        var ulObj = my$("screen").children[0];
        current -= 10;
        //每张图片宽度为300 当第四张图片播放结束就又重新开始播放第一张
        if (current < -1200) {
          ulObj.style.left = 0 + "px";
          current = 0;
        } else {
          ulObj.style.left = current + "px";
        }
      }
      //最开始没有获取焦点,那么通过定时任务自动移动图片
      var timeId=setInterval(f1, 30);
    
      //鼠标获得焦点
      my$("screen").onmouseover=function () {
        //停止
        clearInterval(timeId);
      };
      //鼠标失去焦点
      my$("screen").onmouseout=function () {
        //继续
        timeId=setInterval(f1, 30);
      };
    
    </script>
    </body>
    </html>
    

    原理

    实现自动轮播有一个需要注意的原理

    那就是第一张图需要和最后一张图是一样的,这里有五张图,那么第一张图和第五张图其实同一张图,当第四张图播放完即将切到第五张图的时候,
    其实就是切换到第一张图,这样做的目的就是让整个循环轮播变的很自然
    

    如果这里第五张和第一张图不一样就会有一闪的。

    很明显当第四张播放完切换到第一张的图的时候,会有一闪的动作,使整个动作并不自然。


    五、完整示例

    效果最顶上已经演示了,这里展示代码就可以。

    代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title></title>
      <style type="text/css">
        * {
          padding: 0;
          margin: 0;
          list-style: none;
          border: 0;
        }
    
        .all {
           500px;
          height: 200px;
          padding: 7px;
          border: 1px solid #ccc;
          margin: 100px auto;
          position: relative;
        }
    
        .screen {
           500px;
          height: 200px;
          overflow: hidden;
          position: relative;
        }
    
        .screen li {
           500px;
          height: 200px;
          overflow: hidden;
          float: left;
        }
    
        .screen ul {
          position: absolute;
          left: 0;
          top: 0px;
           3000px;
        }
    
        .all ol {
          position: absolute;
          right: 10px;
          bottom: 10px;
          line-height: 20px;
          text-align: center;
        }
    
        .all ol li {
          float: left;
           20px;
          height: 20px;
          background: #fff;
          border: 1px solid #ccc;
          margin-left: 10px;
          cursor: pointer;
        }
    
        .all ol li.current {
          background: #DB192A;
        }
    
        #arr {
          display: none;
        }
    
        #arr span {
           40px;
          height: 40px;
          position: absolute;
          left: 5px;
          top: 50%;
          margin-top: -20px;
          background: #000;
          cursor: pointer;
          line-height: 40px;
          text-align: center;
          font-weight: bold;
          font-family: '黑体';
          font-size: 30px;
          color: #fff;
          opacity: 0.3;
          border: 1px solid #fff;
        }
    
        #arr #right {
          right: 5px;
          left: auto;
        }
      </style>
    </head>
    <body>
    <div class="all" id='box'>
      <div class="screen"><!--相框-->
        <ul>
          <li><img src="images/1.jpg" width="500" height="200"/></li>
          <li><img src="images/2.jpg" width="500" height="200"/></li>
          <li><img src="images/3.jpg" width="500" height="200"/></li>
          <li><img src="images/4.jpg" width="500" height="200"/></li>
          <li><img src="images/5.jpg" width="500" height="200"/></li>
        </ul>
        <ol>
        </ol>
      </div>
      <div id="arr"><span id="left">&lt;</span><span id="right">&gt;</span></div>
    </div>
    <script src="common.js"></script>
    <script>
      //获取最外面的div
      var box = my$("box");
      //获取相框
      var screen = box.children[0];
      //获取相框的宽度
      var imgWidth = screen.offsetWidth;
      //获取ul
      var ulObj = screen.children[0];
      //获取ul中的所有的li
      var list = ulObj.children;
      //获取ol
      var olObj = screen.children[1];
      //焦点的div
      var arr = my$("arr");
    
      var pic = 0;//全局变量
      //创建小按钮----根据ul中的li个数
      for (var i = 0; i < list.length; i++) {
        //创建li标签,加入到ol中
        var liObj = document.createElement("li");
        olObj.appendChild(liObj);
        liObj.innerHTML = (i + 1);
        //在每个ol中的li标签上添加一个自定义属性,存储索引值
        liObj.setAttribute("index", i);
        //注册鼠标进入事件
        liObj.onmouseover = function () {
          //先干掉所有的ol中的li的背景颜色
          for (var j = 0; j < olObj.children.length; j++) {
            olObj.children[j].removeAttribute("class");
          }
          //设置当前鼠标进来的li的背景颜色
          this.className = "current";
          //获取鼠标进入的li的当前索引值
          pic = this.getAttribute("index");
          //移动ul
          animate(ulObj, -pic * imgWidth);
        };
      }
      //设置ol中第一个li有背景颜色
      olObj.children[0].className = "current";
    
    
      //克隆一个ul中第一个li,加入到ul中的最后=====克隆
      ulObj.appendChild(ulObj.children[0].cloneNode(true));
    
      //自动播放
     var timeId= setInterval(clickHandle,1000);
    
      //鼠标进入到box的div显示左右焦点的div
      box.onmouseover = function () {
        arr.style.display = "block";
        //鼠标进入废掉之前的定时器
        clearInterval(timeId);
      };
      //鼠标离开到box的div隐藏左右焦点的div
      box.onmouseout = function () {
        arr.style.display = "none";
        //鼠标离开自动播放
        timeId= setInterval(clickHandle,1000);
      };
      //右边按钮
      my$("right").onclick =clickHandle;
      function clickHandle() {
        //如果pic的值是5,恰巧是ul中li的个数-1的值,此时页面显示第六个图片,而用户会认为这是第一个图,
        //所以,如果用户再次点击按钮,用户应该看到第二个图片
        if (pic == list.length - 1) {
          //如何从第6个图,跳转到第一个图
          pic = 0;//先设置pic=0
          ulObj.style.left = 0 + "px";//把ul的位置还原成开始的默认位置
        }
        pic++;//立刻设置pic加1,那么此时用户就会看到第二个图片了
        animate(ulObj, -pic * imgWidth);//pic从0的值加1之后,pic的值是1,然后ul移动出去一个图片
        //如果pic==5说明,此时显示第6个图(内容是第一张图片),第一个小按钮有颜色,
        if (pic == list.length - 1) {
          //第五个按钮颜色干掉
          olObj.children[olObj.children.length - 1].className = "";
          //第一个按钮颜色设置上
          olObj.children[0].className = "current";
        } else {
          //干掉所有的小按钮的背景颜色
          for (var i = 0; i < olObj.children.length; i++) {
            olObj.children[i].removeAttribute("class");
          }
          olObj.children[pic].className = "current";
        }
    
      };
      //左边按钮
      my$("left").onclick = function () {
        if (pic == 0) {
          pic = 5;
          ulObj.style.left = -pic * imgWidth + "px";
        }
        pic--;
        animate(ulObj, -pic * imgWidth);
        //设置小按钮的颜色---所有的小按钮干掉颜色
        for (var i = 0; i < olObj.children.length; i++) {
          olObj.children[i].removeAttribute("class");
        }
        //当前的pic索引对应的按钮设置颜色
        olObj.children[pic].className = "current";
    
      };
    
      //设置任意的一个元素,移动到指定的目标位置
      function animate(element, target) {
        clearInterval(element.timeId);
        //定时器的id值存储到对象的一个属性中
        element.timeId = setInterval(function () {
          //获取元素的当前的位置,数字类型
          var current = element.offsetLeft;
          //每次移动的距离
          var step = 10;
          step = current < target ? step : -step;
          //当前移动到位置
          current += step;
          if (Math.abs(current - target) > Math.abs(step)) {
            element.style.left = current + "px";
          } else {
            //清理定时器
            clearInterval(element.timeId);
            //直接到达目标
            element.style.left = target + "px";
          }
        }, 10);
      }
    </script>
    </body>
    </html>
    


    ``` 你如果愿意有所作为,就必须有始有终。(27) ```
  • 相关阅读:
    医学影像分割之HIP
    c++画分形之Julia集与Mandelbrot集
    趣题一道
    华山论剑常用角点检测与角点匹配方法比较
    改变鼠标样式
    Unity3D Pro 利用摄像头产生俯视地图效果
    unity3D小地图教程
    WebBrowser网址中特殊字符的问题
    打开多个unity3D项目 (项目多开)
    u3d按住鼠标右键才转动摄像机的方法
  • 原文地址:https://www.cnblogs.com/qdhxhz/p/12142802.html
Copyright © 2011-2022 走看看