You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.0 KiB
165 lines
5.0 KiB
import baseComponent from '../helpers/baseComponent'
|
|
import classNames from '../helpers/classNames'
|
|
|
|
baseComponent({
|
|
properties: {
|
|
prefixCls: {
|
|
type: String,
|
|
value: 'wux-notice-bar',
|
|
},
|
|
icon: {
|
|
type: String,
|
|
value: null,
|
|
},
|
|
content: {
|
|
type: String,
|
|
value: '',
|
|
},
|
|
mode: {
|
|
type: String,
|
|
value: '',
|
|
},
|
|
action: {
|
|
type: String,
|
|
value: null,
|
|
},
|
|
loop: {
|
|
type: Boolean,
|
|
value: false,
|
|
},
|
|
leading: {
|
|
type: Number,
|
|
value: 500,
|
|
},
|
|
trailing: {
|
|
type: Number,
|
|
value: 1000,
|
|
},
|
|
speed: {
|
|
type: Number,
|
|
value: 25,
|
|
},
|
|
},
|
|
data: {
|
|
animatedWidth: 0,
|
|
overflowWidth: 0,
|
|
visible: true,
|
|
},
|
|
computed: {
|
|
classes: ['prefixCls', function(prefixCls) {
|
|
const wrap = classNames(prefixCls)
|
|
const hd = `${prefixCls}__hd`
|
|
const icon = `${prefixCls}__icon`
|
|
const bd = `${prefixCls}__bd`
|
|
const container = `${prefixCls}__marquee-container`
|
|
const marquee = `${prefixCls}__marquee`
|
|
const ft = `${prefixCls}__ft`
|
|
const action = `${prefixCls}__action`
|
|
|
|
return {
|
|
wrap,
|
|
hd,
|
|
icon,
|
|
bd,
|
|
container,
|
|
marquee,
|
|
ft,
|
|
action,
|
|
}
|
|
}],
|
|
},
|
|
observers: {
|
|
content() {
|
|
this.resetAnimation()
|
|
},
|
|
},
|
|
methods: {
|
|
clearMarqueeTimer() {
|
|
if (this.marqueeTimer) {
|
|
clearTimeout(this.marqueeTimer)
|
|
this.marqueeTimer = null
|
|
}
|
|
},
|
|
startAnimation() {
|
|
this.clearMarqueeTimer()
|
|
const { loop, leading, trailing, speed } = this.data
|
|
const isLeading = this.data.animatedWidth === 0
|
|
const timeout = isLeading ? leading : speed
|
|
const animate = () => {
|
|
let animatedWidth = this.data.animatedWidth + 1
|
|
const isRoundOver = animatedWidth > this.data.overflowWidth
|
|
// 判断是否完成一次滚动
|
|
if (isRoundOver) {
|
|
if (!loop) return
|
|
// 重置初始位置
|
|
animatedWidth = 0
|
|
}
|
|
// 判断是否等待一段时间后进行下一次滚动
|
|
if (isRoundOver && trailing) {
|
|
this.triggerEvent('loop')
|
|
setTimeout(() => {
|
|
this.setData({ animatedWidth })
|
|
this.marqueeTimer = setTimeout(animate, speed)
|
|
}, trailing)
|
|
} else {
|
|
this.setData({ animatedWidth })
|
|
this.marqueeTimer = setTimeout(animate, speed)
|
|
|
|
}
|
|
}
|
|
if (this.data.overflowWidth !== 0) {
|
|
this.marqueeTimer = setTimeout(animate, timeout)
|
|
}
|
|
},
|
|
initAnimation(isForce) {
|
|
const { prefixCls } = this.data
|
|
const query = wx.createSelectorQuery().in(this)
|
|
query.select(`.${prefixCls}__marquee-container`).boundingClientRect()
|
|
query.select(`.${prefixCls}__marquee`).boundingClientRect()
|
|
query.exec((rects) => {
|
|
if (rects.filter((n) => !n).length) return
|
|
|
|
const [container, text] = rects
|
|
const overflowWidth = text.width - container.width
|
|
if (this.data.overflowWidth !== overflowWidth || isForce) {
|
|
this.setData({ overflowWidth, animatedWidth: 0 }, () => {
|
|
// 当文本内容存在且长度可滚动时,才触发动画
|
|
if (text.width > 0 && overflowWidth > 0) {
|
|
this.startAnimation()
|
|
} else {
|
|
this.startLoop()
|
|
}
|
|
})
|
|
}
|
|
})
|
|
},
|
|
startLoop: function () {
|
|
this.clearMarqueeTimer()
|
|
this.marqueeTimer = setTimeout(() => {
|
|
this.triggerEvent('loop')
|
|
}, 3000)
|
|
},
|
|
resetAnimation() {
|
|
this.initAnimation(true)
|
|
},
|
|
stopAnimation() {
|
|
this.clearMarqueeTimer()
|
|
},
|
|
onAction() {
|
|
if (this.data.mode === 'closable') {
|
|
this.clearMarqueeTimer()
|
|
this.setData({ visible: false })
|
|
}
|
|
this.triggerEvent('click')
|
|
},
|
|
onClick() {
|
|
this.triggerEvent('click')
|
|
},
|
|
},
|
|
ready() {
|
|
this.initAnimation()
|
|
},
|
|
detached() {
|
|
this.clearMarqueeTimer()
|
|
},
|
|
})
|