JS原生实现轮播图的几种方法


Posted in Javascript onMarch 23, 2021

轮播图

主要思想就是:

在大的容器里,装着一个很长的表,表是容器宽度的整数倍。

然后通过更改列表样式里的left属性来实现左右滑动。

本文旨在控制滑动五张图片,但在html中使用了七张图片,第一张和最后一张是有重复的,至于原因会在下面解释。

JS原生实现轮播图的几种方法

通过给容器设定overflow:hidden属性来保证只显示容器视口大小的一张图片。

<body>
 <div id="container">  /*容器*/
  <div id="wrap" style="left: -400px;">  /*存放图片的列表*/
   <div class="item item5">l5</div>
   <div class="item item1">1</div>
   <div class="item item2">2</div>
   <div class="item item3">3</div>
   <div class="item item4">4</div>
   <div class="item item5">5</div>
   <div class="item item1">r1</div>
  </div>
 </div>
 <div id="key">   /*设置按钮*/   
  <div id="list">         /*点击小圆圈切换到固定图片*/
   <div class="btn1 btnNum">1</div>
   <div class="btn2 btnNum">2</div>
   <div class="btn3 btnNum">3</div>
   <div class="btn4 btnNum">4</div>
   <div class="btn5 btnNum">5</div>
  </div>
  <div id="btn">     /*向左切换和向右切换的按钮*/
   <button class="left">←</button>
   <button class="right">→</button>
  </div>
 </div>
</body>

CSS:

可以给wrap列表设置flex属性,让图片在一行显示。其他布局可以按自己需求来做。

注意在定义id="wrap"d的节点中设置了内联样式left。因为在切换图片的时候我用到的是left属性,而如果不设置left的话,在DOM设置style时是找不到left属性的。

<style>
  #container {
   width: 400px;
   height: 300px;
   border: 8px rgb(8, 8, 8) solid;
   margin: 0 auto;
   margin-top: 150px;
   overflow: hidden;
   position: relative;
  }
  #wrap {
   width: 2800px;
   height: 300px;
   display: flex;
   position: relative;
  }
  .item {
   flex: 1;
   width: 400px;
   height: 300px;
  }
  .item1 {
   background-color: rosybrown;
  }
  .item2 {
   background-color: rgb(12, 226, 37);
  }
  .item3 {
   background-color: rgb(212, 221, 29);
  }
  .item4 {
   background-color: rgb(61, 27, 182);
  }
  .item5 {
   background-color: rgb(221, 23, 145);
  }
  #key {
   width: 400px;
   height: 300px;
   margin: 0 auto;
  }
  #list {
   width: 400px;
   height: 40px;
   display: flex;
   justify-content: center;
  }
  #list div {
   margin-top: 10px;
   margin-left: 10px;
   width: 20px;
   height: 20px;
   background-color: rgb(13, 162, 221);
   text-align: center;
   border-radius: 45%;
   opacity: 0.6;
  }
  #list div:hover {
   cursor: pointer;
   opacity: 1;
  }
  #btn {
   width: 400px;
   text-align: center;
  }
 </style>

这是完整的样式

JS原生实现轮播图的几种方法

每种颜色代表一张图片,且按序标了序号。起始位置是第二张图片。

至于为什么第一张和最后一张有额外重复的一张放在两端,是为了在做滑动效果的时候,最后一张(倒数第二张,粉紫色)可以继续向右顺滑的滑到第一张(其实是本图的第二张,浅棕色的)。第一张(本图第二张,浅棕色)向左滑动时可以顺滑的滑到最后一张(实则倒数第二张)。继续往下看。

1. 多种轮播方式

轮播必然离开不了定位,以及修改wrap列表的left属性,使其移动。

先初始化几个数据

var wrap = document.getElementById('wrap');
var nowleft = -400;     //用于存放当前列表的left的值
var currIndex = 1;          //用于存放当前是第几个图片
//定位到几个按钮
var btnNum = document.getElementsByClassName('btnNum'); //小圆圈
 
var right = document.getElementsByClassName('right')[0]; //向右滑的按钮
var left = document.getElementsByClassName('left')[0];      //向左滑的按钮

1.1 定时自动轮播效果

只讲向左自动滑动的效果

既然是自动轮播的,那必然少不了setInterval()定时器让其持续轮播。

function next() {
  setInterval(function() {      //设置每两秒切换一次图片
    wrap.style.transition = 'left 1s' //设定有过渡滑动的效果
        nowleft = parseInt(wrap.style.left) - 400;  //切换一次后nowleft应该减少(即向左滑)一个图片的宽度
    wrap.style.left = nowleft + 'px';   //然后将nowleft赋值给wrap的left属性
    if(parseInt(wrap.style.left) == -2400) { //判断到最后一个后,偷偷变回到最开头的位置
      setTimeout(() => {
       wrap.style.transition = 'none'  //因为是偷偷变回去,所以要取消过渡效果
       nowleft = -400;
       wrap.style.left = nowleft + 'px'
      },1200) //保证定时器的时间大于过度的时间且小于每次轮换的时间
     }
  },2000)
}

由于wrap.style.left 返回的是带px的字符串,所以用parseInt可以取得前面的数值/

1.2 按向右滑动按钮

right.addEventListener('click',function() {
  if(nowleft >= -2000){   //判断是否到最后一个图了,没有的话就开始滑动
   nowleft -= 400;
   wrap.style.transition = 'left 1s';
   wrap.style.left = nowleft + 'px';
  }
  if(nowleft == -2400) {   //如果到最后一个图了,就偷偷换回第一张图
   setTimeout(() => {
    wrap.style.transition = 'none';
    nowleft = -400;
    wrap.style.left = nowleft + 'px';
   },1020)
  }
})

1.3 小圆圈切换图片

for(let i = 0; i < btnNum.length; i++) {
  btnNum[0].style.opacity = 1;
  btnNum[i].addEventListener('click',function() {
   wrap.style.transition = 'left 1s';
   for(let j = 0; j < btnNum.length; j++) {
    btnNum[j].style.opacity = '0.6';
   }
   btnNum[i].style.opacity = 1;
   nowleft = nowleft - (i+1 - currIndex)*400;
   currIndex = i + 1;
   wrap.style.left = nowleft + 'px';
})

其实本文在控制从最后一个图偷偷换回第一张图的操作是有缺陷的,因为要把控序号5的图滑动到序号为r1的图是需要1s的,然而wrap.style.left是直接发生变化的,不会随着过渡期间发生位移而left一直变化。所以把控序号5完整滑动到r1后再偷偷切换到序号1的时间是有些难控制的。

而且比如从序号1连续点击3下是可以切换到序号4的。然是从序号5连续点击3下是不可以的,在r1切换到序号1的时候是无法响应点击效果的,因此此处交互差异会容易感到别扭。

如果想改善这个别扭的bug,可以用下防抖来改善。

Javascript 相关文章推荐
基于jquery实现后台左侧菜单点击上下滑动显示
Apr 11 Javascript
JavaScript中的全局对象介绍
Jan 01 Javascript
JavaScript数据结构和算法之图和图算法
Feb 11 Javascript
jQuery选择器基础入门教程
May 10 Javascript
全面解析JavaScript中“&amp;&amp;”和“||”操作符(总结篇)
Jul 18 Javascript
浅谈JS中的三种字符串连接方式及其性能比较
Sep 02 Javascript
JS实现用户注册时获取短信验证码和倒计时功能
Oct 27 Javascript
canvas时钟效果
Feb 16 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
Mar 02 Javascript
js使用原型对象(prototype)需要注意的地方
Aug 28 Javascript
认识jQuery的Promise的具体使用方法
Oct 10 jQuery
vue 实现复制内容到粘贴板clipboard的方法
Mar 17 Javascript
几款主流好用的富文本编辑器(所见即所得常用编辑器)介绍
vue+flask实现视频合成功能(拖拽上传)
Mar 04 #Vue.js
React服务端渲染原理解析与实践
Mar 04 #Javascript
vue打开新窗口并实现传参的图文实例
Mar 04 #Vue.js
Vue-router编程式导航的两种实现代码
Mar 04 #Vue.js
手写Vue2.0 数据劫持的示例
Mar 04 #Vue.js
vue3.0封装轮播图组件的步骤
Mar 04 #Vue.js
You might like
mysql 性能的检查和优化方法
2009/06/21 PHP
PHP企业级应用之常见缓存技术篇
2011/01/27 PHP
基于PHP的简单采集数据入库程序【续篇】
2014/07/30 PHP
gearman管理工具GearmanManager的安装与php使用方法示例
2020/02/27 PHP
JavaScript 事件冒泡简介及应用
2010/01/11 Javascript
js 数值项目的格式化函数代码
2010/05/14 Javascript
优化innerHTML操作(提高代码执行效率)
2011/08/20 Javascript
Jquery 获取checkbox的checked问题
2011/11/16 Javascript
Jquery Uploadify上传带进度条的简单实例
2014/02/12 Javascript
JS判断客户端是手机还是PC的2个代码
2014/04/12 Javascript
js键盘事件的keyCode
2014/07/29 Javascript
jQuery插件EnPlaceholder实现输入框提示文字
2015/06/05 Javascript
Jquery实现瀑布流布局(备有详细注释)
2015/07/31 Javascript
浅析Node.js实现HTTP文件下载
2016/08/05 Javascript
AngularJS通过$sce输出html的方法
2016/09/22 Javascript
JS设计模式之状态模式概念与用法分析
2018/02/05 Javascript
Vue-cli3项目配置Vue.config.js实战记录
2018/07/29 Javascript
node使用request请求的方法
2019/12/20 Javascript
浅谈VUE中演示v-for为什么要加key
2020/01/16 Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
2020/02/19 Javascript
[01:35]2018完美盛典章节片——共竞
2018/12/17 DOTA
Centos5.x下升级python到python2.7版本教程
2015/02/14 Python
MySQL适配器PyMySQL详解
2017/09/20 Python
python selenium UI自动化解决验证码的4种方法
2018/01/05 Python
详解Python self 参数
2019/08/30 Python
在Python中使用filter去除列表中值为假及空字符串的例子
2019/11/18 Python
Python通过两个dataframe用for循环求笛卡尔积
2020/04/29 Python
Selenium结合BeautifulSoup4编写简单的python爬虫
2020/11/06 Python
如何用PyPy让你的Python代码运行得更快
2020/12/02 Python
Auchan Direct波兰:欧尚在线杂货店
2016/10/19 全球购物
养成教育经验材料
2014/05/26 职场文书
社区工作者个人总结
2015/02/28 职场文书
离职证明格式样本
2015/06/12 职场文书
2016中秋节晚会开场白
2015/11/26 职场文书
2016年学校党支部创先争优活动总结
2016/04/05 职场文书
Python list列表删除元素的4种方法
2021/11/01 Python