374 lines
13 KiB
Vue
374 lines
13 KiB
Vue
<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: 40
|
||
},
|
||
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>
|