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);
}

使用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>YiBo</span>

<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>

显示效果:

在这里插入图片描述

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">&lt;</a>
    <!--右箭头-->
    <a href="javascript:;" class="arrow-r">&gt;</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>

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;
}

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)



})

实现效果:

在这里插入图片描述

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340