原生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 相关文章推荐
表单提交验证类
Jul 14 Javascript
jQuery 学习第六课 实现一个Ajax的TreeView
May 17 Javascript
MooTools 页面滚动浮动层智能定位实现代码
Aug 23 Javascript
javascript权威指南 学习笔记之变量作用域分享
Sep 28 Javascript
javascript时间自动刷新实现原理与步骤
Jan 06 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
Dec 14 Javascript
利用Three.js如何实现阴影效果实例代码
Sep 26 Javascript
基于vue-element组件实现音乐播放器功能
May 06 Javascript
不得不知的ES6小技巧
Jul 28 Javascript
AngularJS上传文件的示例代码
Nov 10 Javascript
详解JavaScript栈内存与堆内存
Apr 04 Javascript
JavaScript实现图片放大预览效果
Nov 02 Javascript
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
MVC模式的PHP实现
2006/10/09 PHP
PHP获取url的函数代码
2011/08/02 PHP
php数组一对一替换实现代码
2012/08/31 PHP
深入解析php之apc
2013/05/15 PHP
JavaScript 函数调用规则
2009/09/14 Javascript
JQuery优缺点分析说明
2010/06/09 Javascript
JavaScript中的细节分析
2012/06/30 Javascript
js实现键盘操作实现div的移动或改变的原理及代码
2014/06/23 Javascript
node.js+Ajax实现获取HTTP服务器返回数据
2014/11/26 Javascript
jQuery菜单插件superfish使用指南
2015/04/21 Javascript
jQuery中$(function() {});问题详解
2015/08/10 Javascript
javascript中alert()与console.log()的区别
2015/08/26 Javascript
Vuex 入门教程
2018/01/10 Javascript
微信小程序自定义音乐进度条的实例代码
2018/08/28 Javascript
JavaScript 判断iPhone X Series机型的方法
2019/01/28 Javascript
Vue递归组件+Vuex开发树形组件Tree--递归组件的简单实现
2019/04/01 Javascript
用webpack4开发小程序的实现方法
2019/06/04 Javascript
在JavaScript中如何访问暂未存在的嵌套对象
2019/06/18 Javascript
ES6 Symbol在对象中的作用实例分析
2020/06/06 Javascript
js实现限定范围拖拽的示例
2020/10/26 Javascript
python多线程抓取天涯帖子内容示例
2014/04/03 Python
Python多线程编程简单介绍
2015/04/13 Python
Python中几个比较常见的名词解释
2015/07/04 Python
Python的Django框架安装全攻略
2015/07/15 Python
在arcgis使用python脚本进行字段计算时是如何解决中文问题的
2015/10/18 Python
Python网络编程 Python套接字编程
2017/09/13 Python
python利用urllib和urllib2访问http的GET/POST详解
2017/09/27 Python
python3反转字符串的3种方法(小结)
2019/11/07 Python
Python内置函数locals和globals对比
2020/04/28 Python
CSS3+HTML5+JS 实现一个块的收缩与展开动画效果
2020/11/17 HTML / CSS
俄罗斯在线手表和珠宝商店:AllTime
2019/09/28 全球购物
财务会计专业毕业生自荐信
2013/10/02 职场文书
会计岗位职责
2013/11/08 职场文书
经济管理专业求职信
2014/06/09 职场文书
vue使用v-model进行跨组件绑定的基本实现方法
2021/04/28 Vue.js
mysql的单列多值存储实例详解
2022/04/05 MySQL