实现效果
初级方法:
实现原理:
注意事项:由于需要循环滚动,可以把获取到的数组在复制一份放到列表里,做到无缝衔接
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