I have a tiny application that displays a single dot on the screen.
This is a simple div bound to state in NgRx store.
<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>
The dot state changes are animated by CSS transitions.
.dot {
border-radius: 50%;
position: absolute;
$moveTime: 500ms;
$sizeChangeTime: 400ms;
$colorChangeTime: 900ms;
transition:
top $moveTime, left $moveTime,
background-color $colorChangeTime,
width $sizeChangeTime, height $sizeChangeTime;
}
I have a backend which pushes updates for the dot (position, color and size). I map these updates on NgRx actions.
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 }));
}
});
}
}
The problem is that new changes from backend sometimes come earlier than animation ends.
My objective is to delay updating the state in store (pause triggering new NgRx actions) until all transitions ended. We can easily handle this moment because chrome already supports the transitionstart
event.
I can also explain this with such a diagram
The spacing depends on the transition duration.
Here is the runnable application https://stackblitz.com/edit/angular-qlpr2g and repo https://github.com/cwayfinder/pausable-ngrx.