原生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 相关文章推荐
Opacity.js
Jan 22 Javascript
Mootools 1.2 手风琴(Accordion)教程
Sep 15 Javascript
基于jQuery捕获超链接事件进行局部刷新代码
May 10 Javascript
JavaScript获取路径设计源码
May 22 Javascript
JavaScript编写Chrome扩展实现与浏览器的交互及时间通知
May 16 Javascript
js实现文字超出部分用省略号代替实例代码
Sep 01 Javascript
详解如何提高 webpack 构建 Vue 项目的速度
Jul 03 Javascript
Angularjs 事件指令详细整理
Jul 27 Javascript
JS实现利用两个队列表示一个栈的方法
Dec 13 Javascript
简单明了区分escape、encodeURI和encodeURIComponent
May 26 Javascript
详解微信小程序调用支付接口支付
Apr 28 Javascript
解决angular 使用原生拖拽页面卡顿及表单控件输入延迟问题
Apr 21 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
使用 MySQL Date/Time 类型
2008/03/26 PHP
PHP中的类型约束介绍
2015/05/11 PHP
WordPress中调试缩略图的相关PHP函数使用解析
2016/01/07 PHP
PHP+HTML+JavaScript+Css实现简单爬虫开发
2016/03/28 PHP
thinkphp查询,3.X 5.0方法(亲试可行)
2017/06/17 PHP
使用composer命令加载vendor中的第三方类库 的方法
2019/07/09 PHP
PHP cookie与session会话基本用法实例分析
2019/11/18 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
阻止JavaScript事件冒泡传递(cancelBubble 、stopPropagation)
2007/05/08 Javascript
js 匿名调用实现代码
2009/06/19 Javascript
js控制的遮罩层实例介绍
2013/05/29 Javascript
基于js实现投票的实例代码
2015/08/04 Javascript
Javascript 计算字符串在localStorage中所占字节数
2015/10/21 Javascript
Jquery attr()方法 属性赋值和属性获取详解
2016/04/15 Javascript
AngularJS实现用户登录状态判断的方法(Model添加拦截过滤器,路由增加限制)
2016/12/12 Javascript
Node.js操作redis实现添加查询功能
2017/05/25 Javascript
vue.js的手脚架vue-cli项目搭建的步骤
2017/08/30 Javascript
vue中添加mp3音频文件的方法
2018/03/02 Javascript
js变量声明var使用与不使用的区别详解
2019/01/21 Javascript
Vue项目实现简单的权限控制管理功能
2019/07/17 Javascript
uni-app 组件里面获取元素宽高的实现
2019/12/27 Javascript
[02:41]DOTA2英雄基础教程 冥魂大帝
2014/01/16 DOTA
Python+tkinter使用40行代码实现计算器功能
2018/01/30 Python
wxpython实现图书管理系统
2018/03/12 Python
Python3实现的判断环形链表算法示例
2019/03/07 Python
django 消息框架 message使用详解
2019/07/22 Python
基于pytorch 预训练的词向量用法详解
2020/01/06 Python
HTML5 Canvas绘制文本及图片的基础教程
2016/03/14 HTML / CSS
小橄榄树:Le Petit Olivier
2018/04/23 全球购物
介绍一下常见的木马种类
2014/11/15 面试题
什么是符号链接,什么是硬链接?符号链接与硬链接的区别是什么?
2014/01/19 面试题
产假请假条
2014/04/10 职场文书
项目安全员岗位职责
2015/02/15 职场文书
爱心募捐通知范文
2015/04/27 职场文书
银行服务理念口号
2015/12/25 职场文书
使用ORM新增数据在Mysql中的操作步骤
2021/07/26 MySQL