Files
hyperframes/packages/studio/src/utils/globalTimeCompiler.ts
T

79 lines
2.3 KiB
TypeScript

import type { GsapAnimation } from "@hyperframes/core/gsap-parser";
export function absoluteToPercentage(
time: number,
tweenStart: number,
tweenDuration: number,
): number {
if (tweenDuration <= 0) return 0;
const raw = ((time - tweenStart) / tweenDuration) * 100;
return Math.max(0, Math.min(100, Math.round(raw * 1000) / 1000));
}
export function percentageToAbsolute(
pct: number,
tweenStart: number,
tweenDuration: number,
): number {
return tweenStart + (pct / 100) * tweenDuration;
}
export function isTimeWithinTween(
time: number,
tweenStart: number,
tweenDuration: number,
): boolean {
return time >= tweenStart && time <= tweenStart + tweenDuration;
}
export function resolveTweenStart(animation: GsapAnimation): number | null {
if (animation.resolvedStart != null) return animation.resolvedStart;
if (typeof animation.position === "number") return animation.position;
const parsed = Number.parseFloat(animation.position as string);
if (!Number.isNaN(parsed)) return parsed;
return null;
}
export function resolveTweenDuration(animation: GsapAnimation, fallback = 0.5): number {
return animation.duration ?? fallback;
}
export function findTweenAtTime(
time: number,
animations: GsapAnimation[],
selector: string,
): GsapAnimation | null {
for (const anim of animations) {
if (!matchesSelector(anim.targetSelector, selector)) continue;
const start = resolveTweenStart(anim);
if (start === null) continue;
const duration = resolveTweenDuration(anim);
if (isTimeWithinTween(time, start, duration)) return anim;
}
return null;
}
export function absoluteToPercentageForAnimation(
time: number,
animation: GsapAnimation,
): number | null {
const start = resolveTweenStart(animation);
if (start === null) return null;
const duration = resolveTweenDuration(animation);
return absoluteToPercentage(time, start, duration);
}
export function percentageToAbsoluteForAnimation(
pct: number,
animation: GsapAnimation,
): number | null {
const start = resolveTweenStart(animation);
if (start === null) return null;
const duration = resolveTweenDuration(animation);
return percentageToAbsolute(pct, start, duration);
}
function matchesSelector(tweenSelector: string, querySelector: string): boolean {
return tweenSelector.split(",").some((part) => part.trim() === querySelector);
}