<template>
<view
v-if="show"
class="u-notice-bar"
:style="{
background: computeBgColor,
padding: padding
}"
:class="[
type ? `u-type-${type}-light-bg` : ''
]"
>
<view class="u-direction-row">
<view class="u-icon-wrap">
<u-icon
class="u-left-icon"
v-if="volumeIcon"
name="volume-fill"
:size="volumeSize"
:color="computeColor"
></u-icon>
</view>
<view class="u-notice-box" id="u-notice-box">
<view
class="u-notice-content"
id="u-notice-content"
:style="{
animationDuration: animationDuration,
animationPlayState: animationPlayState,
}"
>
<text
class="u-notice-text"
@tap="click"
:style="[textStyle]"
:class="['u-type-' + type]"
>{{showText}}</text>
</view>
</view>
<view class="u-icon-wrap">
<u-icon
@click="getMore"
class="u-right-icon"
v-if="moreIcon"
name="arrow-right"
:size="26"
:color="computeColor"
></u-icon>
<u-icon
@click="close"
class="u-right-icon"
v-if="closeIcon"
name="close"
:size="24"
:color="computeColor"
></u-icon>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default() {
return []
}
},
type: {
type: String,
default: 'warning'
},
volumeIcon: {
type: Boolean,
default: true
},
moreIcon: {
type: Boolean,
default: false
},
closeIcon: {
type: Boolean,
default: false
},
autoplay: {
type: Boolean,
default: true
},
color: {
type: String,
default: ''
},
bgColor: {
type: String,
default: ''
},
show: {
type: Boolean,
default: true
},
fontSize: {
type: [Number, String],
default: 13
},
volumeSize: {
type: [Number, String],
default: 17
},
speed: {
type: [Number, String],
default: 160
},
playState: {
type: String,
default: 'play'
},
padding: {
type: [Number, String],
default: '9rpx 12rpx'
}
},
data() {
return {
textWidth: 0,
boxWidth: 0,
animationDuration: '10s',
animationPlayState: 'paused',
showText: ''
}
},
watch: {
list: {
immediate: true,
handler(val) {
this.showText = val.join(',')
this.$nextTick(() => {
this.initSize()
})
}
},
playState(val) {
if (val == 'play') this.animationPlayState = 'running'
else this.animationPlayState = 'paused'
},
speed(val) {
this.initSize()
}
},
computed: {
computeColor() {
if (this.color) return this.color
else if (this.type == 'none') return '#606266'
else return this.type
},
textStyle() {
let style = {}
if (this.color) style.color = this.color
else if (this.type == 'none') style.color = '#606266'
style.fontSize = this.fontSize + 'rpx'
return style
},
computeBgColor() {
if (this.bgColor) return this.bgColor
else if (this.type == 'none') return 'transparent'
}
},
mounted() {
this.$nextTick(() => {
this.initSize()
})
},
methods: {
initSize() {
let query = [],
boxWidth = 0,
textWidth = 0
let textQuery = new Promise((resolve, reject) => {
uni
.createSelectorQuery()
.in(this)
.select(`#u-notice-content`)
.boundingClientRect()
.exec(ret => {
this.textWidth = ret[0].width
resolve()
})
})
query.push(textQuery)
Promise.all(query).then(() => {
this.animationDuration = `${this.textWidth / uni.upx2px(this.speed)}s`
this.animationPlayState = 'paused'
setTimeout(() => {
if (this.playState == 'play' && this.autoplay)
this.animationPlayState = 'running'
}, 10)
})
},
click(index) {
this.$emit('click')
},
close() {
this.$emit('close')
},
getMore() {
this.$emit('getMore')
}
}
}
</script>
<style lang="scss" scoped>
@import '../../libs/css/style.components.scss';
.u-notice-bar {
padding: 9rpx 12rpx;
overflow: hidden;
}
.u-direction-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.u-left-icon {
display: inline-flex;
align-items: center;
}
.u-notice-box {
flex: 1;
display: flex;
overflow: hidden;
margin-left: 6rpx;
}
.u-right-icon {
margin-left: 6rpx;
display: inline-flex;
align-items: center;
}
.u-notice-content {
animation: u-loop-animation 10s linear infinite both;
text-align: right;
// 这一句很重要,为了能让滚动左右连接起来
padding-left: 100%;
display: flex;
flex-wrap: nowrap;
}
.u-notice-text {
font-size: 13rpx;
word-break: keep-all;
white-space: nowrap;
}
@keyframes u-loop-animation {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>