原生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 相关文章推荐
js获取元素在浏览器中的绝对位置
Jul 24 Javascript
Javascript实现仿WebQQ界面的“浮云”兼容 IE7以上版本及FF
Apr 27 Javascript
基于jQuery仿淘宝产品图片放大镜特效
Oct 19 Javascript
常用的JQuery函数及功能小结
Mar 24 Javascript
jQuery实现的动态文字变化输出效果示例【附演示与demo源码下载】
Mar 24 jQuery
JavaScript数组,JSON对象实现动态添加、修改、删除功能示例
May 26 Javascript
layui自定义工具栏的方法
Sep 19 Javascript
基于PHP pthreads实现多线程代码实例
Jun 24 Javascript
通过实例解析JavaScript常用排序算法
Sep 02 Javascript
vue el-upload上传文件的示例代码
Dec 21 Vue.js
jQuery实现本地存储
Dec 22 jQuery
学习 Vue.js 遇到的那些坑
Feb 02 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
几款免费开源的不用数据库的php的cms
2010/12/19 PHP
php中unlink()、mkdir()、rmdir()等方法的使用介绍
2012/12/21 PHP
PHP批量查询WordPress留言者E-mail地址实现方法
2015/02/15 PHP
jquery实现图片灯箱明暗的遮罩效果
2013/11/15 Javascript
JQuery弹出层示例可自定义
2014/05/19 Javascript
基于JavaScript代码实现兼容各浏览器的设为首页和加入收藏
2016/01/07 Javascript
JS实现css hover操作的方法示例
2017/04/07 Javascript
nodejs入门教程五:连接数据库的方法分析
2017/04/24 NodeJs
用纯Node.JS弹出Windows系统消息提示框实例(MessageBox)
2017/05/17 Javascript
微信小程序通过保存图片分享到朋友圈功能
2018/05/24 Javascript
JavaScript 中的12种循环遍历方法【总结】
2018/05/31 Javascript
零基础之Node.js搭建API服务器的详解
2019/03/08 Javascript
Jquery动态列功能完整实例
2019/08/30 jQuery
vue列表数据发生变化指令没有更新问题及解决方法
2020/01/16 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
[39:00]Optic vs VP 2018国际邀请赛淘汰赛BO3 第三场 8.24
2018/08/25 DOTA
使用scrapy实现爬网站例子和实现网络爬虫(蜘蛛)的步骤
2014/01/23 Python
Python中利用Scipy包的SIFT方法进行图片识别的实例教程
2016/06/03 Python
利用django-suit模板添加自定义的菜单、页面及设置访问权限
2018/07/13 Python
Django自带的加密算法及加密模块详解
2019/12/03 Python
matlab、python中矩阵的互相导入导出方式
2020/06/01 Python
如何用Matlab和Python读取Netcdf文件
2021/02/19 Python
北美个性化礼品商店:Things Remembered
2018/06/12 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
什么是动态端口(Dynamic Ports)?动态端口的范围是多少?
2014/12/12 面试题
内科护士实习自我鉴定
2013/10/17 职场文书
大学四年职业生涯规划书范文
2014/01/02 职场文书
《沙漠中的绿洲》教学反思
2014/04/24 职场文书
销售求职信范文
2014/05/26 职场文书
大学生学雷锋活动总结
2014/06/26 职场文书
运动会广播稿诗歌版
2014/09/12 职场文书
会议欢迎词
2015/01/23 职场文书
学校工会工作总结2015
2015/05/19 职场文书
2015年乡镇纪委工作总结
2015/05/26 职场文书
Mac环境Nginx配置和访问本地静态资源的实现
2021/03/31 Servers
Redis超详细讲解高可用主从复制基础与哨兵模式方案
2022/04/07 Redis