• Javascript专题(三)b.各种轮播和细节分析--上下滚动轮播


    这一次,我们用原生JS实现上下滚动方式的轮播。顺带学习一下用JS来创建HTML元素。

    上一次写的轮播是淡入淡出效果的,相对来说其实是比较简单的。

    github源码: 上下轮播源码-github

    A. 先将基本架构搭好。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
    <style>
    body, div, ul, li {
      margin:0;
      padding:0;
      list-style: none;
      border: 0;
    }
    </style>
    </head>
    <body>
      <div id="box">
        <ul class="list-image">
          <li><img src="pic1.jpg" width="500px" height="200px"></li>
          <li><img src="pic2.jpg" width="500px" height="200px"></li>
          <li><img src="pic3.jpg" width="500px" height="200px"></li>
          <li><img src="pic4.jpg" width="500px" height="200px"></li>
          <li><img src="pic5.jpg" width="500px" height="200px"></li>
        </ul>
      </div>
    </body>
    <script></script>
    </html>
    

    B. 这里我们用JS来添加HTML元素,以图片的个数来添加按钮的个数。写在我们的script标签之中。

      const oBox = document.getElementById("box");
      const oUl = oBox.getElementsByTagName("ul")[0];
      const oImage = oUl.getElementsByTagName("li");
      // 根据图片 li 的个数生成同样数量的 按钮 li
      let eleArr = [];
      for (let i = 0; i < oImage.length; i++) {
        eleArr.push("<li>" + (i + 1) + "</li>");
      }
      // 创建节点元素并且添加节点元素至 html 里面
      var oEle = document.createElement("ul");
      oEle.className = "list-number";
      oEle.innerHTML = eleArr.join("");
      oBox.appendChild(oEle);
    

    此后效果如下:


    C. 之后修改style里面的样式

    /* reset */
    body, div, ul, li {
      margin:0;
      padding:0;
      list-style: none;
      border: 0;
    }
    body{
      background: #fff;
    }
    /* wrap */
    #box {
      position: relative;
       502px;
      height: 202px;
      margin: 10px auto;
      border: 8px solid #002232;
    }
    /* image */
    #box .list-image {
       500px;
      height: 200px;
      overflow: hidden;
    }
    #box .list-image li {
      border: 1px solid purple;
       500px;
      height: 200px;
      /*这里也设置宽高,解决的是默认行间距问题*/
    }
    #box .list-image li img {
       500px;
      height: 200px;
    }
    /* number */
    #box .list-number {
      position: absolute;
      right: 0;
      bottom: 5px;
    }
    #box .list-number li {
      float: left;
      margin-right: 10px;
       20px;
      height: 20px;
      font: 12px / 20px Arial;
      border-radius: 10px;
      background-color: #f60;
      text-align: center;
      color: #fff;
      opacity: 0.7;
      filter: alpha(opacity = 70);
      cursor: pointer;
    }
    #box .list-number li.current {
      opacity: 1;
      filter: alpha(opacity=100);
    }
    
    • 其中的 filter: alpha(opacity=100)主要用于兼容IE7
    • 行内文字的垂直居中需要使得line-heightheight相同
    • 这里的line-height采用三者的简写font: 12px/20px Arial,分别简写了font-size,line-heiht,font-family.

    D. 接下来,我们来实现上下滚动的JS代码,我们先实现手动版本的。

    修改JS如下

      const oBox = document.getElementById("box");
      const oUl = oBox.getElementsByTagName("ul")[0];
      const oImage = oUl.getElementsByTagName("li");
      // 根据图片 li 的个数生成同样数量的 按钮 li
      let eleArr = [];
      for (let i = 0; i < oImage.length; i++) {
        eleArr.push("<li>" + (i + 1) + "</li>");
      }
      // 创建节点元素并且添加节点元素至 html 里面
      var oEle = document.createElement("ul");
      oEle.className = "list-number";
      oEle.innerHTML = eleArr.join("");
      oBox.appendChild(oEle);
      // 手动点击,触发轮播的触发函数
      const oNumber = oEle.getElementsByTagName("li");
      for (var i = 0; i < oNumber.length; i++) {
        oNumber[i].index = i;
        oNumber[i].onmouseover = function () {
          Show(this.index);
        }
      }
      // 轮播触发,并且内部调用移动效果函数
      function Show(index) {
        for (let i = 0; i < oNumber.length; i++) {
          oNumber[i].className = "";
        }
        oNumber[index].className = "current";
        Move(index);
      }
      // 移动效果函数
      function Move(index) {
      }
    

    E. 接下来我们来实现移动函数

    实现上下滚动,我们想一下要怎么实现,应该就是改变absolute元素高度吧?探索过程

    function Move(x) {
      console.log(oUl.offsetHeight); // 202
      console.log(oUl.offsetTop);//0
      oUl.offsetHeight = 100;
      oUl.offsetTop = 100;
      console.log(oUl.offsetHeight);//202
      console.log(oUl.offsetTop);//0
    }
    
    
    诶,我发现不行??修改不了offsetHeight和offsetTop啊!查阅一下资料原来是这样子!

    预备知识:offsetTop、offsetLeft、offsetWidth、offsetHeight
    我们知道 offsetTop 可以获得 HTML 元素距离上方或外层元素的位置,style.top 也是可以的,二者的区别是:

    • offsetTop 返回的是数字,而 style.top 返回的是字符串,除了数字外还带有单位:px。(这里的style.top是读的css样式中的top:20px;这种形式的值,所以是带有"px"的)
    • offsetTop 只读,而 style.top 可读写。(style.top赋值切记加上"px",测试过发现IE下用数值是可以的,但其它主流chrome,opera,ff,safari都不能识别,所以必须加"px")
    • 如果没有给 HTML 元素指定过 top 样式,则 style.top 返回的是空字符串。

    offsetLeft 与 style.left、offsetWidth 与 style.width、offsetHeight 与 style.height 也都是类似区别。------------offsetTop 与style.top之间的区别

    综上所述,我们应该修改absolute元素的sytle.top才行。所以,首先,我们要让我们被移动的框变为absolute

    所以我们先给我们要移动的地方添加 absolute,继续修改CSS

    #box .list-image {
      position: absolute;
      border: 1px solid #fff;
       500px;
      height: 200px;
      overflow: hidden;
    }
    

    然后添加JS,于是我们加入以下代码看看效果!

    
    function Move(x){
      oUl.style.top=-100+"px";
      // 赋值的时候要加上"px"
      alert(oUl.style.top);
    }
    

    效果图是这样的---

    诶,这个是我们的预期吗?????????????
    不是,那么是为什么呢!因为!!这里的overflow:hidden

    #box .list-image {
      position: absolute;
      border: 1px solid #fff;
       500px;
      height: 200px;
      overflow: hidden;
    }
    
    我们所移动的oUl就是它,而我们在这里写了overflow:hidden; ,那它就会把超出的部分全都隐藏了,然而我们要让它的长度足以装下所有的图片。我们应该让它的父级隐藏起来。像是夹着尾巴的人一样。

    也就是说,我们不能让它被隐藏。那么,我们一方面不能让这么长的一列图片耷拉下来,一方面又要实现overflow,于是,我们在oBox(oUl的父级)的地方用overflow就可以了

    #box {
      position: relative;
       502px;
      height: 202px;
      margin: 10px auto;
      border: 8px solid #002232;
    
      overflow: hidden;
    }
    /* image */
    #box .list-image {
      position: absolute;
      border: 1px solid #fff;
       500px;
      height: 200px;
    }
    

    变成了这样----

    接下来,我们改变相关的赋值,使其达成我们想要的效果吧!
    function Move(index) {
      oUl.style.top = -index * 202 + "px";
    }
    


    可以看见我们已经达成了我们的预期。


    F. 漂亮的移动效果

    我们发现切换正常!之后我们来做缓冲的效果,来使切换不那么突兀。我们来思考一个缓冲效果,比如我们可以做一个让它越到目的地速度越慢的缓冲效果。
    修改移动函数如下

      // 移动效果函数
      let timer = null;
      function Move(index) {
        clearInterval(timer);
        let target = -index * 202;
        timer = setInterval(function() {
          let speed = (target - oUl.offsetTop) / 10;
          // 速度为 目标位置 - 当前位置
          speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
          oUl.offsetTop === target ? clearInterval(timer) : oUl.style.top = oUl.offsetTop + speed + "px";
          // 没有到达目标,则不停止。
        }, 30);
      }
    

    具体思想就是:

    • x*oImage[0].offsetHeight为我们的目标值此处的 offsetHeight 为202 px.
    • 我们设置target为目标不变,通过我们所处的位置和目标位置的差值作为速度speed的变化量,即离目标越远,我们越快.
    • 然后让speed为整数,注意,如果这里不加这句话我们会有bug,取整,图片不能完美移动和重合.
    我们可以看到,我们的需求基本完成了。剩下的就是锦上添花了。

    G. 锦上添花,自动轮播

    之后我们还是来实现其自动轮播的效果,与上一个专题很像。
    加入代码

      // 添加自动轮播函数
      let nowIndex = 0;
      let autoTimer = null;
      oBox.onmouseout = function() {
        auto();
      }
      oBox.onmouseover = function() {
        clearInterval(autoTimer);
      }
      function auto() {
        autoTimer = setInterval(() => {
          if (nowIndex < oImage.length - 1) {
            nowIndex ++;
          } else {
            nowIndex = 0;
          }
          Show(nowIndex);
        }, 2000);
      }
      auto();
      // 起始的时候默认开始
    

    至此,我们的自动上下滚动轮播完成。

    上下轮播源码-github

  • 相关阅读:
    Hibernate
    Redis的学习
    Redis的人门以及使用
    Win32 配置文件用法
    Using virtual lists
    windows log
    Win查询注册表获取CPU与内存参数
    MFC 多线程及线程同步
    使用Custom Draw优雅的实现ListCtrl的重绘
    MFC工具栏设计
  • 原文地址:https://www.cnblogs.com/can-i-do/p/6861749.html
Copyright © 2020-2023  润新知