实现效果

初级方法:
实现原理:
注意事项:由于需要循环滚动,可以把获取到的数组在复制一份放到列表里,做到无缝衔接
html:
<div class="inner_box">
<div class="prize_container">
<ul
ref="prizeRef"
class="prize_ul"
v-if="info.joinList && info.joinList.length"
>
<li
class="prize_item"
v-for="(item, index) in info.joinList"
:key="index"
>
<div class="left">{{ item.mobile | mobileFilter }}</div>
<div class="right">{{ item.name }}</div>
</li>
</ul>
</div>
</div>
js:
// 获取活动信息
getData() {
this.fetch
.get("TjModule/GetActivityInfo", {
activityId: this.id
})
.then(res => {
if (res.data && res.data.success) {
this.$setTitle(res.data.result.activityName);
this.info = res.data.result;
let arr = [];
if (res.data.result.joinList.length) {
arr = res.data.result.joinList;
arr.map(i => {
arr.push(i);
});
}
this.info.joinList = arr;
console.log(this.info.joinList);
this.$nextTick(() => {
this.changeAnimation(this.info.joinList.length);
});
}
})
.catch(error => {
if (error.response && error.response.status === 500) {
this.$toast(error.response.data.error.message);
}
});
},
// 编写动画
changeAnimation(d) {
console.log(9090);
let total = 25.5 * d/2
let every = 0
const dm = this.$refs.prizeRef;
this.timers = setInterval(()=>{
every += 5
if(every < total){
dm.style.top = - every + ‘px‘
}else{
dm.style.top = 0
every = 0
}
},120)
},
// 关闭定时器
css:
.prize_container { overflow: hidden; position: absolute; height: 90%; width: 100%; padding: 30px 0; } .prize_ul { width: 100%; color: #fff; position: absolute; padding: 0px 80px; // animation: opacityShow linear 5s infinite; .prize_item { width: 100%; display: flex; justify-content: space-between; margin-bottom: 12px; } }
在changeAnimation函数中, let total = 25.5 * d/2 这个25.5是每行的高度,通过 every(移动距离) 与 total(总高度) 比较,实现循环
缺点:
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行animate() {
requestAnimationFrame(this.animate);
this.changeAnimation();
},
html:
<div class="prize_container">
<div class="prize_list" :style="{ transform: ‘translateY( -‘+ ulLeft + ‘px)‘ }" >
<ul
ref="prizeUl"
class="prize_ul"
v-if="info.joinList && info.joinList.length" >
<li
class="prize_item"
v-for="(item, index) in info.joinList"
:key="index"
>
<div class="left">{{ item.mobile | mobileFilter }}</div>
<div class="right">{{ item.name }}</div>
</li>
</ul>
<ul
class="prize_ul"
v-if="info.joinList && info.joinList.length" >
<li
class="prize_item"
v-for="(item, index) in info.joinList"
:key="index"
>
<div class="left">{{ item.mobile | mobileFilter }}</div>
<div class="right">{{ item.name }}</div>
</li>
</ul>
</div>
</div>
这里使用复制两个ul元素,不在js中操作复制列表
js:
data(){ prizeUlHeight:0, //滚动ref高度 $prizeUl:null, //滚动的ref ulLeft:0, //移动参数 }
methods:{ // 获取活动信息 getData() { this.fetch .get("TjModule/GetActivityInfo", { activityId: this.id }) .then(res => { if (res.data && res.data.success) { this.$setTitle(res.data.result.activityName); this.info = res.data.result; this.$nextTick(() => { this.$prizeUl = this.$refs.prizeUl; this.prizeUlHeight = this.$prizeUl.clientHeight; this.times = requestAnimationFrame(this.animate); }); } }) .catch(error => { if (error.response && error.response.status === 500) { this.$toast(error.response.data.error.message); } }); }, animate() { requestAnimationFrame(this.animate); this.changeAnimation(); }, // 编写动画 changeAnimation(d) { if( this.ulLeft == this.prizeUlHeight ){ this.ulLeft = 0; }else{ this.ulLeft += 1; } }, }
css:
.prize_container { overflow: hidden; position: absolute; height: 90%; width: 100%; } .prize_ul { width: 100%; color: #fff; // position: absolute; padding: 0px 80px; .prize_item { width: 100%; display: flex; line-height: 58px; justify-content: space-between; } }
这样就完美解决了循环滚动动画,
使用帧动画还有一个优点:
每次切换页面的时候,帧动画会暂停执行,直到切换回该页面,才会继续执行动画,这样就比定时器更加保护性能
其实还有一个方案:
用css + js
// 写动画 @keyframes opacityShow { from { transform: translateY(0); } to { transform: translateY(-50%); } }
使用
原文:https://www.cnblogs.com/huangaiya/p/12668345.html