原生JS利用transform实现banner的无限滚动示例代码


Posted in Javascript onJune 15, 2020

功能

原生JS利用transform实现banner的无限滚动示例代码

  • 默认情况无限循环向右移动
  • 点击数字切换到对应图片
  • 点击左右切换可切换图片

原理

首先说下原理。

  • 在布局上所有的图片都是重叠的,即只要保证Y方向对齐即可,当前可见的图z-index层级最高。
  • 每隔3s中更换一张图片,使用setTimeout定时。
  • 使用gIndex记录当前可视区域的展示的是哪张图片下标,每次更换,计算下一张图片的下标。
  • 通过requestAnimationFrame实现一次图片切换的动画。

这种方法也可以做到整个页面始终只有2个img标签,而不必把所有的img节点全部创建出来,要点是每次更换不可见img的src。

原生JS利用transform实现banner的无限滚动示例代码

动画的实现

  • 首先定义一个timestap,这个值记录每个帧移动多少距离。定义初始step=0,记录移动的步数。
  • 每次移动的距离moveWidth是timestamp*step,图片1向右移动增加moveWidth,图片2从左侧进入moveWidth。因此,图片1的transform是translate(moveWidth), 而图片2的transform则是translate(moveWidth-图片宽度)。
  • step+1
  • 如果moveWidth>图片宽度,步骤5,否则requestAnimationFrame请求下一次执行,继续2-4.
  • 图片1和2都将位置放置在起始位置,图片2的z-index设置为最高。

这样就完成了一次移动的动画。

html代码

<header>
  <div class="box">
    <img src="imgs/banner1.jpg">
    <img src="imgs/banner2.jpg">
    <img src="imgs/banner3.jpg">
    <img src="imgs/banner4.jpg">
  </div>
  <div class="buttons">
    <div class="active">1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
  </div>
  <div class="left">
    <div class="arrow"></div>
  </div>
  <div class="right">
    <div class="arrow"></div>
  </div>
</header>

JS代码

var timeout = null;
window.onload = function () {
  var oLeft = document.querySelector('.left');
  var oRight = document.querySelector('.right');
  var oButton = document.querySelector('.buttons');
  var oButtons = document.querySelectorAll('.buttons div');
  var oImgs = document.querySelectorAll('.box img');
  var imgWidth = oImgs[0].width;
  var gIndex = 0;
  begainAnimate();

  // 绑定左右点击事件
  oLeft.onclick = function () {
    clearTimeout(timeout);
    leftMove();
    begainAnimate();
  };
  oRight.onclick = function () {
    clearTimeout(timeout);
    rightMove();
    begainAnimate();
  };
  // 绑定数字序号事件
  oButton.onclick = function (event) {
    clearTimeout(timeout);
    var targetEl = event.target;
    var nextIndex = (+targetEl.innerText) - 1;
    console.log(nextIndex);
    rightMove(nextIndex);
    begainAnimate();
  }
  // 默认初始动画朝右边
  function begainAnimate() {
    clearTimeout(timeout);
    timeout = setTimeout(function () {
      rightMove();
      begainAnimate();
    }, 3000);
  }
  // 向左移动动画
  function leftMove() {
    var nextIndex = (gIndex - 1 < 0) ? oImgs.length - 1 : gIndex - 1;
    animateSteps(nextIndex, -50);
  }
  // 向右移动动画
  function rightMove(nextIndex) {
    if (nextIndex == undefined) {
      nextIndex = (gIndex + 1 >= oImgs.length) ? 0 : gIndex + 1;
    }
    animateSteps(nextIndex, 50);
  }
  // 一次动画
  function animateSteps(nextIndex, timestamp) {
    var currentImg = oImgs[gIndex];
    var nextImg = oImgs[nextIndex];
    nextImg.style.zIndex = 10;
    var step = 0;
    requestAnimationFrame(goStep);
    // 走一帧的动画,移动timestamp
    function goStep() {
      var moveWidth = timestamp * step++;
      if (Math.abs(moveWidth) < imgWidth) {
        currentImg.style.transform = `translate(${moveWidth}px)`;
        nextImg.style.transform = `translate(${moveWidth > 0 ? (moveWidth - imgWidth) : (imgWidth + moveWidth)}px)`;
        requestAnimationFrame(goStep);
      } else {
        currentImg.style.zIndex = 1;
        currentImg.style.transform = `translate(0px)`;
        nextImg.style.transform = `translate(0px)`;
        oButtons[gIndex].setAttribute('class', '');
        oButtons[nextIndex].setAttribute('class', 'active');
        gIndex = nextIndex;
      }
    }
  }
}
window.onclose = function () {
  clearTimeout(timeout);
}

css布局样式

<style>
  /* 首先设置图片box的区域,将图片重叠在一起 */
  header {
    width: 100%;
    position: relative;
    overflow: hidden;
  }
  .box {
    width: 100%;
    height: 300px;
  }
  .box img {
    width: 100%;
    height: 100%;
    position: absolute;
    transform: translateX(0);
    z-index: 1;
  }
  .box img:first-child {
    z-index: 10;
  }
  
  /* 数字序列按钮 */
  .buttons {
    position: absolute;
    right: 10%;
    bottom: 5%;
    display: flex;
    z-index: 100;
  }

  .buttons div {
    width: 30px;
    height: 30px;
    background-color: #aaa;
    border: 1px solid #aaa;
    text-align: center;
    margin: 10px;
    cursor: pointer;
    opacity: .7;
    border-radius: 15px;
    line-height: 30px;
  }

  .buttons div.active {
    background-color: white;
  }

  /* 左右切换按钮 */
  .left,
  .right {
    position: absolute;
    width: 80px;
    height: 80px;
    background-color: #ccc;
    z-index: 100;
    top: 110px;
    border-radius: 40px;
    opacity: .5;
    cursor: pointer;
  }

  .left {
    left: 2%;
  }

  .right {
    right: 2%;
  }

  .left .arrow {
    width: 30px;
    height: 30px;
    border-left: solid 5px #666;
    border-top: solid 5px #666;
    transform: translate(-5px, 25px) rotate(-45deg) translate(25px, 25px);
  }

  .right .arrow {
    width: 30px;
    height: 30px;
    border-left: solid 5px #666;
    border-top: solid 5px #666;
    transform: translate(50px, 25px) rotate(135deg) translate(25px, 25px);
  }
</style>

到此这篇关于原生JS利用transform实现banner的无限滚动示例代码的文章就介绍到这了,更多相关JS banner无限滚动内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript下数值型比较难点说明
Jun 07 Javascript
javascript实现的元素拖动函数宿主为浏览器
Jul 21 Javascript
jQuery统计指定子元素数量的方法
Mar 17 Javascript
Jquery异步提交表单代码分享
Mar 26 Javascript
Javascript实现Array和String互转换的方法
Dec 21 Javascript
XML、HTML、CSS与JS的区别整理
Feb 18 Javascript
jQuery中的一些常见方法小结(推荐)
Jun 13 Javascript
Web打印解决方案之普通报表打印功能
Aug 29 Javascript
详解vue项目构建与实战
Jun 27 Javascript
简单谈谈js的数据类型
Sep 25 Javascript
如何构建 vue-ssr 项目的方法步骤
Aug 04 Javascript
使用这 6个Vue加载动画库来减少我们网站的跳出率
May 18 Vue.js
koa中间件核心(koa-compose)源码解读分析
Jun 15 #Javascript
为react组件库添加typescript类型提示的方法
Jun 15 #Javascript
JavaScript中的全局属性与方法深入解析
Jun 14 #Javascript
Vue使用Three.js加载glTF模型的方法详解
Jun 14 #Javascript
浅谈Vue 自动化部署打包上线
Jun 14 #Javascript
JS定时器如何实现提交成功提示功能
Jun 12 #Javascript
Jquery ajax书写方法代码实例解析
Jun 12 #jQuery
You might like
thinkphp判断访客为手机端或PC端的方法
2014/11/24 PHP
php导入模块文件分享
2015/03/17 PHP
php in_array() 检查数组中是否存在某个值详解
2016/11/23 PHP
laravel 5.4中实现无限级分类的方法示例
2017/07/27 PHP
String.prototype实现的一些javascript函数介绍
2013/11/22 Javascript
js中arguments的用法(实例讲解)
2013/11/30 Javascript
jQuery实现向下滑出的平滑下拉菜单效果
2015/08/21 Javascript
jquery validate.js表单验证入门实例(附源码)
2015/11/10 Javascript
AngularJS ng-mousedown 指令
2016/08/02 Javascript
浅谈JavaScript的自动垃圾收集机制
2016/12/15 Javascript
JS实现在文本指定位置插入内容的简单示例
2017/12/22 Javascript
opencv 识别微信登录验证滑动块位置
2018/08/07 Javascript
[01:42]TI4西雅图DOTA2前线报道 第一顿早饭哦
2014/07/08 DOTA
[04:47]DOTA2-潍坊风行电子俱乐部探秘
2014/08/08 DOTA
Python中的urllib模块使用详解
2015/07/07 Python
Python操作MySQL数据库的三种方法总结
2018/01/30 Python
浅析Python3爬虫登录模拟
2018/02/07 Python
selenium3+python3环境搭建教程图解
2018/12/07 Python
python tkinter canvas 显示图片的示例
2019/06/13 Python
Python之pymysql的使用小结
2019/07/01 Python
matlab中二维插值函数interp2的使用详解
2020/04/22 Python
Python selenium使用autoIT上传附件过程详解
2020/05/26 Python
pandas分批读取大数据集教程
2020/06/06 Python
英国复古和经典球衣网站:Vintage Football Shirts
2018/10/05 全球购物
数据库方面面试题
2012/04/22 面试题
学前教育毕业生自荐信
2013/10/29 职场文书
上课看小说检讨书
2014/02/22 职场文书
学术会议主持词
2014/03/17 职场文书
竞聘书模板
2014/03/31 职场文书
安全技术说明书
2014/05/09 职场文书
甲乙双方合作协议书
2014/10/13 职场文书
2014年便民服务中心工作总结
2014/12/20 职场文书
离婚协议书格式范本
2016/03/18 职场文书
2019年最新证婚词精选集!
2019/06/28 职场文书
Vue组件更新数据v-model不生效的解决
2022/04/02 Vue.js
利用 Python 的 Pandas和 NumPy 库来清理数据
2022/04/13 Python