generic animation interrupt

This commit is contained in:
“chrisshank” 2024-09-12 11:11:01 -07:00
parent 1bd42742f4
commit dc12340294
1 changed files with 70 additions and 16 deletions

View File

@ -281,22 +281,7 @@ export class RecordPlayer extends HTMLElement {
const arm = this.shadowRoot!.querySelector('.tone-arm') as HTMLElement;
const animation = arm.getAnimations()[0];
if (animation) {
animation.commitStyles();
animation.cancel();
const rotate = arm.style.rotate;
arm.style.rotate = '';
arm.animate(
[
{ offset: 0, rotate },
{ offset: 0.2, rotate, transform: 'rotateX(20deg)' },
{ offset: 0.8, transform: 'rotateX(20deg)' },
],
{ duration: 3000 }
);
}
reverseAnimation(arm);
clearTimeout(this.#playTimeout);
this.#internals.states.delete('playing');
@ -332,3 +317,72 @@ export class RecordPlayer extends HTMLElement {
}
}
}
function reverseAnimation(el: HTMLElement) {
const animation = el.getAnimations()[0];
if (!animation || !(animation.effect instanceof KeyframeEffect)) return;
const originalStyles = createStyleMap(el.getAttribute('style') || '');
animation.commitStyles();
animation.cancel();
const animationStyles = createStyleMap(el.getAttribute('style') || '');
const changedProperties = diffStyles(originalStyles, animationStyles);
// reset styles
for (const property of changedProperties) {
el.style.setProperty(property, originalStyles.get(property) || '');
}
// reverse current animation
const { progress = 0 } = animation.effect.getComputedTiming();
const keyframes = animation.effect.getKeyframes();
const rotate = animationStyles.get('rotate') || 0;
// TODO: dont hard code this
el.animate(
[
{ offset: 0, rotate },
{ offset: 0.2, rotate, transform: 'rotateX(20deg)' },
{ offset: 0.8, transform: 'rotateX(20deg)' },
],
{ duration: 3000 }
);
}
function createStyleMap(style: string): Map<string, string> {
const stylesMaps = new Map<string, string>();
for (const declaration of style.split(';')) {
if (declaration.length > 0) {
const [property, value] = declaration.split(':');
stylesMaps.set(property.trim(), value.trim());
}
}
return stylesMaps;
}
function diffStyles(stylesA: Map<string, string>, stylesB: Map<string, string>): Set<string> {
const changedProperties = new Set<string>();
stylesA.forEach((valueA, property) => {
const valueB = stylesB.get(property);
if (valueB === undefined || valueA !== valueB) {
changedProperties.add(property);
}
});
stylesB.forEach((_, property) => {
if (!changedProperties.has(property)) {
changedProperties.add(property);
}
});
return changedProperties;
}