需求:
- 列表为动态,不确定数量;
- 每一个元素不互相遮挡;
结论:
js写又快又简单,但是兼容差,极大可能出现抖动和卡顿;推荐使用对浏览器更加友好的纯css的animation; 小伙伴们根据自己需求去选择哪一种;
方案1:
这也是大多数人使用的方法:在dom生成完毕之后,将父元素复制,插到自己后面;当复制的盒子滚动到容器顶部时,修改元素的scrollTop值;
- 演示:
-
- 优点:1、实现简单,会自己动态计算高度;
-
- 缺点:1、在给scrollTop赋值为0时,会有卡顿的情况, 当.item样式复杂的情况下更为明显;
- 代码:
<template>
<div class="app container" ref="container">
<div class="box" ref="box1" @mouseover="stopRoll" @mouseleave="startRoll">
<div v-for="(item, index) in list" class="item" :style="[{ transform: `translateX(${translateX[index]}px)` }]">{{ item }}</div>
</div>
<div class="box2" ref="box2" @mouseover="stopRoll" @mouseleave="startRoll">
<div v-for="(item, index) in list" class="item" :style="[{ transform: `translateX(${translateX[index]}px)`}]">{{ item }}</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [], //轮播的列表数据
translateX: [], // x位移数组
timer: null
}
},
mounted() {
this.getList()
},
beforeDestroy() {
clearInterval(this.timer)
},
methods: {
getList() {
this.list = ['1王小明', '李晓红', '张小刚', '钱多多', '张大宝', '李华', '孙策', '赵明明', '钱多多', '0周武王'] // 获取列表
for (let i = 0; i < this.list.length; i++) {
this.translateX.push(this.getRandomInteger()) // 记录随机的偏移量
}
this.$nextTick(() => {
this.startRoll()
})
},
startRoll() {
// this.$refs.box2.innerHtml = this.$refs.box1.innerHtml //重复写在dom里面了,不用再js复制了
this.timer = setInterval(() => {
this.rollFunction()
}, 20)// 越小,滚动越快
},
stopRoll() {
clearInterval(this.timer)
},
rollFunction() {
if (this.$refs.container.scrollTop - this.$refs.box1.scrollHeight <= 0) {
this.$refs.container.scrollTop++
} else {
this.$refs.container.scrollTop = 0
}
},
getRandomInteger() {
// 计算范围内的最小值和最大值
const min = 20
const max = 700
// 生成随机数并四舍五入到最近的十位数
const randomTen = Math.round((Math.random() * (max - min) + min) / 10) * 10
return randomTen
}
}
}
</script>
<style lang="scss" scoped>
// 内容高度box1,box2必须大于容器container高度,否则滚动不起来!!!!!!!!!!!!!
.container {
width: 800px;
height: 300px;
border: 1px solid #ccc;
overflow: hidden;
position: relative;
.box1,.box2 {
}
.item {
margin-bottom: 20px;
}
}
</style>
方案2
抛弃js判断高度,采用动画animation,动态设置不同的动画时长,在动画结束时重新开始动画;
演示:
-
- 优点:1、纯css写的,对浏览器非常友好,无卡顿;
-
- 缺点:1、必须最后一个元素动画结束之后,第一个动画才开始,会导致容器有全部空白的时间(不超过1s ,这个是可以解决的,但是我懒,大佬们帮我优化下)
- 代码:
<template>
<div :class="['app', 'container', 'animation-my']" ref="container">
<div class="box" ref="box1" @mouseover="stopRoll" @mouseleave="startRoll">
<!-- 给最后一个item加class;
动态设置动画延迟,实现先后滚动;根据自己项目实际情况设置值 -->
<div v-for="(item, index) in list" :class="['item', { lastItem: index == list.length - 1 }]" :style="[{ left: `${translateX[index]}px` }, { animationDelay: `${index * 1.1}s` }]">
{{ item }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [], //轮播的列表数据
translateX: [], // x位移数组
lastDom: null //最后一个元素
}
},
mounted() {
this.getList()
if (this.lastDom) {
this.lastDom.removeEventListener('animationend', this.setClass)
}
},
methods: {
getList() {
this.list = ['1王小明', '李晓红', '张小刚', '钱多多', '张大宝', '李华', '孙策', '赵明明', '钱多多', '0周武王'] // 获取列表
for (let i = 0; i < this.list.length; i++) {
this.translateX.push(this.getRandomInteger()) // 记录随机的偏移量
}
this.$nextTick(() => {
this.lastDom = document.querySelector('.lastItem')
this.lastDom.addEventListener('animationend', this.setClass)
})
},
startRoll() {
document.querySelector('.container').classList.remove('pause-animation')
},
stopRoll() {
document.querySelector('.container').classList.add('pause-animation')
},
setClass() {
document.querySelector('.container').classList.remove('animation-my')
setTimeout(() => {
document.querySelector('.container').classList.add('animation-my')
}, 1) // 必须这样写,不然之间删除再加不生效
},
getRandomInteger() {
// 计算范围内的最小值和最大值
const min = 20
const max = 700
// 生成随机数并四舍五入到最近的十位数
const randomTen = Math.round((Math.random() * (max - min) + min) / 10) * 10
return randomTen
}
}
}
</script>
<style lang="scss" scoped>
// 内容高度box1,box2必须大于容器container高度,否则滚动不起来!!!!!!!!!!!!!
.container {
width: 800px;
height: 300px;
border: 1px solid #ccc;
overflow: hidden;
position: relative;
.box1,
.box2 {
}
.item {
position: absolute;
bottom: -20px;
cursor: pointer;
animation-timing-function: linear;
animation-duration: 10s;
}
}
// 设置控制动画开始、暂停的外层大类
.animation-my {
.item {
animation-name: moveUp;
}
}
.pause-animation {
.item {
animation-play-state: paused;
}
}
@keyframes moveUp {
0% {
bottom: -20px;
}
100% {
bottom: 300px;
}
}
</style>