a.先搭架子:
* {
margin: 0;
padding: 0;
}
.box {
width: 670px;
height: 300px;
border: 1px solid #000;
margin: 100px auto;
position: relative;
overflow: hidden;
}
.box>ul {
list-style: none;
display: flex;
/* width: 6000px; */
}
.box>img {
width: 670px;
height: 300px;
}
.box>p {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 100%;
display: flex;
justify-content: space-between;
}
.box>p>span {
width: 30px;
height: 60px;
background: rgba(0, 0, 0, .5);
color: #fff;
font-size: 40px;
line-height: 60px;
}
<div class="box">
<ul>
<li>
<img src="images/ad1.jpg" alt="">
</li>
<li>
<img src="images/ad2.jpg" alt="">
</li>
<li>
<img src="images/ad3.jpg" alt="">
</li>
</ul>
<p>
<span class="left"><</span>
<span class="right">></span>
</p>
</div>
引入自己封装的动画函数:
<script src="js/animate.js"></script>
b.设计逻辑:
- 首先,获取需要操作的元素
- 其次,克隆第一张图片然后将其加入到ul里的最后位置以实现无限轮播效果
- 然后,当鼠标点击右边按钮时,图片从右向左移动,在这里需要进行判断:如果是最后一张,就快速返回到第一张;这里我们利用crrentIndex来记录当前的索引
- 再者,当鼠标点击左边的按钮时,图片从左向右运动,在这里需要进行判断:如果是第一张,就快速返回最后一张
- 再然后,利用setInterval实现自动轮播,并且设置当鼠标移入到box盒子里时轮播停止,当鼠标移出到box盒子里时轮播继续
- 最后,为了防止用户疯狂点击按钮,我们需要做节流处理;利用var lock = true;定义节流锁,默认值为true;在点击左右按钮之间先进行判断锁的状态,再执行后面的操作,最后要利用setTimeout来设置延迟
//1.拿到需要操作的元素
const oBox = document.querySelector(".box");
const oLeft = document.querySelector(".left");
const oRight = document.querySelector(".right");
const oUl = document.querySelector("ul");
const oItems = document.querySelectorAll("ul>li");
// const imgWidth = parseFloat(getComputedStyle(oItems[0]).width);
// console.log(imgWidth);//0
// 克隆第一张图片然后将其加入到ul里
const cloneli = oUl.firstElementChild.cloneNode(true);
oUl.appendChild(cloneli);
let crruentIndex = 0; //记录当前索引
// 定义节流锁
var lock = true;
//2.监听按钮点击
oRight.onclick = function() {
//判断锁的状态
if (!lock) return;
lock = true;
crruentIndex++;
//如果是最后一张,就返回第一张
if (crruentIndex > oItems.length - 1) {
crruentIndex = 0;
//快速跳转到第一张
oUl.style.marginLeft = -crruentIndex * 670 + 'px';
crruentIndex++;
}
// oUl.style.marginLeft = -crruentIndex * imgWidth + 'px';
linearAnimation(oUl, -crruentIndex * 670);
// 函数节流
setTimeout(function() {
lock = true;
}, 500);
};
oLeft.onclick = function() {
if (!lock) return;
lock = false;
crruentIndex--;
//如果是第一张,就返回最后一张
if (crruentIndex < 0) {
crruentIndex = oItems.length - 1;
//快速跳转到最后一张
oUl.style.marginLeft = -crruentIndex * 670 + 'px';
crruentIndex--;
}
// oUl.style.marginLeft = -crruentIndex * imgWidth + 'px';
linearAnimation(oUl, -crruentIndex * 670);
// 函数节流
setTimeout(function() {
lock = true;
}, 500);
};
//3.自动轮播
let timer1 = setInterval(function() {
oRight.onclick();
}, 2000);
//3.1鼠标移入时停止轮播
oBox.onmouseenter = function() {
//关闭定时器
clearInterval(timer1);
};
//3.2鼠标移出时轮播继续
oBox.onmouseleave = function() {
//重新开启定时器
timer1 = setInterval(function() {
oRight.onclick();
}, 2000);
};
animate.js
(function() {
let timer = null;
//匀速动画
function linearAnimation(ele, target) {
clearInterval(timer);
timer = setInterval(function() {
// 1.拿到元素当前的位置
let begin = parseInt(ele.style.marginLeft) || 0;
// 2.定义变量记录步长
let step = (begin - target) > 0 ? -13 : 13;
// 3.计算新的位置
begin += step;
// console.log(Math.abs(target - begin), Math.abs(step));
if (Math.abs(target - begin) <= Math.abs(step)) {
clearInterval(timer);
begin = target;
}
// 4.重新设置元素的位置
ele.style.marginLeft = begin + "px";
}, 30);
}
//缓动动画
function easeAnimation(ele, target) {
clearInterval(timer);
timerId = setInterval(function() {
// 1.拿到元素当前的位置
let begin = parseInt(ele.style.marginLeft) || 0;
// 2.定义变量记录步长
// 公式: (结束位置 - 开始位置) * 缓动系数(0 ~1)
let step = (target - begin) * 0.3;
// console.log(step);
// 3.计算新的位置
begin += step;
if (Math.abs(Math.floor(step)) <= 1) {
clearInterval(timer);
begin = target;
}
// 4.重新设置元素的位置
ele.style.marginLeft = begin + "px";
}, 100);
}
// 将函数绑定到window对象上, 这样全局就可以使用了
window.linearAnimation = linearAnimation;
window.easeAnimation = easeAnimation;
})();