• js — 原生轮播图的制作


    原生轮播图

    1、封装一个简单的动画函数

    animate.js文件

    // 主要进行简单动画函数的封装
    /*
      业务实现:封装的animate动画主要实现obj对象简单的左右移动的功能
      其中,obj为目标对象;target为对象需要移动的目标;
      callback为回调函数,可以在动画结束后实现相关的操作
     */
    function animate(obj, target, callback) {
    
      // 清除在此之前的定时器,保证一次只开一个定时器
      clearInterval(obj.timer);
      //使用定时器实现左右移动,其中,给每一个对象设置一个定时器
      obj.timer = setInterval(() => {
    
        //这里让动画减速运行,每次运行时,步长按规律减小,但是这样的话,步长值可能有小数,需要取整
        var step = (target - obj.offsetLeft) / 10;
    
        //对步长值取整。向右移动时,向上取整(Math.ceil);向左移动时,向下取整(Math.floor)
        step = step > 0 ? Math.ceil(step) : Math.floor(step);
    
        if(obj.offsetLeft == target) {
          // 如果到达目的地之后,清除动画
          clearInterval(obj.timer);
          if(callback) {
            // 如果传入的参数有回调函数,则调用回调函数
            callback();
          }
        }
    
        // obj.style.left获取的是具有定位属性的父元素的左边距。
        // 并且obj.style.left是可读写的;而obj.offsetLeft是只读的属性,返回值为数值
        obj.style.left = obj.offsetLeft + step + 'px';  // 每调用一次,就会计算一下left值
      }, 15);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    使用animation.js中的动画效果

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>animate动画实现title>
    head>
    
    <style>
      span {
          display: block;
          position: relative;
          top: 50px;
          left: 0;
          width: 200px;
          height: 200px;
          background-color: #42b983;
      }
    style>
    <script src="animate.js">script>
    <body>
    
    <button class="btn400">移动到400的位置button>
    <button class="btn800">移动到800的位置button>
    <span>YiBospan>
    
    <script>
      window.addEventListener('load', function (){
        // var btn400 = document.getElementById('btn400');
        // var box1 = document.getElementById('box1');
        var btn400 = document.querySelector('.btn400');
        var btn800 = document.querySelector('.btn800');
        var span = document.querySelector('span');
        btn400.addEventListener('click', function () {
          animate(span, 400);
          // alert("1");
        });
        btn800.addEventListener('click', function() {
          animate(span, 800);
        })
      })
    script>
    body>
    
    
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    显示效果:

    在这里插入图片描述

    2、轮播图的实现

    实现思路及满足的效果

    网页轮播图需要满足的功能需求为:

    1. 鼠标经过轮播图模块时,左右按钮显示,鼠标离开,左右按钮隐藏
    2. 点击右侧按钮一次,图片向左播放一张。以此类推,左侧按钮同理,点击左侧按钮,图片向右播放一张。
    3. 图片播放的同时,下面的小圆圈模块跟随其一起变换
    4. 点击小圆圈,可以播放相应的图片
    5. 鼠标不经过轮播图,轮播图也会自动播放图片
    6. 鼠标经过轮播图模块,自动播放停止

    实现的步骤、过程:
    1)鼠标经过时:进行相应的显示隐藏左右箭头
    通过设置元素.style.display = ‘block’ / ‘none’ 来实现

    2)动态生成小圆圈
    小圆圈的个数要跟图片的张数保持一致,所以我们可以根据图片的张数,动态的生成 li 的个数
    思路:循环动态生成小圆点
    创建节点:createElement(‘li’)
    插入节点:ol.appendChild(li)
    给第一个小圆点,默认添加current类

    3)小圆圈的排他思想
    点击当前小圆圈,就添加current类;其余的小圆圈就移除这个current类
    注意:在生成小圆圈时,就绑定点击事件

    4)点击小圆圈滚动图片
    此时可以用到我们封装过的animate动画函数。需要将js文件引入,注意:animate.js文件引入在前,因为index.js文件需要用到animate.js文件
    注意
    使用动画前,该元素必须有定位
    是ul移动,不是li移动
    计算滚动图片的距离:点击某个小圆圈,就让图片滚动,移动距离为:小圆圈的索引号乘以图片的宽度

    5)右侧按钮无缝滚动
    需求:点击右侧按钮一次,就让图片滚动一张
    实现思路:
    声明一个变量num,点击右侧按钮(箭头)一次,让这个变量乘以图片宽度,就是ul滚动的距离
    图片要做到无缝滚动的原理
    把ul第一个li复制一份,放到ul的最后面
    当图片滚动到克隆的最后一张图片时,让ul快速地、不做动画的跳到最左侧:left为0,同时将num赋值为0,然后就可以从新开始滚动了。

    6)克隆第一张图片
    克隆ul的第一个li,cloneNode(),传入的参数为true,为深克隆,可复制里面的节点
    将克隆的li,使用appendChild(),添加到ul的后面

    7)小圆圈跟随右侧按钮变化
    点击右侧按钮(箭头),小圆圈跟随其变化
    最简单的做法是再声明一个变量circle,每次点击自增1。需要注意的是:左侧按钮也需要这个变量,所以可以声明为全局变量
    但是图片比我们生成的小圆圈多一个,所以,必须加一个判断条件
    如果circle == 4 (ul.length - 1),就重新复原为0

    8)自动播放功能

    添加一个定时器
    自动播放轮播图,实际上就类似于点击了右侧按钮
    使用手动调用右侧按钮点击事件 arrow_r.click()即可
    鼠标经过focus就停止定时器
    鼠标离开时就开启定时器

    节流阀:
    作用:防止轮播图按钮连续点击造成播放过快
    节流阀的目的:当上一个函数动画内容执行完毕,再执行下一个函数动画,让事件无法连续触发
    核心实现思路:利用回调函数,添加一个变量来控制,锁住和解锁函数

    文件的目录结构:

    在这里插入图片描述

    index.html文件

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>原生轮播图title>
      <link rel="stylesheet" href="css/index.css">
      <script src="js/animate.js">script>
      <script src="js/index.js">script>
    head>
    <body>
    
      <div class="focus">
        
        <a href="javascript:;" class="arrow-l"><a>
        
        <a href="javascript:;" class="arrow-r">>a>
    
        
        <ul>
          <li>
            <a href="#"><img src="./images/11.jpg" alt="">a>
          li>
          <li>
            <a href="#"><img src="./images/12.jpg" alt="">a>
          li>
          <li>
            <a href="#"><img src="./images/14.jpg" alt="">a>
          li>
          <li>
            <a href="#"><img src="./images/15.jpg" alt="">a>
          li>
        ul>
    
        
        <ol class="circle">
    
        ol> 
      div>
     
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    index.css文件

    /* 1. 配置基础的css样式*/
    * {
        margin: 0;
        padding: 0;
    }
    
    /*去除li前面的点点*/
    li {
        list-style: none;
    }
    /*去除链接的下划线*/
    a {
        color: #666;
        text-decoration: none;
    }
    
    /* 2.配置项目中的样式 */
    .focus {
        position: relative;
        width: 320px;
        height: 320px;
        margin: 20px auto;
        overflow: hidden;
        background-color: #42b983;
    }
    .focus ul {
        position: absolute;
        top: 0;
        left: 0;
        width: 600%;
    }
    .focus ul li {
        float: left;
    }
    
    .arrow-l,
    .arrow-r{
        display: none;
        position: absolute;
        top: 50%;
        margin-top: -20px; /* 和top:50%搭配,使其在父元素中垂直居中*/
        width: 24px;
        height: 40px;
        line-height: 40px;  /* 让箭头垂直居中*/
        text-align: center; /* 让箭头水平居中 */
        background-color: rgba(0, 0, 0, .3);
        color: #fff;
        z-index: 1; /*提高元素的层级,不然显示不出来*/
    }
    .arrow-r {
        right: 0;
    }
    
    .circle {
        position: absolute;
        bottom: 10px;
        left: 50px
    }
    .circle li {
        float: left;
        width: 8px;
        height: 8px;
        /*background-color: #fff;*/
        border: 2px solid rgba(255, 255, 255, 0.5);
        margin: 0 3px;
        border-radius: 50%;
    
    }
    
    .current {
        background-color: #fff;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    index.js文件

    window.addEventListener('load', function () {
      //获取元素
      var arrow_l = document.querySelector('.arrow-l');
      var arrow_r = document.querySelector('.arrow-r');
      var focus = document.querySelector('.focus');
      var focusWidth = focus.offsetWidth; //获取轮播图区域的大小,也就是图片的大小,它们是相等的
    
      // 1.鼠标经过时,显示隐藏的箭头
      focus.addEventListener('mouseenter', function () {
        arrow_l.style.display = 'block';
        arrow_r.style.display = 'block';
    
        // 鼠标经过时,停止定时器
        clearInterval(timer);
        timer = null;
      })
    
      //2.鼠标离开时,隐藏箭头
      focus.addEventListener('mouseleave', function () {
        arrow_l.style.display = 'none';
        arrow_r.style.display = 'none';
    
        // 鼠标离开时,开启定时器
        timer = setInterval(() => {
          arrow_r.click()
        }, 2500)
      })
    
      // 3.动态生成小圆点:有几张图片,就生成几个
      var ul = focus.querySelector('ul');
      var ol = focus.querySelector('.circle');
      for(var i = 0; i < ul.children.length; i++) {
        var li = document.createElement('li');
    
        // 记录小圆圈创建的索引号,使用setAttribute(),设置自定义属性
        li.setAttribute('index', i);
        ol.appendChild(li);
    
        // 4.小圆圈的排他思想,添加current类
        li.addEventListener('click', function() {
          // 干掉其他人
          for(var i = 0; i < ol.children.length; i++) {
            ol.children[i].className = '';
          }
          // this指的是当前事件监听的li  留下我自己
          this.className = 'current';
    
          // 5.点击小圆圈,滚动图片,滚动距离:小圆圈的索引值*图片的宽度
          // 获取当前li的索引值
          var index = this.getAttribute('index');
          num = index;
          circle = index;
          animate(ul, -index * focusWidth)
        })
      }
    
      // 将ol中的第一个孩子的类名设置为current
      ol.children[0].className = "current";
    
      // 6.克隆第一个li,放在ul的最后 这里是深克隆呀
      var first = ul.children[0].cloneNode(true);
      ul.appendChild(first); //这个不会影响之前设置index的li,因为克隆没有在循环中克隆
    
      // 7.点击右侧按钮(箭头),图片滚动一张
      var num = 0;  //用来标记当前的图片索引,作用与index相似
      var circle = 0;  //circle,用来控制小圆圈的播放
      var flag = true;  // 设置节流阀,否则使用定时器点击左右轮播的按钮时,它会越来越快
    
      arrow_r.addEventListener('click', function () {
        if(flag) {
          flag = false; //关闭节流阀
          // 如果走到了最后克隆的这张图片,此时,ul要快速复原
          if(num == ul.children.length - 1) {
            ul.style.left = 0;
            num = 0;
          }
          num++;
          animate(ul, -num * focusWidth, function () {
            flag = true; // 打开节流阀
          });
    
          // 8.点击右侧按钮时,小圆圈也跟着改变
          circle++;
          if(circle == ol.children.length) {
            circle = 0; //遍历完了之后,重置为0
          }
          circleChange(); //因为后面需要用到小圆圈的变化,所以,我们可以将其抽取为一个函数
        }
      })
    
      // 左侧按钮的功能实现
      arrow_l.addEventListener('click', function () {
        if(flag) {
          flag = false; // 关闭节流阀
          // 如果走到了最后克隆的这张图片,此时,ul要快速复原
          if(num == 0) {
            num = ul.children.length - 1;
            ul.style.left = -num * focusWidth + 'px';
          }
          num--;
          animate(ul, -num * focusWidth, function () {
            flag = true; // 打开节流阀
          });
    
          // 8.点击右侧按钮时,小圆圈也跟着改变
          circle--;
          if(circle < 0) {
            circle = ol.children.length - 1; //遍历完了之后,重置为0
          }
          circleChange(); //因为后面需要用到小圆圈的变化,所以,我们可以将其抽取为一个函数
        }
      })
    
      // 清除小圆点函数
      function circleChange() {
        // 清除其他小圆圈的current类名
        for(var i = 0; i < ol.children.length; i++) {
          ol.children[i].className = '';
        }
        ol.children[circle].className = 'current';
      }
    
      // 10.自动播放轮播图
      var timer = setInterval(() => {
        // 手动调用点击事件
        arrow_r.click();
      }, 2500)
    
    
    
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131

    实现效果:

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    深度解读《深度探索C++对象模型》之数据成员的存取效率分析(二)
    工作来了,管理者该怎么分配下去?
    程序员-你得把自己卖出去
    学习ASP.NET Core Blazor编程系列二——第一个Blazor应用程序(上)
    基于深度学习的智能PCB板缺陷检测系统(Python+清新界面+数据集)
    算法设计与分析 SCAU8597 石子划分问题
    java基于ssm+vue+elementui的勤工助俭学管理系统
    RabbitMQ 安装登陆 提示:User can only log in via localhost
    TCP/IP传输协议学习
    CSS【详解】居中对齐 (水平居中 vs 垂直居中)
  • 原文地址:https://blog.csdn.net/Matcha_ice_cream/article/details/126499234