У меня есть крошечное приложение, которое отображает одну точку на экране.
Это простой div, связанный с состоянием в хранилище 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 и репозиторий https://github.com/cwayfinder/pausable-ngrx.