OpenCut/apps/web/src/lib/animation/resolve.ts

136 lines
3.0 KiB
TypeScript

import type {
AnimationPropertyPath,
ElementAnimations,
} from "@/lib/animation/types";
import type { Transform } from "@/lib/rendering";
import {
getColorValueAtTime,
getNumberChannelValueAtTime,
getVectorChannelValueAtTime,
} from "./interpolation";
import { getColorChannelForPath } from "./color-channel";
import { getNumberChannelForPath } from "./number-channel";
import { getVectorChannelForPath } from "./vector-channel";
export function getElementLocalTime({
timelineTime,
elementStartTime,
elementDuration,
}: {
timelineTime: number;
elementStartTime: number;
elementDuration: number;
}): number {
const localTime = timelineTime - elementStartTime;
if (localTime <= 0) {
return 0;
}
if (localTime >= elementDuration) {
return elementDuration;
}
return localTime;
}
export function resolveTransformAtTime({
baseTransform,
animations,
localTime,
}: {
baseTransform: Transform;
animations: ElementAnimations | undefined;
localTime: number;
}): Transform {
const safeLocalTime = Math.max(0, localTime);
return {
position: getVectorChannelValueAtTime({
channel: getVectorChannelForPath({
animations,
propertyPath: "transform.position",
}),
time: safeLocalTime,
fallbackValue: baseTransform.position,
}),
scaleX: getNumberChannelValueAtTime({
channel: getNumberChannelForPath({
animations,
propertyPath: "transform.scaleX",
}),
time: safeLocalTime,
fallbackValue: baseTransform.scaleX,
}),
scaleY: getNumberChannelValueAtTime({
channel: getNumberChannelForPath({
animations,
propertyPath: "transform.scaleY",
}),
time: safeLocalTime,
fallbackValue: baseTransform.scaleY,
}),
rotate: getNumberChannelValueAtTime({
channel: getNumberChannelForPath({
animations,
propertyPath: "transform.rotate",
}),
time: safeLocalTime,
fallbackValue: baseTransform.rotate,
}),
};
}
export function resolveOpacityAtTime({
baseOpacity,
animations,
localTime,
}: {
baseOpacity: number;
animations: ElementAnimations | undefined;
localTime: number;
}): number {
return getNumberChannelValueAtTime({
channel: getNumberChannelForPath({
animations,
propertyPath: "opacity",
}),
time: Math.max(0, localTime),
fallbackValue: baseOpacity,
});
}
export function resolveNumberAtTime({
baseValue,
animations,
propertyPath,
localTime,
}: {
baseValue: number;
animations: ElementAnimations | undefined;
propertyPath: AnimationPropertyPath;
localTime: number;
}): number {
return getNumberChannelValueAtTime({
channel: getNumberChannelForPath({ animations, propertyPath }),
time: Math.max(0, localTime),
fallbackValue: baseValue,
});
}
export function resolveColorAtTime({
baseColor,
animations,
propertyPath,
localTime,
}: {
baseColor: string;
animations: ElementAnimations | undefined;
propertyPath: AnimationPropertyPath;
localTime: number;
}): string {
return getColorValueAtTime({
channel: getColorChannelForPath({ animations, propertyPath }),
time: Math.max(0, localTime),
fallbackValue: baseColor,
});
}