1 需求
效果就是下面这样,就是一次滚出一个元素,无限循环,可以使用死数据,也可以追加,当然具体动画你可以修改代码。
效果
思路
使用css做过渡动画,用js控制滚动(其实也可以只用css)。
* {
padding: 0;
margin: 0;
list-style: none;
}
#ul {
position: relative;
top: 0px;
left: 0px;
}
li {
width: 200px;
height: 100px;
margin: 10px;
background-color: #f00;
color: #fff;
text-align: center;
font-size: 60px;
transition: all 0.3s ease-out;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
html结构的大概意思就是,最外层的div限制可视区域,使用js移动ul达到滚动的效果
主要的代码如下
const ul = document.getElementById('ul')
const firstLi = document.querySelector('#ul li:first-child')
setInterval(() => {
const firstLi = document.querySelector('#ul li:first-child')
ul.style.transition = 'all 0.5s ease-out'
firstLi.style.opacity = 0
ul.style.top = -110 + 'px'
setTimeout(() => {
firstLi.removeAttribute('style')
ul.appendChild(firstLi)
ul.style.transition = ''
ul.style.top = 0
}, 500)
}, 2000)
这里有几个地方要注意
首先每两秒滚动一次,每次滚动的距离-110px,这个距离就是每个li加上它margin。
在ul滚动完成后我们需要移除第一个li,把它加入到ul的最后,但是这里会有一个问题,如果在ul.style.top = -110 + 'px'之后直接ul.appendChild(firstLi),会导致第一个元素消失后,第二个元素就会顶上去,实际在页面上看到的不是预期的第二个元素而是第三个元素。所以这里在移除第一个元素之后,马上将ul的位置重置为0
可以看到在append的时候我使用了一个500毫秒的定时器,这里是因为我的过渡动画用的是css,没办法知道他什么时候结束(除非使用animation可以事件监听),所以使用了一个大于之前设定的过渡动画时间的定时器,在动画完成后再移除第一个元素
3. 总体代码如下
Document* {
padding: 0;
margin: 0;
list-style: none;
}
#ul {
position: relative;
top: 0px;
left: 0px;
}
li {
width: 200px;
height: 100px;
margin: 10px;
background-color: #f00;
color: #fff;
text-align: center;
font-size: 60px;
transition: all 0.3s ease-out;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
走起来
复位
const ul = document.getElementById('ul')
const start = document.getElementById('start')
const reset = document.getElementById('reset')
let timerId
start.onclick = () => {
if(timerId) return
timerId = setInterval(() => {
const firstLi = document.querySelector('#ul li:first-child')
ul.style.transition = 'all 0.5s ease-out'
firstLi.style.opacity = 0
ul.style.top = -110 + 'px'
setTimeout(() => {
firstLi.removeAttribute('style')
// 模拟随机添加数据
// const count = Math.random() * 10
// for(let i = count; i >0; i--) {
// ul.appendChild(firstLi.cloneNode(true))
// }
ul.appendChild(firstLi)
ul.style.transition = ''
ul.style.top = 0
}, 500)
}, 2000)
}
reset.onclick = () => {
clearInterval(timerId)
timerId = undefined
location.reload()
}