fix(NoticeBar): replay event only triggered once (#6293)

This commit is contained in:
neverland 2020-05-17 20:54:27 +08:00 committed by GitHub
parent f2ec0c5a4d
commit 1dfa1af288
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 57 deletions

View File

@ -1,4 +1,5 @@
import { createNamespace } from '../utils'; import { createNamespace } from '../utils';
import { doubleRaf } from '../utils/dom/raf';
import Icon from '../icon'; import Icon from '../icon';
const [createComponent, bem] = createNamespace('notice-bar'); const [createComponent, bem] = createNamespace('notice-bar');
@ -27,12 +28,12 @@ export default createComponent({
data() { data() {
return { return {
show: true,
offset: 0,
duration: 0,
wrapWidth: 0, wrapWidth: 0,
firstRound: true, firstRound: true,
duration: 0, contentWidth: 0,
offsetWidth: 0,
showNoticeBar: true,
animationClass: '',
}; };
}, },
@ -47,25 +48,27 @@ export default createComponent({
methods: { methods: {
onClickIcon(event) { onClickIcon(event) {
if (this.mode === 'closeable') { if (this.mode === 'closeable') {
this.showNoticeBar = false; this.show = false;
this.$emit('close', event); this.$emit('close', event);
} }
}, },
onAnimationEnd() { onTransitionEnd() {
this.offset = this.wrapWidth;
this.duration = 0;
this.firstRound = false; this.firstRound = false;
this.$nextTick(() => {
this.duration = (this.offsetWidth + this.wrapWidth) / this.speed; doubleRaf(() => {
this.animationClass = bem('play--infinite'); this.offset = -this.contentWidth;
this.duration = (this.contentWidth + this.wrapWidth) / this.speed;
this.$emit('replay'); this.$emit('replay');
}); });
}, },
reset() { reset() {
this.wrapWidth = 0;
this.offsetWidth = 0;
this.animationClass = '';
this.duration = 0; this.duration = 0;
this.wrapWidth = 0;
this.contentWidth = 0;
}, },
start() { start() {
@ -76,12 +79,13 @@ export default createComponent({
} }
const wrapWidth = wrap.getBoundingClientRect().width; const wrapWidth = wrap.getBoundingClientRect().width;
const offsetWidth = content.getBoundingClientRect().width; const contentWidth = content.getBoundingClientRect().width;
if (this.scrollable && offsetWidth > wrapWidth) {
if (this.scrollable && contentWidth > wrapWidth) {
this.offset = -contentWidth;
this.duration = contentWidth / this.speed;
this.wrapWidth = wrapWidth; this.wrapWidth = wrapWidth;
this.offsetWidth = offsetWidth; this.contentWidth = contentWidth;
this.duration = offsetWidth / this.speed;
this.animationClass = bem('play');
} else { } else {
this.reset(); this.reset();
} }
@ -98,9 +102,9 @@ export default createComponent({
}; };
const contentStyle = { const contentStyle = {
paddingLeft: this.firstRound ? 0 : this.wrapWidth + 'px', transform: `translateX(${this.offset}px)`,
animationDelay: (this.firstRound ? this.delay : 0) + 's', transitionDelay: (this.firstRound ? this.delay : 0) + 's',
animationDuration: this.duration + 's', transitionDuration: this.duration + 's',
}; };
function LeftIcon() { function LeftIcon() {
@ -143,7 +147,7 @@ export default createComponent({
return ( return (
<div <div
role="alert" role="alert"
vShow={this.showNoticeBar} vShow={this.show}
class={bem({ wrapable: this.wrapable })} class={bem({ wrapable: this.wrapable })}
style={barStyle} style={barStyle}
onClick={(event) => { onClick={(event) => {
@ -156,12 +160,10 @@ export default createComponent({
ref="content" ref="content"
class={[ class={[
bem('content'), bem('content'),
this.animationClass,
{ 'van-ellipsis': !this.scrollable && !this.wrapable }, { 'van-ellipsis': !this.scrollable && !this.wrapable },
]} ]}
style={contentStyle} style={contentStyle}
onAnimationend={this.onAnimationEnd} onTransitionend={this.onTransitionEnd}
onWebkitAnimationEnd={this.onAnimationEnd}
> >
{this.slots() || this.text} {this.slots() || this.text}
</div> </div>

View File

@ -34,20 +34,13 @@
&__content { &__content {
position: absolute; position: absolute;
white-space: nowrap; white-space: nowrap;
transition-timing-function: linear;
&.van-ellipsis { &.van-ellipsis {
max-width: 100%; max-width: 100%;
} }
} }
&__play {
animation: van-notice-bar-play linear both;
&--infinite {
animation: van-notice-bar-play-infinite linear infinite both;
}
}
&--wrapable { &--wrapable {
height: auto; height: auto;
padding: @notice-bar-wrapable-padding; padding: @notice-bar-wrapable-padding;
@ -65,19 +58,3 @@
} }
} }
} }
/**
* Declare two same keyframes
* In case that some mobile browsers can continue animation when className changed
*/
@keyframes van-notice-bar-play {
to {
transform: translate3d(-100%, 0, 0);
}
}
@keyframes van-notice-bar-play-infinite {
to {
transform: translate3d(-100%, 0, 0);
}
}

View File

@ -6,34 +6,34 @@ exports[`renders demo correctly 1`] = `
<div role="alert" class="van-notice-bar"><i class="van-icon van-icon-volume-o van-notice-bar__left-icon"> <div role="alert" class="van-notice-bar"><i class="van-icon van-icon-volume-o van-notice-bar__left-icon">
<!----></i> <!----></i>
<div role="marquee" class="van-notice-bar__wrap"> <div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div> <div class="van-notice-bar__content" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div>
</div> </div>
</div> </div>
</div> </div>
<div> <div>
<div role="alert" class="van-notice-bar"> <div role="alert" class="van-notice-bar">
<div role="marquee" class="van-notice-bar__wrap"> <div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content van-ellipsis" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div> <div class="van-notice-bar__content van-ellipsis" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div>
</div> </div>
</div> </div>
</div> </div>
<div> <div>
<div role="alert" class="van-notice-bar van-notice-bar--wrapable"> <div role="alert" class="van-notice-bar van-notice-bar--wrapable">
<div role="marquee" class="van-notice-bar__wrap"> <div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div> <div class="van-notice-bar__content" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div>
</div> </div>
</div> </div>
</div> </div>
<div> <div>
<div role="alert" class="van-notice-bar"> <div role="alert" class="van-notice-bar">
<div role="marquee" class="van-notice-bar__wrap"> <div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div> <div class="van-notice-bar__content" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div>
</div><i class="van-icon van-icon-cross van-notice-bar__right-icon"> </div><i class="van-icon van-icon-cross van-notice-bar__right-icon">
<!----></i> <!----></i>
</div> </div>
<div role="alert" class="van-notice-bar"> <div role="alert" class="van-notice-bar">
<div role="marquee" class="van-notice-bar__wrap"> <div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div> <div class="van-notice-bar__content" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div>
</div><i class="van-icon van-icon-arrow van-notice-bar__right-icon"> </div><i class="van-icon van-icon-arrow van-notice-bar__right-icon">
<!----></i> <!----></i>
</div> </div>
@ -42,7 +42,7 @@ exports[`renders demo correctly 1`] = `
<div role="alert" class="van-notice-bar" style="color: rgb(25, 137, 250); background: rgb(236, 249, 255);"><i class="van-icon van-icon-info-o van-notice-bar__left-icon"> <div role="alert" class="van-notice-bar" style="color: rgb(25, 137, 250); background: rgb(236, 249, 255);"><i class="van-icon van-icon-info-o van-notice-bar__left-icon">
<!----></i> <!----></i>
<div role="marquee" class="van-notice-bar__wrap"> <div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div> <div class="van-notice-bar__content" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">足协杯战线连续第2年上演广州德比战上赛季半决赛上恒大以两回合5-3的总比分淘汰富力。</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,7 +2,7 @@
exports[`icon slot 1`] = ` exports[`icon slot 1`] = `
<div role="alert" class="van-notice-bar">Custom Left Icon<div role="marquee" class="van-notice-bar__wrap"> <div role="alert" class="van-notice-bar">Custom Left Icon<div role="marquee" class="van-notice-bar__wrap">
<div class="van-notice-bar__content" style="padding-left: 0px; animation-delay: 1s; animation-duration: 0s;"> <div class="van-notice-bar__content" style="transform: translateX(0px); transition-delay: 1s; transition-duration: 0s;">
Content Content
</div> </div>
</div>Custom Right Icon</div> </div>Custom Right Icon</div>

View File

@ -44,7 +44,7 @@ test('replay event', async () => {
}, },
}); });
wrapper.find('.van-notice-bar__content').trigger('animationend'); wrapper.find('.van-notice-bar__content').trigger('transitionend');
await later(); await later(50);
expect(wrapper.emitted('replay')).toBeTruthy(); expect(wrapper.emitted('replay')).toBeTruthy();
}); });