原生JS利用transform实现banner的无限滚动

功能

image.png

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

原理

首先说下原理。

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

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

动画的实现

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

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

html代码

<header>

<div class="box">

<img>

<img>

<img>

<img>

</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的无限滚动 的全部内容, 来源链接: utcz.com/a/24832.html

回到顶部