原理
定位
在相对定位的容器中使用绝对定位来确保需要循环移动的元素的起始位置,确定容器宽度,超出部分隐藏。
移动
使用transform操作每一个item进行平移
移动距离
为了使移动变得平滑我这里设置每次移动的距离moveLength为1。
移动时间
这里设置了一个定时器,每10ms执行一次,也就是每10ms所有的item向左移动1px
实现思路
设定一个maxLength随着moveLength一起自增,当maxLength等于distance(item的宽度+间隔)时将第一个item移到最后的位置,这里涉及到几个问题:
- 将第一个item移到最后需要移动的距离
- 如何确定当前哪个是第一个item
对于第一个问题,可以先列出计算公式
第一个item需要移动的距离就是list的宽度+一个item的宽度:
(distance)(item个数)+(distance)
第二个item需要移动的距离是在第一个移动的基础上再加一个item+间隔的距离:
(distance)(item个数)+distance2
…
第itemNum个item需要移动的距离:
(distance)(item个数)+(distance)itemNum
这样我们就得出一个移动的公式,但还有一个问题是第一轮可以这么移,第二轮以及后面的怎么办?先想象一下第二轮其实就是两个完整的list宽度+item的宽度itemNum,以此类推第currentTurn轮其实就是,**currentTurn*(distance)*(item个数)+(distance)*itemNum = distance*[currentTurn*item个数+itemNum]**
。到这里我们就得到了一个完整的通项公式
对于第二个问题,需要一个参数itemNum,来记录当前准备操作的item。每当maxLength==distance时对应的currentTurn也要+1并对总数取余。
至此,我们就完成了整个列表移动的理论部分,现在开始编写代码。
实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>循环列表</title>
</head>
<body>
<div class="prize-list" id="prizeList">
<div class="item">
<div class="item-text">1</div>
</div>
<div class="item" style="left: 120px;">
<div class="item-text">2</div>
</div>
<div class="item" style="left: 240px;">
<div class="item-text">3</div>
</div>
<div class="item" style="left: 360px;">
<div class="item-text">4</div>
</div>
<div class="item" style="left: 480px;">
<div class="item-text">5</div>
</div>
</div>
<script>
let moveLength = 0;
let maxLength = -150;
const distance = 120
const turnTime = 10;
let totalTurn = 1
let currentIndex = 0;
moveItems()
function moveItems() {
const items = document.querySelectorAll('.item');
const totalItems = items.length;
console.log(totalItems)
moveInterval = setInterval(() => {
moveLength++;
maxLength++;
if (maxLength >= distance) {
items[currentIndex].style.left = distance * (items.length * totalTurn + currentIndex) + 'px'
if (currentIndex == totalItems - 1) {
totalTurn++
}
currentIndex = (currentIndex + 1) % totalItems;
maxLength = 0;
} else {
items.forEach(item => {
item.style.transform = `translateX(-${moveLength}px)`;
});
}
}, turnTime);
}
</script>
<style>
.prize-list {
display: flex;
width: 90%;
position: relative;
overflow: hidden;
height: 5.5rem;
margin-top: 1rem;
margin-left: 1rem;
}
.item {
position: absolute;
bottom: 0rem;
z-index: 9;
transition: transform 1s ease;
}
.item-text {
width: 50px;
height: 50px;
background-color: black;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</body>
</html>