原生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 相关文章推荐
弹出广告特效(一个IP只弹出一次)的代码
Jul 27 Javascript
jQuery.Autocomplete实现自动完成功能(详解)
Jul 13 Javascript
javascript的数据类型、字面量、变量介绍
May 23 Javascript
Javascript alert消息换行的方法
Aug 07 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
Oct 23 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
Oct 27 Javascript
常常会用到的截取字符串substr()、substring()、slice()方法详解
Dec 16 Javascript
jQuery Validation PlugIn的使用方法详解
Dec 18 Javascript
实例讲解JavaScript中call、apply、bind方法的异同
Sep 13 Javascript
AngularJS集合数据遍历显示的实例
Dec 27 Javascript
深入解读Node.js中的koa源码
Jun 17 Javascript
解决layui的table插件无法多层级获取json数据的问题
Sep 19 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
浅析PHP页面局部刷新功能的实现小结
2013/06/21 PHP
ThinkPHP之import方法实例详解
2014/06/20 PHP
php基于dom实现读取图书xml格式数据的方法
2017/02/03 PHP
yii2实现Ueditor百度编辑器的示例代码
2018/11/02 PHP
详解laravel passport OAuth2.0的4种模式
2019/11/04 PHP
推荐自用 Javascript 缩图函数 (onDOMLoaded)……
2007/10/23 Javascript
热点新闻滚动特效的js代码
2013/08/17 Javascript
JS获取及验证开始结束日期的方法
2016/08/20 Javascript
浅谈JS使用[ ]来访问对象属性
2016/09/21 Javascript
vue2.0嵌套路由实现豆瓣电影分页功能(附demo)
2017/03/13 Javascript
微信小程序 密码输入(源码下载)
2017/06/27 Javascript
使用Vue-Router 2实现路由功能实例详解
2017/11/14 Javascript
JavaScript实现的DOM绘制柱状图效果示例
2018/08/08 Javascript
vue 实现v-for循环回来的数据动态绑定id
2019/11/07 Javascript
JavaScript中的全局属性与方法深入解析
2020/06/14 Javascript
[04:38]完美世界携手游戏风云打造 卡尔工作室饰品系统篇
2013/04/25 DOTA
Python标准异常和异常处理详解
2015/02/02 Python
python实现图片变亮或者变暗的方法
2015/06/01 Python
在Python的Flask框架中构建Web表单的教程
2016/06/04 Python
python获取网页中所有图片并筛选指定分辨率的方法
2018/03/31 Python
使用pycharm生成代码模板的实例
2018/05/23 Python
5分钟 Pipenv 上手指南
2018/12/20 Python
Python实现堡垒机模式下远程命令执行操作示例
2019/05/09 Python
python中如何实现将数据分成训练集与测试集的方法
2019/09/13 Python
Python jieba库用法及实例解析
2019/11/04 Python
使用Django搭建一个基金模拟交易系统教程
2019/11/18 Python
使用sklearn的cross_val_score进行交叉验证实例
2020/02/28 Python
Python如何实现爬取B站视频
2020/05/20 Python
django使用多个数据库的方法实例
2021/03/04 Python
个性发展自我评价
2014/02/11 职场文书
数学教师个人工作总结
2015/02/06 职场文书
2015年教师节主持词
2015/07/03 职场文书
百年校庆感言
2015/08/01 职场文书
学校标语口号大全
2015/12/26 职场文书
关于Javascript闭包与应用的详解
2021/04/22 Javascript
Mysql排序的特性详情
2021/11/01 MySQL