UNPKG

antd-mini

Version:

antd-mini 是支付宝小程序 UI 组件库,遵循 Ant Design 规范。

157 lines (145 loc) 4.25 kB
import { IBoundingClientRect } from '../_util/base'; import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; import { Component, getValueFromProps, triggerEventOnly, } from '../_util/simply'; import { NoticeBarDefaultProps } from './props'; Component({ props: NoticeBarDefaultProps, data: { show: true, marqueeStyle: '', }, methods: { getInstance() { if (this.$id) { return my; } return this; }, async getBoundingClientRectWithId(prefix: string) { return await getInstanceBoundingClientRect( this.getInstance(), `${prefix}${this.$id ? `-${this.$id}` : ''}` ); }, onTap() { const mode = getValueFromProps(this, 'mode'); if (mode === 'link') { triggerEventOnly(this, 'tap'); } if (mode === 'closeable') { if (typeof this.props.onTap !== 'function') { return; } this.setData({ show: false, }); triggerEventOnly(this, 'tap'); } }, startMarquee(state) { const loop = getValueFromProps(this, 'loop'); const leading = 500; const { duration, overflowWidth, viewWidth } = state; let marqueeScrollWidth = overflowWidth; if (loop) { marqueeScrollWidth = overflowWidth + viewWidth; } const newMarqueeStyle = `transform: translate3d(${-marqueeScrollWidth}px, 0, 0); transition: ${duration}s all linear ${ typeof leading === 'number' ? `${leading / 1000}s` : '0s' };`; this.setData({ marqueeStyle: newMarqueeStyle, }); return newMarqueeStyle; }, measureText(callback) { const fps = 40; const loop = getValueFromProps(this, 'loop'); // 计算文本所占据的宽度,计算需要滚动的宽度 setTimeout(async () => { const marqueeSize: IBoundingClientRect | null = await this.getBoundingClientRectWithId('.ant-notice-bar-marquee'); const contentSize: IBoundingClientRect | null = await this.getBoundingClientRectWithId('.ant-notice-bar-content'); const overflowWidth = (marqueeSize && contentSize && marqueeSize.width - contentSize.width) || 0; const viewWidth = contentSize?.width || 0; let marqueeScrollWidth = overflowWidth; if (loop) { marqueeScrollWidth = overflowWidth + viewWidth; } if (overflowWidth > 0) { callback({ overflowWidth, viewWidth, duration: marqueeScrollWidth / fps, }); } }, 0); }, // 文本滚动的计算 resetMarquee(state) { const loop = getValueFromProps(this, 'loop'); const { viewWidth } = state; let showMarqueeWidth = '0px'; if (loop) { showMarqueeWidth = `${viewWidth}px`; } const marqueeStyle = `transform: translate3d(${showMarqueeWidth}, 0, 0); transition: 0s all linear;`; this.setData({ marqueeStyle, }); }, onTransitionEnd() { const loop = getValueFromProps(this, 'loop'); const trailing = 200; if (loop) { const timer = setTimeout(() => { this.measureText((state) => { this.resetMarquee.call(this, state); }); clearTimeout(timer); }, trailing); } }, }, didMount() { const { enableMarquee } = this.props; if (enableMarquee) { this.measureText((state) => { this.startMarquee.call(this, state); }); } }, didUpdate() { const { enableMarquee } = this.props; // 这里更新处理的原因是防止notice内容在动画过程中发生改变。 if (enableMarquee) { this.measureText((state) => { this.startMarquee.call(this, state); }); } }, pageEvents: { onShow() { if (this.props.enableMarquee) { this.setData({ marqueeStyle: '' }); this.resetMarquee({ overflowWidth: 0, duration: 0, viewWidth: 0, }); this.measureText((state) => { this.startMarquee.call(this, state); }); } }, }, });