javaScript交互案例2

1、京东侧边导航条

需求:

    1. 原先侧边栏是绝对定位
    2. 当页面滚动到一定位置,侧边栏改为固定定位
    3. 页面继续滚动,会让返回顶部显示出来

思路:

    1. 需要用到页面滚动事件scroll,因为是页面滚动,所以事件源是document
    2. 滚动到某个位置,就是判断页面被卷去的上部值
    3. 页面被卷去的头部:可以通过window.pageYOffset获得,如果是被卷去的左侧window.pageXOffset
    4. 注意:元素被卷去的头部是element.scrollTop,如果是页面被卷去的头部则是window.pageYOffset
javascript 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>侧边栏案例</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      header,
      footer {
        width: 1000px;
        height: 200px;
        background-color: pink;
        margin: 0 auto;
      }
      main {
        width: 1000px;
        height: 800px;
        background-color: #bfa;
        margin: 0 auto;
      }
      nav {
        width: 60px;
        height: 200px;
        background-color: blue;
        position: absolute;
        right: 0;
        top: 250px;
        line-height: 30px;
      }
      span {
        display: block;
        width: 60px;
        height: 60px;
        background-color: red;
        margin-top: 140px;
        text-align: center;
        display: none;
      }
    </style>
  </head>
  <body>
    <header>头部</header>
    <nav>
      <span
        >返回 <br />
        顶部</span
      >
    </nav>
    <main>主体</main>
    <footer>底部</footer>
    <script>
      // 1、获取元素
      var span = document.querySelector("span");
      var nav = document.querySelector("nav");
      var main = document.querySelector("main");
      // 主体以上被卷去的距离
      var mainTop = main.offsetTop;
      // 侧边导航以上被卷去的距离
      var navTop = nav.offsetTop;
      console.log(navTop);
      // 2、页面滚动事件 scroll
      document.addEventListener("scroll", function () {
        // window.pageYOffset 获取页面被滚去的距离
        // 3、判断距离,变化定位
        if (window.pageYOffset >= mainTop) {
          // 3.1将定位改成固定定位
          nav.style.position = "fixed";
          // 3.2 改成固定定位后,会有跳动,需要重新设置定位的top值,否则还是原值
          nav.style.top = navTop - mainTop + "px";
          // 3.3 出现返回顶部字样
          span.style.display = "block";
        } else {
          nav.style.position = "absolute";
          nav.style.top = "300px";
          span.style.display = "none";
        }
      });
    </script>
  </body>
</html>

4、轮播图

(1)、搭建轮播图的结构

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>轮播图结构</title>
    <!-- <script src="../js/tools.js"></script> -->
    <script src="../js/animation.js"></script>
    <script src="./01.轮播图.js"></script>
    <style>
      * {
        padding: 0;
        margin: 0;
        list-style: none;
        text-decoration: none;
      }
      #outer {
        width: 590px;
        height: 470px;
        border: 10px solid red;
        margin: 50px auto;
        position: relative;
        overflow: hidden;
      }
      #outer > ul {
        width: 500%;
        position: absolute;
        left: 0;
        top: 0;
      }
      #outer > ul > li {
        float: left;
      }
      .dot {
        position: absolute;
        bottom: 30px;
        left: 50%;
        transform: translate(-50%, -50%);
      }
      .dot > a {
        display: inline-block;
        width: 15px;
        height: 15px;
        border-radius: 50%;
        background-color: #999;
        margin: 0 5px;
      }
      .dot > .active,
      .dot > a:hover {
        background-color: orange;
      }
      .prev,
      .next {
        width: 40px;
        height: 40px;
        background-color: rgba(0, 0, 0, 0.4);
        text-align: center;
        position: absolute;
        font-size: 30px;
        color: #999;
        /* 隐藏左右按钮 */
        display: none;
      }
      .prev > a,
      .next > a {
        color: #fff;
      }
      .prev {
        left: 10px;
        top: 42%;
      }
      .next {
        right: 10px;
        top: 42%;
      }
    </style>
  </head>
  <body>
    <div id="outer">
      <!-- 图片部分 -->
      <ul>
        <li>
          <a href="#"><img src="./img/1.jpg" alt="" /></a>
        </li>
        <li>
          <a href="#"><img src="./img/2.jpg" alt="" /></a>
        </li>
        <li>
          <a href="#"><img src="./img/3.jpg" alt="" /></a>
        </li>
        <li>
          <a href="#"><img src="./img/4.jpg" alt="" /></a>
        </li>
        <!-- <li>
          <a href="#"><img src="./img/1.jpg" alt="" /></a>
        </li> -->
      </ul>
      <!-- 导航点  class="active"-->
      <div class="dot">
        <!-- <a href="#" ></a>
        <a href="#"></a>
        <a href="#"></a>
        <a href="#"></a> -->
      </div>
      <!-- 左右导航 -->
      <ol class="prevNext">
        <li class="prev">
          <a href="#"> &lt;</a>
        </li>
        <li class="next">
          <a href="#">&gt;</a>
        </li>
      </ol>
    </div>
  </body>
</html>

(2)、es5写法

功能需求:

  • 鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮
  • 点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理
  • 图片播放的同时,下面的小圆圈模块跟随一起变化
  • 点击小圆圈,可以播放相应图片
  • 鼠标不经过轮播图,轮播图也会自动播放图片
  • 鼠标经过,轮播图模块,自动播放停止

es5写法

javascript 复制代码
window.addEventListener("load", function () {
  var prev = this.document.querySelector(".prev");
  var next = this.document.querySelector(".next");
  var outer = this.document.querySelector("#outer");
  //需求1 鼠标移入,左右按钮出现隐藏
  outer.addEventListener("mouseenter", function () {
    prev.style.display = "block";
    next.style.display = "block";
  });
  outer.addEventListener("mouseleave", function () {
    prev.style.display = "none";
    next.style.display = "none";
  });

  //需求2 动态生成pot,小圆圈
  // 2.1、获取元素
  var ulL = outer.querySelector("ul");
  var dot = outer.querySelector(".dot");
  for (var i = 0; i < ulL.children.length; i++) {
    // 2.2、动态的创建a标签
    var a = this.document.createElement("a");
    // 给a添加索引,方便下面计算点击圆圈,移动图片
    a.setAttribute("index", i);
    // 2.3 插入节点
    dot.appendChild(a);
  }
  // 2.4 给第一个小点,设置选中样式
  dot.children[0].className = "active";

  //需求3  给点击的小圆圈加上类名 active  排他思想
  var as = dot.querySelectorAll("a");
  for (var i = 0; i < as.length; i++) {
    as[i].addEventListener("click", function () {
      for (var j = 0; j < as.length; j++) {
        dot.children[j].className = "";
      }
      this.className = "active";

      //需求4   点击小圆圈,移动图片 move(obj, attr, target, speed, callback)
      //4.1  获取点击a的索引,这个索引是创建a时添加的,用来表示每个a
      var index = this.getAttribute("index");
      // 4.2 ulL的移动距离,小圆圈的索引号*图片的宽度
      animation(ulL, -index * 590);
      // move(ulL, "left", -index * 590, 10);
      // 获取到index后,需要同步赋值给下面的num跟current

      // 以便可以同步小圆点,跟点击下一张的变化
      num = index;
      current = index;
    });
  }
  // 克隆第一张图片,不在结构里加
  // 循环生成小圆点的时候,还没有克隆这个图片。所有不会自动生成的小圆圈
  var firstImg = ulL.children[0].cloneNode(true);
  ulL.appendChild(firstImg);

  //需求5  点击左右按钮,实现上下一张切换
  var num = 0;
  var current = 0; //用来标记小圆圈
  next.addEventListener("click", function () {
    //无缝滚动  如果走到了最后一张图片,此时我们的ul要快速复原left改为0
    if (num >= ulL.children.length - 1) {
      ulL.style.left = 0;
      num = 0;
    }
    num++;
    animation(ulL, -num * 590);
    // move(ulL, "left", -num * 590, 20);

    // 点击右侧按钮,小圆圈跟着跳动
    current++;
    // 如果curent的数值跟小圆圈的数量一样,走到了克隆的那张图片,要还原为0
    if (current == dot.children.length) {
      current = 0;
    }
    for (var i = 0; i < dot.children.length; i++) {
      dot.children[i].className = "";
    }
    dot.children[current].className = "active";
  });

  //需求6  左侧按钮的功能
  prev.addEventListener("click", function () {
    if (num == 0) {
      num = ulL.children.length - 1;
      ulL.style.left = -num * 590 + "px";
    }
    num--;
    animation(ulL, -num * 590);
    // move(ulL, "left", -num * 590, 20);
    // 点击右侧按钮,小圆圈跟着跳动
    current--;
    // 如果curent的数值跟小圆圈的数量一样,要还原为0
    if (current < 0) {
      current = dot.children.length - 1;
    }
    for (var i = 0; i < dot.children.length; i++) {
      dot.children[i].className = "";
    }
    dot.children[current].className = "active";
  });

  //需求7  自动播放功能
  var timer = setInterval(function () {
    // 手动调用点击事件
    next.click();
  }, 2000);
  
  //需求8  鼠标移入,自动播放停止
  outer.addEventListener("mouseenter", function () {
    clearInterval(timer);
    timer = null;
  });

  //需求9  鼠标移出,重新开启定时器
  outer.addEventListener("mouseleave", function () {
    timer = setInterval(function () {
      // 手动调用点击事件
      next.click();
    }, 2000);
  });
});

(3)、es6写法

javascript 复制代码
window.onload = function () {
  var that;
  class Swiper {
    constructor() {
      // 保存this
      that = this;
      // 1.1 获取对应元素
      this.prev = document.querySelector(".prev");
      this.next = document.querySelector(".next");
      this.outer = document.querySelector("#outer");
      //2.1 获取导航点父元素
      this.dot = document.querySelector(".dot");
      this.imgList = document.querySelector(".imgList");
      //   2.4 调用创建小圆点函数
      this.creatDot();
      //   3.1 获取图片导航小圆点
      this.dots = document.querySelectorAll(".dot a");
      //   4.1 用于标识当前的图片位置
      this.num = 0;
      this.current = 0; //用于标识当前小圆点的位置
      //   5、克隆轮播图第一张照片
      this.cloneFirstImg();

      // 调用监听函数
      this.addevent();
    }
    // 所有监听函数
    addevent() {
      console.log(this);
      // 1.2 监听鼠标是否移入
      this.outer.addEventListener("mouseenter", that.pervNextShow);
      this.outer.addEventListener("mouseleave", that.pervNextNode);
      //  3.3 监听是否点击了小圆点
      for (var i = 0; i < this.dots.length; i++) {
        // 保存i值,方便找对应的图片
        this.dots[i].index = i;
        // 默认第一个按钮为选中状态
        this.dots[0].className = "active";
        // 点击切换背景色
        this.dots[i].addEventListener("click", that.updatBackgroundColor);
        // 点击切换图片
        this.dots[i].addEventListener("click", that.updatImg);
      }
      //   4、点击next
      this.next.addEventListener("click", that.nextFun);
      //   5、点击prev
      this.prev.addEventListener("click", that.prevFun);
      //   8、调用自动轮播函数
      this.timer = null; //定义标识定时器
      this.autoPlay();
      // 9、移入outer,暂停自动轮播
      this.outer.addEventListener("mouseenter", that.stopAutoPlay);
      //   10、移出outer,继续自动轮播
      this.outer.addEventListener("mouseleave", that.startAutoPlay);
    }
    // 所有功能函数
    // 注意函数中的this指向
    // 1.3 上下一张出现
    pervNextShow() {
      that.prev.style.display = "block";
      that.next.style.display = "block";
    }
    pervNextNode() {
      that.prev.style.display = "none";
      that.next.style.display = "none";
    }
    // 2、根据图片创建导航点
    creatDot() {
      var imgNum = this.imgList.children.length;
      for (var i = 0; i < imgNum; i++) {
        var a = `<a href="#" ></a>`;
        this.dot.insertAdjacentHTML("afterBegin", a);
      }
    }
    // 3.4 点击小圆点,切换颜色
    updatBackgroundColor(e) {
      // (1)、先解决默认行为,超链接跳转的问题
      e.preventDefault();
      //  (2)、点击颜色切换
      for (var i = 0; i < that.dots.length; i++) {
        that.dots[i].className = "";
      }
      this.className = "active";
    }

    // 3.5 点击小圆点,切换图片
    updatImg() {
      //  (3)、根据图片导航点的索引移动图片
      animation(that.imgList, -590 * this.index);
    }

    // 4、点击下一张,切换图片
    nextFun() {
      // 根据num的值,判断num是否++
      var len = that.imgList.children.length;
      if (that.num >= len - 1) {
        that.imgList.style.left = 0;
        that.num = 0;
      }
      that.num++;

      animation(that.imgList, -that.num * 590);

      // 点击下一张照片后,更换小圆点背景色
      that.current++;
      if (that.current == that.dots.length) that.current = 0;
      //调用更换小圆点颜色函数
      that.changeBackgroundColor();
    }
    // 5、为解决轮播图最后一张快速问题,多赋值一张照片
    cloneFirstImg() {
      var firstImg = that.imgList.children[0].cloneNode(true);
      that.imgList.appendChild(firstImg);
    }
    // 6、更换小圆点颜色
    changeBackgroundColor() {
      for (var i = 0; i < that.dots.length; i++) {
        that.dots[i].className = "";
      }
      that.dots[that.current].className = "active";
    }
    // 7、点击prev,上一张照片
    prevFun() {
      // 根据num的值,判断显示图片
      if (that.num == 0) {
        that.num = that.imgList.children.length - 1;
        that.imgList.style.left = -that.num * 590 + "px";
      }
      that.num--;
      animation(that.imgList, -that.num * 590);
      //  同步图片小圆点的背景色
      if (that.current <= 0) {
        that.current = that.dots.length;
      }
      that.current--;
      //调用更换小圆点颜色函数
      that.changeBackgroundColor();
    }
    // 8、自动轮播,每隔2s,调动一次next函数
    autoPlay() {
      that.timer = setInterval(function () {
        that.nextFun();
      }, 2000);
    }
    // 9、鼠标移入轮播图,停止自动轮播
    stopAutoPlay() {
      //   console.log(that.timer);
      clearInterval(that.timer);
      that.timer = null;
    }
    // 10、鼠标移出轮播图,开始自动轮播
    startAutoPlay() {
      that.autoPlay();
    }
  }
  new Swiper();
};

(4)、节流阀优化

防止轮播图按钮连续点击造成播放过快

节流阀目的,当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发

核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数

开始设置一个变量 var flag =true

if(flag){ flag = false,do something} 关闭水龙头

利用回调函数动画执行完毕, falg=true 打开水龙头

javascript 复制代码
  // 10、节流阀优化点击过快问题
  var flag = true;
  next.addEventListener("click", function () {
    if (flag) {
      flag = false; // 关闭水龙头
      //无缝滚动  如果走到了最后一张图片,此时我们的ul要快速复原left改为0
      if (num >= ulL.children.length - 1) {
        ulL.style.left = 0;
        num = 0;
      }
      num++;
      animation(ulL, -num * 590, function () {
        flag = true;
      });
      // move(ulL, "left", -num * 590, 20);

      // 点击右侧按钮,小圆圈跟着跳动
      current++;
      // 如果curent的数值跟小圆圈的数量一样,走到了克隆的那张图片,要还原为0
      if (current == dot.children.length) {
        current = 0;
      }
      for (var i = 0; i < dot.children.length; i++) {
        dot.children[i].className = "";
      }
      dot.children[current].className = "active";
    }
  });

  //需求6  左侧按钮的功能
  prev.addEventListener("click", function () {
    if (flag) {
      flag = false;
      if (num == 0) {
        num = ulL.children.length - 1;
        ulL.style.left = -num * 590 + "px";
      }
      num--;
      animation(ulL, -num * 590, function () {
        flag = true;
      });
      // move(ulL, "left", -num * 590, 20);
      // 点击右侧按钮,小圆圈跟着跳动
      current--;
      // 如果curent的数值跟小圆圈的数量一样,要还原为0
      if (current < 0) {
        current = dot.children.length - 1;
      }
      for (var i = 0; i < dot.children.length; i++) {
        dot.children[i].className = "";
      }
      dot.children[current].className = "active";
    }
  });
相关推荐
数据小爬虫@1 分钟前
利用Python爬虫获取淘宝店铺详情
开发语言·爬虫·python
蒟蒻的贤11 分钟前
vue学习11.21
javascript·vue.js·学习
高 朗11 分钟前
【GO基础学习】基础语法(2)切片slice
开发语言·学习·golang·slice
寒笙LED27 分钟前
C++详细笔记(六)string库
开发语言·c++·笔记
IT书架33 分钟前
golang面试题
开发语言·后端·golang
初遇你时动了情1 小时前
uniapp 城市选择插件
开发语言·javascript·uni-app
zhangjr05751 小时前
【HarmonyOS Next】鸿蒙实用装饰器一览(一)
前端·harmonyos·arkts
不爱学习的YY酱2 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
zongzi_4942 小时前
二次封装的天气时间日历选择组件
开发语言·javascript·ecmascript
kikyo哎哟喂2 小时前
Java 代理模式详解
java·开发语言·代理模式