@lordicon/element
Version:
This package offers developers a convenient method for embedding, controlling, and customizing animated icons from Lordicon within web projects.
118 lines (96 loc) • 3.01 kB
text/typescript
import { Player } from '@lordicon/web';
import { Trigger } from '../interfaces';
/**
* The __In__ trigger plays the animation when the icon (target) enters the user's viewport.
*/
export class In implements Trigger {
protected connected: boolean = false;
protected delayTimer: any = null;
protected intersectionObserver: IntersectionObserver | undefined;
constructor(
protected player: Player,
protected element: HTMLElement,
protected targetElement: HTMLElement,
) {
this.onClick = this.onClick.bind(this);
}
onConnected() {
this.connected = true;
this.targetElement.addEventListener('click', this.onClick);
if (this.loading) {
this.play(true);
} else {
this.initIntersectionObserver();
}
}
onDisconnected() {
this.connected = false;
this.targetElement.removeEventListener('click', this.onClick);
this.cleanup();
}
onClick() {
if (this.clickToReplay) {
this.play();
}
}
play(handleDelay?: boolean) {
if (this.player.playing || this.delayTimer) {
return;
}
if (handleDelay && this.delay > 0) {
this.scheduleDelayedPlay();
} else {
this.player.playFromStart();
}
}
protected scheduleDelayedPlay(): void {
this.resetDelayTimer();
this.delayTimer = setTimeout(() => {
this.player.playFromStart();
this.delayTimer = null;
}, this.delay);
}
protected initIntersectionObserver() {
if (this.intersectionObserver) {
return;
}
const callback: IntersectionObserverCallback = (entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.play(true);
this.resetIntersectionObserver();
}
});
};
this.intersectionObserver = new IntersectionObserver(callback, { threshold: 0.5 });
this.intersectionObserver.observe(this.element);
}
protected resetIntersectionObserver() {
if (!this.intersectionObserver) {
return;
}
this.intersectionObserver.unobserve(this.element);
this.intersectionObserver = undefined;
}
protected resetDelayTimer() {
if (!this.delayTimer) {
return;
}
clearTimeout(this.delayTimer);
this.delayTimer = null;
}
protected cleanup(): void {
this.resetIntersectionObserver();
this.resetDelayTimer();
}
get delay() {
const value = this.element.hasAttribute('delay') ? +(this.element.getAttribute('delay') || 0) : 0;
return Math.max(value, 0);
}
get loading() {
return this.element.hasAttribute('loading');
}
get clickToReplay() {
return this.element.hasAttribute('click-to-replay');
}
}