By Noxxxx from https://www.noxxxx.com/?post_type=post&p=1281
欢迎分享与聚合,尊重版权,可以联系授权
这个单行轮播是在之前多行轮播的基础上迭代的,本质上二者的思路都相同的,解决了核心重复轮播的算法后,剩下的就是样式的调整。
以前会用重复 dom 的方式来实现轮播,后来受到一个轮播插件的方案的启发,首先我们补齐 dom 的方式本质上还是在补齐需要重复的数据,所以在 Vue 中我们可以先根据你的轮播方式,
- 计算出需要追加的重复元素
- 计算出重复元素开始在可视区域后(即第一轮的数据展示的位置和当前重复元素的展示位置一致时)通过 css 将 dom 的位置「闪现」复位
在没有过渡动画的加持下,元素的位移肉眼无法察觉,所以我们又可以开始新一轮的轮播。
<template>
<div
class="scroll-container"
:style="{height: `${height/100}rem`}"
>
<ul
v-for="(item, index) in list"
:key="index"
class="scroll-ul"
:style="{transform: `translate3d(0, ${y/100}rem, 0)`, transition: `${transition}`}"
>
<li
class="c-item"
>
<img
v-if="item.content"
class="a-item"
:src="item.avatar"
>
<div
v-if="item.content"
class="c-content"
v-html="item.content"
/>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'broad-cast',
props: {
list: {
type: Array,
default: function () {
return []
}
}
},
data () {
return {
height: 0, // 单项高度
y: 0, // 每次移动距离
originLength: 0, // 原始数组长度
transition: 'ease all .4s',
number: 1, // 默认一次滚动一条
interval: null
}
},
mounted () {
this.init()
this.scroll()
},
methods: {
init () {
if (!this.list.length) return
this.originLength = this.list.length
const mod = this.originLength % this.number
let need = this.originLength < this.number ? (this.number - this.originLength + this.number) : mod === 0 ? (this.number + 1) : (this.number - mod + this.number)
// 按次序从头开始补齐
let index = 0
for (let i = 0; i < need; i++) {
if (this.list[i]) {
index = i
} else {
index = 0
}
const tmp = JSON.parse(JSON.stringify(this.list[index]))
index++
this.list.push(tmp)
}
},
scroll () {
if (!this.list.length) return
// 计算可视区域高度
this.height = 64 * this.number + (12 * (this.number - 1))
let count = 0
this.y = 0
clearInterval(this.interval)
this.interval = setInterval(() => {
count++
this.y -= (64 + 12)
this.transition = '.4s ease all'
setTimeout(() => {
if (count === (this.originLength)) {
count = 0
this.transition = ''
this.y = 0
}
}, 800)
}, 2000)
}
}
}
</script>
<style scoped lang="scss">
.scroll-container {
overflow: hidden;
}
.c-item {
display: flex;
align-items: center;
height: .64rem;
box-sizing: border-box;
margin-bottom: .12rem;
color: #223875;
}
.c-content {
max-width: 4.4rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.a-item {
border-radius: 50%;
overflow: hidden;
width: .42rem;
height: .42rem;
margin-right: .14rem;
}
</style>