纸通宝小程序
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

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()
},
})