taro-material
Version:
Mini Program components that implement Google's Material Design.
198 lines (179 loc) • 5.76 kB
JavaScript
import PropTypes from 'prop-types'
import Taro from '@tarojs/taro'
import classNames from 'classnames'
import { View, Text } from '@tarojs/components'
import AtComponent from '../../common/component'
export default class AtNoticebar extends AtComponent {
constructor () {
super(...arguments)
const animElemId = `J_${Math.ceil(Math.random() * 10e5).toString(36)}`
this.state = {
show: true,
animElemId,
dura: 15,
isWEAPP: Taro.getEnv() === Taro.ENV_TYPE.WEAPP,
isALIPAY: Taro.getEnv() === Taro.ENV_TYPE.ALIPAY,
isWEB: Taro.getEnv() === Taro.ENV_TYPE.WEB,
}
}
onClose () {
this.setState({
show: false,
})
this.props.onClose && this.props.onClose(...arguments)
}
onGotoMore () {
this.props.onGotoMore && this.props.onGotoMore(...arguments)
}
componentWillReceiveProps () {
if (!this.timeout) {
this.interval && clearInterval(this.interval)
this.initAnimation()
}
}
componentDidMount () {
if (!this.props.marquee) return
this.initAnimation()
}
initAnimation () {
const {
isWEAPP,
isALIPAY,
} = this.state
this.timeout = setTimeout(() => {
this.timeout = null
if (this.state.isWEB) {
const elem = document.querySelector(`.${this.state.animElemId}`)
if (!elem) return
const width = elem.getBoundingClientRect().width
const dura = width / (+this.props.speed)
this.setState({ dura })
} else if (isWEAPP || isALIPAY) {
const query = isALIPAY ? Taro.createSelectorQuery() : Taro.createSelectorQuery().in(this.$scope)
query.select(`.${this.state.animElemId}`).boundingClientRect().exec(res => {
res = res[0]
if (!res) return
const { width } = res
const dura = width / (+this.props.speed)
const animation = Taro.createAnimation({
duration: dura * 1000,
timingFunction: 'linear',
})
const resetAnimation = Taro.createAnimation({
duration: 0,
timingFunction: 'linear',
})
const resetOpacityAnimation = Taro.createAnimation({
duration: 0,
timingFunction: 'linear',
})
const animBody = () => {
resetOpacityAnimation.opacity(0).step()
this.setState({ animationData: resetOpacityAnimation.export() })
setTimeout(() => {
resetAnimation.translateX(0).step()
this.setState({ animationData: resetAnimation.export() })
}, 300)
setTimeout(() => {
resetOpacityAnimation.opacity(1).step()
this.setState({ animationData: resetOpacityAnimation.export() })
}, 600)
setTimeout(() => {
animation.translateX(-width).step()
this.setState({ animationData: animation.export() })
}, 900)
}
animBody()
this.interval = setInterval(animBody, (dura * 1000) + 1000)
})
}
}, 100)
}
render () {
const {
single,
icon,
marquee,
customStyle,
} = this.props
let {
showMore,
close,
} = this.props
const { dura } = this.state
const rootClassName = ['at-noticebar']
let _moreText = this.props.moreText
if (!single) showMore = false
if (!_moreText) _moreText = '查看详情'
const style = {}
const innerClassName = ['at-noticebar__content-inner']
if (marquee) {
close = false
style['animation-duration'] = `${dura}s`
innerClassName.push(this.state.animElemId)
}
const classObject = {
'at-noticebar--marquee': marquee,
'at-noticebar--weapp': marquee && (this.state.isWEAPP || this.state.isALIPAY),
'at-noticebar--single': !marquee && single,
}
const iconClass = ['at-icon']
if (icon) iconClass.push(`at-icon-${icon}`)
return (
this.state.show &&
<View
className={classNames(rootClassName, classObject, this.props.className)}
style={customStyle}
>
{close && (
<View className='at-noticebar__close' onClick={this.onClose.bind(this)}>
<Text className='at-icon at-icon-close'></Text>
</View>
)}
<View className='at-noticebar__content'>
{icon && (
<View className='at-noticebar__content-icon'>
{/* start hack 百度小程序 */}
<Text className={classNames(iconClass, iconClass)}></Text>
</View>
)}
<View className='at-noticebar__content-text'>
<View animation={this.state.animationData} className={classNames(innerClassName)} style={style}>{this.props.children}</View>
</View>
</View>
{showMore && (
<View className='at-noticebar__more' onClick={this.onGotoMore.bind(this)}>
<Text className='text'>{_moreText}</Text>
<View className='at-noticebar__more-icon'>
<Text className='at-icon at-icon-chevron-right'></Text>
</View>
</View>
)}
</View>
)
}
}
AtNoticebar.defaultProps = {
close: false,
single: false,
marquee: false,
speed: 100,
moreText: '查看详情',
showMore: false,
icon: '',
customStyle: {},
onClose: () => {},
onGotoMore: () => {},
}
AtNoticebar.propTypes = {
close: PropTypes.bool,
single: PropTypes.bool,
marquee: PropTypes.bool,
speed: PropTypes.number,
moreText: PropTypes.string,
showMore: PropTypes.bool,
icon: PropTypes.string,
customStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
onClose: PropTypes.func,
onGotoMore: PropTypes.func,
}