diff options
Diffstat (limited to 'apps/web/src/services/renderer/nodes/visual-node.ts')
| -rw-r--r-- | apps/web/src/services/renderer/nodes/visual-node.ts | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/apps/web/src/services/renderer/nodes/visual-node.ts b/apps/web/src/services/renderer/nodes/visual-node.ts index 7179369e..50451b4a 100644 --- a/apps/web/src/services/renderer/nodes/visual-node.ts +++ b/apps/web/src/services/renderer/nodes/visual-node.ts @@ -2,8 +2,13 @@ import type { CanvasRenderer } from "../canvas-renderer"; import { BaseNode } from "./base-node"; import type { BlendMode } from "@/types/rendering"; import type { Transform } from "@/types/timeline"; - -const VISUAL_EPSILON = 1 / 1000; +import type { ElementAnimations } from "@/types/animation"; +import { + getElementLocalTime, + resolveOpacityAtTime, + resolveTransformAtTime, +} from "@/lib/animation"; +import { TIME_EPSILON_SECONDS } from "@/constants/animation-constants"; export interface VisualNodeParams { duration: number; @@ -11,6 +16,7 @@ export interface VisualNodeParams { trimStart: number; trimEnd: number; transform: Transform; + animations?: ElementAnimations; opacity: number; blendMode?: BlendMode; } @@ -18,14 +24,22 @@ export interface VisualNodeParams { export abstract class VisualNode< Params extends VisualNodeParams = VisualNodeParams, > extends BaseNode<Params> { - protected getLocalTime(time: number): number { + protected getSourceLocalTime(time: number): number { return time - this.params.timeOffset + this.params.trimStart; } + protected getAnimationLocalTime(time: number): number { + return getElementLocalTime({ + timelineTime: time, + elementStartTime: this.params.timeOffset, + elementDuration: this.params.duration, + }); + } + protected isInRange(time: number): boolean { - const localTime = this.getLocalTime(time); + const localTime = this.getSourceLocalTime(time); return ( - localTime >= this.params.trimStart - VISUAL_EPSILON && + localTime >= this.params.trimStart - TIME_EPSILON_SECONDS && localTime < this.params.trimStart + this.params.duration ); } @@ -35,15 +49,27 @@ export abstract class VisualNode< source, sourceWidth, sourceHeight, + timelineTime, }: { renderer: CanvasRenderer; source: CanvasImageSource; sourceWidth: number; sourceHeight: number; + timelineTime: number; }): void { renderer.context.save(); - const { transform, opacity } = this.params; + const animationLocalTime = this.getAnimationLocalTime(timelineTime); + const transform = resolveTransformAtTime({ + baseTransform: this.params.transform, + animations: this.params.animations, + localTime: animationLocalTime, + }); + const opacity = resolveOpacityAtTime({ + baseOpacity: this.params.opacity, + animations: this.params.animations, + localTime: animationLocalTime, + }); const containScale = Math.min( renderer.width / sourceWidth, renderer.height / sourceHeight, |
