这是一个简单的 div,绑定(bind)到 NgRx 存储中的状态。
<div class="dot"
[style.width.px]="size$ | async"
[style.height.px]="size$ | async"
[style.backgroundColor]="color$ | async"
[style.left.px]="x$ | async"
[style.top.px]="y$ | async"
(transitionstart)="transitionStart()"
(transitionend)="transitionEnd()"></div>
点状态的变化由 CSS 转换动画。
.dot {
border-radius: 50%;
position: absolute;
$moveTime: 500ms;
$sizeChangeTime: 400ms;
$colorChangeTime: 900ms;
transition:
top $moveTime, left $moveTime,
background-color $colorChangeTime,
width $sizeChangeTime, height $sizeChangeTime;
}
我有一个后端推送点的更新(位置、颜色和大小)。我将这些更新映射到 NgRx 操作上。
export class AppComponent implements OnInit {
...
constructor(private store: Store<AppState>, private backend: BackendService) {}
ngOnInit(): void {
...
this.backend.update$.subscribe(({ type, value }) => {
// TODO: trigger new NgRx action when all animations ended
if (type === 'position') {
const { x, y } = value;
this.store.dispatch(move({ x, y }));
} else if (type === 'color') {
this.store.dispatch(changeColor({ color: value }));
} else if (type === 'size') {
this.store.dispatch(changeSize({ size: value }));
}
});
}
}
问题是来自后端的新变化有时比动画结束来得早。
我的目标是延迟更新存储中的状态(暂停触发新的 NgRx 操作)直到所有转换结束。我们可以轻松处理这一刻,因为 chrome 已经支持 transitionstart
事件。
间距取决于过渡持续时间。
这是可运行的应用程序 https://stackblitz.com/edit/angular-qlpr2g和 repo https://github.com/cwayfinder/pausable-ngrx .
最佳答案
您可以使用 concatMap和 delayWhen去做这个。还要注意 transitionEnd
事件 can be fired multiple times如果更改了多个属性,那么我使用 debounceTime过滤此类双重事件。我们不能改用 distinctUntilChanged
,因为第一个 transitionEnd
将触发下一次更新,立即将 transitionInProgress$ 状态更改为 true。我不使用 transitionStart
回调,因为在触发 transitionStart 之前可能会出现多个更新。 Here is工作示例。
export class AppComponent implements OnInit {
...
private readonly transitionInProgress$ = new BehaviorSubject(false);
ngOnInit(): void {
...
this.backend.update$.pipe(
concatMap(update => of(update).pipe(
delayWhen(() => this.transitionInProgress$.pipe(
// debounce the transition state, because transitionEnd event fires multiple
// times for a single transiation, if multiple properties were changed
debounceTime(1),
filter(inProgress => !inProgress)
))
))
).subscribe(update => {
this.transitionInProgress$.next(true)
if (update.type === 'position') {
this.store.dispatch(move(update.value));
} else if (update.type === 'color') {
this.store.dispatch(changeColor({ color: update.value }));
} else if (update.type === 'size') {
this.store.dispatch(changeSize({ size: update.value }));
}
});
}
transitionEnd(event: TransitionEvent) {
this.transitionInProgress$.next(false)
}
}
关于javascript - 在动画进行时暂停调度 NgRx Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57026990/