cleanup, refactors

This commit is contained in:
MinamiFunakoshiTR 2025-12-01 13:50:43 -05:00
parent 867155c189
commit 916344dcab
Failed to extract signature
2 changed files with 109 additions and 113 deletions

View file

@ -4,7 +4,14 @@
import { DotLottie } from '@lottiefiles/dotlottie-web'; import { DotLottie } from '@lottiefiles/dotlottie-web';
import { createLottieState } from './ts/lottieState.svelte'; import { createLottieState } from './ts/lottieState.svelte';
import { isEqual } from 'es-toolkit'; import { isEqual } from 'es-toolkit';
import { map } from './ts/utils'; import {
syncLottieState,
getMarkerRange,
calculateTargetFrame,
isReverseMode,
createRenderConfig,
isNullish,
} from './ts/utils';
import { Tween } from 'svelte/motion'; import { Tween } from 'svelte/motion';
// Components // Components
@ -74,7 +81,7 @@
: []; : [];
} }
if (marker == '' || marker == null || marker == undefined) { if (isNullish(marker)) {
start = segment ? segment[0] : 0; start = segment ? segment[0] : 0;
end = segment ? segment[1] : lottiePlayer.totalFrames - 1; end = segment ? segment[1] : lottiePlayer.totalFrames - 1;
} }
@ -92,86 +99,11 @@
} }
function onRenderEvent() { function onRenderEvent() {
const keys = [
'currentFrame',
'totalFrames',
'duration',
'loop',
'speed',
'loopCount',
'mode',
'isPaused',
'isPlaying',
'isStopped',
'isLoaded',
'isFrozen',
'segment',
'autoplay',
'layout',
'activeThemeId',
'marker',
];
if (lottiePlayer && lottieState) { if (lottiePlayer && lottieState) {
keys.forEach((key) => { syncLottieState(lottiePlayer, lottieState);
switch (key) {
case 'currentFrame':
lottieState.currentFrame = lottiePlayer!.currentFrame;
break;
case 'totalFrames':
lottieState.totalFrames = lottiePlayer!.totalFrames;
break;
case 'duration':
lottieState.duration = lottiePlayer!.duration;
break;
case 'loop':
lottieState.loop = lottiePlayer!.loop;
break;
case 'speed':
lottieState.speed = lottiePlayer!.speed;
break;
case 'loopCount':
lottieState.loopCount = lottiePlayer!.loopCount;
break;
case 'mode':
lottieState.mode = lottiePlayer!.mode;
break;
case 'isPaused':
lottieState.isPaused = lottiePlayer!.isPaused;
break;
case 'isPlaying':
lottieState.isPlaying = lottiePlayer!.isPlaying;
break;
case 'isStopped':
lottieState.isStopped = lottiePlayer!.isStopped;
break;
case 'isLoaded':
lottieState.isLoaded = lottiePlayer!.isLoaded;
break;
case 'isFrozen':
lottieState.isFrozen = lottiePlayer!.isFrozen;
break;
case 'segment':
lottieState.segment = lottiePlayer!.segment ?? null;
break;
case 'autoplay':
lottieState.autoplay = lottiePlayer!.autoplay ?? false;
break;
case 'layout':
lottieState.layout = lottiePlayer!.layout ?? null;
break;
case 'activeThemeId':
lottieState.activeThemeId = lottiePlayer!.activeThemeId ?? null;
break;
case 'marker':
lottieState.marker = lottiePlayer!.marker ?? undefined;
break;
}
});
progress = (lottiePlayer.currentFrame + 1) / lottiePlayer.totalFrames; progress = (lottiePlayer.currentFrame + 1) / lottiePlayer.totalFrames;
lottieState.progress = progress; lottieState.progress = progress;
onRender(); // call user-defined onRender function onRender();
} }
} }
@ -189,12 +121,7 @@
progressTween = new Tween(0, { duration: tweenDuration, easing: easing }); progressTween = new Tween(0, { duration: tweenDuration, easing: easing });
const _renderConfig = { const _renderConfig = createRenderConfig();
autoResize: true,
devicePixelRatio:
window.devicePixelRatio > 1 ? window.devicePixelRatio * 0.75 : 1,
freezeOnOffscreen: true,
};
lottiePlayer = new DotLottie({ lottiePlayer = new DotLottie({
canvas, canvas,
@ -252,20 +179,11 @@
lottiePlayer?.unfreeze(); lottiePlayer?.unfreeze();
lottieState.isFrozen = false; lottieState.isFrozen = false;
} }
const targetFrame = map( const targetFrame = calculateTargetFrame(progress, mode, start, end);
mode == 'reverse' || mode == 'reverse-bounce' ?
1 - progress
: progress,
0,
1,
start,
end
);
progressTween.target = targetFrame; progressTween.target = targetFrame;
// lottiePlayer.setFrame(targetFrame); // lottiePlayer.setFrame(targetFrame);
} else if ((progress < 0 || progress > 1) && !lottieState.isFrozen) { } else if ((progress < 0 || progress > 1) && !lottieState.isFrozen) {
// lottiePlayer.setFrame(progress < 0 ? start : end); if (isReverseMode(mode)) {
if (mode == 'reverse' || mode == 'reverse-bounce') {
progressTween.target = progress < 0 ? end : start; progressTween.target = progress < 0 ? end : start;
} else { } else {
progressTween.target = progress < 0 ? start : end; progressTween.target = progress < 0 ? start : end;
@ -297,22 +215,11 @@
// Handles marker change // Handles marker change
$effect(() => { $effect(() => {
if (lottieState.isLoaded && lottiePlayer?.marker !== marker) { if (lottieState.isLoaded && lottiePlayer?.marker !== marker) {
if (typeof marker === 'string') { if (typeof marker === 'string' && lottiePlayer) {
lottiePlayer?.setMarker(marker); lottiePlayer.setMarker(marker);
[start, end] = getMarkerRange(lottiePlayer, marker);
start =
lottiePlayer?.markers().find((m) => m.name === marker)?.time ?? 0;
end =
start +
(lottiePlayer?.markers().find((m) => m.name === marker)?.duration ??
0);
// change lottieState marker because
// onRender fires before this
if (lottieState) {
lottieState.marker = marker; lottieState.marker = marker;
} } else if (isNullish(marker)) {
} else if (marker === null || marker === undefined) {
lottiePlayer?.setMarker(''); lottiePlayer?.setMarker('');
} else { } else {
console.warn('Invalid marker type:', marker); console.warn('Invalid marker type:', marker);
@ -488,7 +395,7 @@
</div> </div>
{#if children} {#if children}
{@render children?.()} {@render children()}
{/if} {/if}
</Block> </Block>

View file

@ -1,3 +1,6 @@
import type { DotLottie } from '@lottiefiles/dotlottie-web';
import type { LottieState } from './lottieState.svelte';
function constrain(n: number, low: number, high: number) { function constrain(n: number, low: number, high: number) {
return Math.max(Math.min(n, high), low); return Math.max(Math.min(n, high), low);
} }
@ -20,3 +23,89 @@ export function map(
return constrain(newval, stop2, start2); return constrain(newval, stop2, start2);
} }
} }
/**
* Syncs the lottie player state with the component's lottie state
*/
export function syncLottieState(
lottiePlayer: DotLottie,
lottieState: LottieState
) {
lottieState.currentFrame = lottiePlayer.currentFrame;
lottieState.totalFrames = lottiePlayer.totalFrames;
lottieState.duration = lottiePlayer.duration;
lottieState.loop = lottiePlayer.loop;
lottieState.speed = lottiePlayer.speed;
lottieState.loopCount = lottiePlayer.loopCount;
lottieState.mode = lottiePlayer.mode;
lottieState.isPaused = lottiePlayer.isPaused;
lottieState.isPlaying = lottiePlayer.isPlaying;
lottieState.isStopped = lottiePlayer.isStopped;
lottieState.isLoaded = lottiePlayer.isLoaded;
lottieState.isFrozen = lottiePlayer.isFrozen;
lottieState.segment = lottiePlayer.segment ?? null;
lottieState.autoplay = lottiePlayer.autoplay ?? false;
lottieState.layout = lottiePlayer.layout ?? null;
lottieState.activeThemeId = lottiePlayer.activeThemeId ?? null;
lottieState.marker = lottiePlayer.marker ?? undefined;
}
/**
* Gets marker info by name
*/
export function getMarkerByName(lottiePlayer: DotLottie, markerName: string) {
return lottiePlayer.markers().find((m) => m.name === markerName);
}
/**
* Gets the start and end frames for a marker
*/
export function getMarkerRange(
lottiePlayer: DotLottie,
markerName: string
): [number, number] {
const marker = getMarkerByName(lottiePlayer, markerName);
const start = marker?.time ?? 0;
const end = start + (marker?.duration ?? 0);
return [start, end];
}
/**
* Calculates target frame based on progress and mode
*/
export function calculateTargetFrame(
progress: number,
mode: string,
start: number,
end: number
): number {
const adjustedProgress =
mode === 'reverse' || mode === 'reverse-bounce' ? 1 - progress : progress;
return map(adjustedProgress, 0, 1, start, end);
}
/**
* Determines if mode is reverse
*/
export function isReverseMode(mode: string): boolean {
return mode === 'reverse' || mode === 'reverse-bounce';
}
/**
* Creates render config with optimized defaults
*/
export function createRenderConfig() {
return {
autoResize: true,
devicePixelRatio:
window.devicePixelRatio > 1 ? window.devicePixelRatio * 0.75 : 1,
freezeOnOffscreen: true,
};
}
/**
* Checks if a value is null or undefined (empty marker check)
*/
export function isNullish(value: any): boolean {
return value === null || value === undefined || value === '';
}