参考文档一:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/108
参考文档二:https://blog.csdn.net/vhwfr2u02q/article/details/79492303
如果需要用css实现无缝轮播,请点传送门
requestAnimationFrame方法的作用为在屏幕刷新每一帧时执行一次回调函数,用requestAnimationFrame实现即表示轮播效果是js实现,接下来上效果图:
下面给出示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
.view-box{width: 200px; height: 200px; overflow: hidden;}
.container{width: 1000px; position: relative; padding: 0; font-size: 0;}
.item{width: 200px; height: 200px; display: inline-block;}
.item1{background-color: red;}
.item2{background-color: blue;}
.item3{background-color: yellow;}
.item4{background-color: green;}
</style>
<body>
<div class="view-box">
<ul class="container">
<li class="item item1"></li>
<li class="item item2"></li>
<li class="item item3"></li>
<li class="item item4"></li>
<li class="item item1"></li>
</ul>
</div>
<input type="button" onclick="start()" value="启动">
<input type="button" onclick="stop()" value="停止">
</body>
<script>
let slicing = () => {
//requestAnimationFrame方法的作用为在屏幕刷新每一帧时执行一次回调函数
const requestAnimationFrame =
window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame
const cancelAnimationFrame =
window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame
//scrollNode为需要执行轮播动作的容器
const scrollNode = document.getElementsByClassName("container")[0]
//单个轮播元素宽度
const itemWidth = 200
//distance为轮播时容器的最大偏移距离(通常为容器的宽度减去第一个轮播元素的宽度)
const distance = scrollNode.clientWidth - itemWidth
//由于容器的定位为相对定位,则可以通过修改style的left来达到移动效果
scrollNode.style.left = scrollNode.style.left || 0
//容器的偏移距离保存在window对象的__offset属性中
window.__offset = window.__offset || 0
/**
* requestId:为requestAnimationFrame执行的返回值,用于停止动画(和setInterval的返回值功能类似)
* sliceStatus:轮播状态(start为启动,stop为停止)
* wait:轮播暂停已等待帧数
* waitMax:轮播暂停最大等待帧数
*/
let requestId = null, sliceStatus = "start", wait = 0, waitMax = 60
//每一帧执行的回调函数
const scrollLeft = () => {
if (window.__offset % itemWidth === 0 && wait < waitMax) {
wait++;
}
else {
if (window.__offset % itemWidth === 0 && wait === waitMax) {
wait = 0;
}
//轮播速度
const speed = 2
//刷新容器偏移距离
window.__offset = window.__offset + speed
//设置容器偏移距离
scrollNode.style.left = -window.__offset + 'px'
}
/**
* 当容器偏移距离达到最大偏移距离时,重置容器偏移距离,继续从头开始移动
* 由于最后一个轮播元素是第一个轮播元素的复制,所以看起来就是无缝轮播的效果
*/
if (distance <= window.__offset) window.__offset = 0
//通过递归的方式循环调用
requestId = requestAnimationFrame(scrollLeft)
}
requestId = requestAnimationFrame(scrollLeft)
return (status) => {
if (sliceStatus === status) return
status === "start" ? requestId =
requestAnimationFrame(scrollLeft) : cancelAnimationFrame(requestId)
sliceStatus = status
}
}
let slice = null
let start = () => slice === null ? slice = slicing() : slice("start")
let stop = () => slice("stop")
</script>
</html>