<template> <view> <view class="contentBox" v-if="list.length" @click="toEmit()" :style="'color:' + color + ';background-color:' + backgroundColor + ';height:' + height+'rpx;'"> <view v-if="showIcon" class="supBox"> <lwIcon :size="32" :color="iconColor" icon="sound"></lwIcon> </view> <view v-if="list.length > 1" class="content"> <view v-for="(item, index) in list" :key="index" @tap.stop="dangGao(index)"> <view class="loopItemBase" :class="index==0&&firstIn?'fistInClass':''" :animation="realAnimation(index)" v-if="aindexArr.includes(index)" :style="'line-height:'+height+'rpx;'"> {{ item }} </view> </view> </view> <view v-if="list.length == 1" class="content"> <view :style="'line-height:'+height+'rpx;'" @tap.stop="dangGao(0)" class="loopItemBaseShow">{{ list[0] }}</view> </view> <view v-if="showMore" class="offBox"> <lwIcon :size="32" :color="moreColor" icon="arrowright"></lwIcon> </view> </view> </view> </template> <script> /* lw-notice公告上下轮询组件(组件内依赖了自有的字体图标组件,可自行替换为uni或自身项目的图标组件) color:字体颜色 backgroundColor:背景色 list:要循环的列表数据 height:组件高度 showScale:是否有缩放动画 runTime:间隔切换时间 showIcon:是否显示头部小喇叭 iconColor:小喇叭的颜色 showMore:是否显示尾部更多 moreColor:显示更多的颜色 */ import lwIcon from './iconFont.vue' export default { components: { lwIcon }, props: { color: { type: String, default: '#666666' }, backgroundColor: { type: String, default: '#f5f5f5' }, list: { type: Array, default: function(){ return [] } }, height: { type: Number, default: 80 }, showScale: { type: Boolean, default: false }, runTime: { type: Number, default: 4000 }, showIcon: { type: Boolean, default: false }, showMore: { type: Boolean, default: false }, iconColor: { type: String, default: '#aaaaaa' }, moreColor: { type: String, default: '#aaaaaa' } }, data() { return { // 第一次展示 firstIn: true, // 当前显示的项 aindexArr: [], // 创建动画的实例 animation: null, // 动画对象一 animationData: null, // 动画对象二 animationDataTwo: null, // 显示项和动画之间的映射关系 indexLinkAnimationObj: {}, setTimerOne: null, setTimerTwo: null, setTimerThree: null, setTimerFour: null, setTimerFive: null }; }, beforeDestroy() { this.resetPage() }, computed: { // 计算展示项应该展示的动画 realAnimation() { return function(value) { if (this.indexLinkAnimationObj[value]) { return this[this.indexLinkAnimationObj[value]] } else { return {} } } } }, methods: { // 开始 按3000毫秒的运行示例图 // 1.a显示 执行动画1 锁定动画1 0ms // 2.b显示 执行动画2 锁定动画2 200ms // 3.a隐藏 停止动画1 释放动画1 300ms // 4.c显示 执行动画1 锁定动画1 400ms // 5.b隐藏 停止动画2 释放动画2 500ms // 6.a显示 执行动画2 锁定动画2 600ms // 7.c隐藏 停止动画1 释放动画1 700ms // 8.b显示 执行动画1 锁定动画1 800ms // 9.a隐藏 停止动画2 释放动画2 900ms // 10.c显示 执行动画2 锁定动画2 1000ms initPage() { this.resetPage(); if (this.list && this.list.length) { if (this.list.length > 1) { this.aindexArr.push(0); this.animation = uni.createAnimation({ timingFunction: 'linear', }) // #ifdef H5 this.animationDataH5 = this.animation.translateY(-100).step({ duration: 10000 }).export() // #endif this.runAnimation(0, true); } } }, // 重置页面动画 resetPage() { // 移除所有定时器 clearTimeout(this.setTimerOne); clearTimeout(this.setTimerTwo); clearTimeout(this.setTimerThree); clearTimeout(this.setTimerFour); clearTimeout(this.setTimerFive); // 重置页面属性 this.aindexArr = []; this.animation = null; this.animationData = null; this.animationDataTwo = null; this.indexLinkAnimationObj = {}; }, // 执行动画方法(此方法内不要清除赋值的定时器) runAnimation(value, firstIn) { let that = this; if (!firstIn) { that.aindexArr.push(value); } // 获取执行动画对象 let lockText = that.createAni(firstIn); // 延迟50毫秒执行(等待dom渲染) that.setTimerOne = setTimeout(() => { // 创建执行动画和执行方之间的映射关系 that.indexLinkAnimationObj[value] = lockText; // console.log('已经创建完成绑定关系') // console.log(that.indexLinkAnimationObj) // 获取基础执行时间单位 let unitRunTime = (that.runTime - 50) / 6; let waitTime = firstIn ? unitRunTime * 4 : unitRunTime * 5; let waitTimeTwo = firstIn ? (that.runTime - unitRunTime) : that.runTime; // #ifdef H5 waitTimeTwo = firstIn ? (that.runTime - (1.5 * unitRunTime)) : that.runTime; //H5重新刷新一下动画绑定关系 if (firstIn) { that.aindexArr.splice(0, 1); that.aindexArr.push(0); } // #endif // 开启下一个动画 that.setTimerTwo = setTimeout(() => { let Index = value == that.list.length - 1 ? 0 : value + 1; that.runAnimation(Index) }, waitTime) // 释放上一个执行方 that.setTimerThree = setTimeout(() => { let index = that.aindexArr.indexOf(value); that.aindexArr.splice(index, 1) that.firstIn = false; delete that.indexLinkAnimationObj[value] }, waitTimeTwo) }, 50) }, // 创建动画方法 createAni(firstIn) { let that = this; let unitRunTime = (that.runTime - 50) / 6; let delayTime = unitRunTime * 4; let durationTime = unitRunTime; let dispairTime = unitRunTime; // #ifdef H5 delayTime = unitRunTime * 3.5; dispairTime = unitRunTime * 1.5; // #endif let showTransformHeight = -uni.upx2px(that.height); let hideTransformHeight = showTransformHeight * 2; // 创建动画 if (that.showScale) { if (firstIn) { // that.animation.translateY(1).scale(1,1).step({ duration: 5 }); that.animation.translateY(showTransformHeight).scale(0.5, 0.5).step({ delay: delayTime, duration: dispairTime }); } else { that.animation.translateY(showTransformHeight).scale(1, 1).step({ duration: durationTime }); that.animation.translateY(hideTransformHeight).scale(0.5, 0.5).step({ delay: delayTime, duration: dispairTime }); } } else { if (firstIn) { // that.animation.translateY(1).step({ duration: 5 }); that.animation.translateY(showTransformHeight).step({ delay: delayTime, duration: dispairTime }); } else { that.animation.translateY(showTransformHeight).step({ duration: durationTime }); that.animation.translateY(hideTransformHeight).step({ delay: delayTime, duration: dispairTime }); } } // 判断动画赋值项并赋值 if (!that.animationData) { that.animationData = that.animation.export() that.setTimerFour = setTimeout(() => { clearTimeout(that.setTimerFour) that.animationData = false; }, that.runTime) return 'animationData' } else { that.animationDataTwo = that.animation.export() that.setTimerFive = setTimeout(() => { clearTimeout(that.setTimerFive) that.animationDataTwo = false; }, that.runTime) return 'animationDataTwo' } }, // 抛出点击事件 toEmit() { let that = this if (that.list.length == 1) { that.$emit('itemClick', that.list[0]) } else { that.$emit('itemClick', that.list[that.aindexArr[0]]) } }, dangGao(index){ let that = this if (that.list.length != 0) { that.$emit('dangGao', index) } } }, created() { }, mounted() { // 判断list有值后开启动画 // setTimeout() this.initPage() }, watch: { list(value) { this.initPage() } } }; </script> <style lang="scss" scoped> .contentBox { width: 100%; display: flex; // padding: 0 20rpx; align-items: center; box-sizing: border-box; font-size: 24rpx; .supBox { width: 50rpx; display: flex; justify-content: flex-start; } .offBox { width: 50rpx; display: flex; justify-content: flex-end; } .content { width: 100%; flex-grow: 1; height: 100%; display: flex; overflow: hidden; position: relative; align-items: center; box-sizing: border-box; justify-content: center; .loopItemBase { left: 0; top: 100%; width: 100%; height: 100%; overflow: hidden; font-size: 28rpx; text-align: left; position: absolute; white-space: nowrap; align-items: center; text-overflow: ellipsis; &.fistInClass { top: 0; } } .loopItemBaseShow { top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; font-size: 28rpx; text-align: left; position: absolute; white-space: nowrap; align-items: center; text-overflow: ellipsis; } } } </style>