Skip to content

Commit 3065edc

Browse files
committed
allow custom blob generator in transition util
1 parent 5496b10 commit 3065edc

File tree

2 files changed

+29
-28
lines changed

2 files changed

+29
-28
lines changed

internal/animate/state.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,23 @@ export interface RenderCache {
2929
export interface RenderInput {
3030
currentFrames: InternalKeyframe[];
3131
timestamp: number;
32-
cache: RenderCache;
32+
renderCache: RenderCache;
3333
}
3434

3535
export interface RenderOutput {
3636
points: Point[];
3737
lastFrameId: string | null;
38-
cache: RenderCache;
38+
renderCache: RenderCache;
3939
}
4040

4141
export interface TransitionInput extends RenderInput {
4242
newFrames: Keyframe[];
43+
blobGenerator: <T extends Keyframe>(options: T) => Point[],
4344
}
4445

4546
export interface TransitionOutput {
4647
newFrames: InternalKeyframe[];
47-
cache: RenderCache;
48+
renderCache: RenderCache;
4849
}
4950

5051
const genId = (): string => {
@@ -73,16 +74,16 @@ export const cleanRenderCache = (
7374
}
7475

7576
export const renderFramesAt = (input: RenderInput): RenderOutput => {
76-
const {cache, currentFrames} = input;
77+
const {renderCache, currentFrames} = input;
7778

7879
if (currentFrames.length === 0) {
79-
return {cache, lastFrameId: null, points: []};
80+
return {renderCache, lastFrameId: null, points: []};
8081
}
8182

8283
// Animation freezes at the final shape if there are no more keyframes.
8384
if (currentFrames.length === 1) {
8485
const first = currentFrames[0];
85-
return {cache, lastFrameId: first.id, points: first.initialPoints};
86+
return {renderCache, lastFrameId: first.id, points: first.initialPoints};
8687
}
8788

8889
// Find the start/end keyframes according to the timestamp.
@@ -95,16 +96,16 @@ export const renderFramesAt = (input: RenderInput): RenderOutput => {
9596
}
9697

9798
// Use and cache prepared points for current interpolation.
98-
let preparedStartPoints: Point[] | undefined = cache[startKeyframe.id].preparedStartPoints;
99-
let preparedEndPoints: Point[] | undefined = cache[endKeyframe.id].preparedEndPoints;
99+
let preparedStartPoints: Point[] | undefined = renderCache[startKeyframe.id].preparedStartPoints;
100+
let preparedEndPoints: Point[] | undefined = renderCache[endKeyframe.id].preparedEndPoints;
100101
if (!preparedStartPoints || !preparedEndPoints) {
101102
[preparedStartPoints, preparedEndPoints] = prepare(
102103
startKeyframe.initialPoints,
103104
endKeyframe.initialPoints,
104105
{rawAngles: false, divideRatio: 1},
105106
);
106-
cache[startKeyframe.id].preparedStartPoints = preparedStartPoints;
107-
cache[endKeyframe.id].preparedEndPoints = preparedEndPoints;
107+
renderCache[startKeyframe.id].preparedStartPoints = preparedStartPoints;
108+
renderCache[endKeyframe.id].preparedEndPoints = preparedEndPoints;
108109
}
109110

110111
// Calculate progress between frames as a fraction.
@@ -115,9 +116,8 @@ export const renderFramesAt = (input: RenderInput): RenderOutput => {
115116
// Apply timing function of end frame.
116117
const adjustedProgress = endKeyframe.timingFunction(progress);
117118

118-
// TODO use timing function.
119119
return {
120-
cache,
120+
renderCache,
121121
lastFrameId: startKeyframe.id,
122122
points: interpolateBetween(adjustedProgress, preparedStartPoints, preparedEndPoints),
123123
};
@@ -127,11 +127,11 @@ export const renderFramesAt = (input: RenderInput): RenderOutput => {
127127
// TODO store current blob when interrupts happen to use as source.
128128
// TODO don't remove any frames.
129129
export const transitionFrames = (input: TransitionInput): TransitionOutput => {
130-
const {cache, timestamp, newFrames} = input;
130+
const {renderCache, timestamp, newFrames} = input;
131131

132132
// Wipe animation when given no keyframes.
133133
if (input.newFrames.length === 0) {
134-
return {cache: input.cache, newFrames: []};
134+
return {renderCache: input.renderCache, newFrames: []};
135135
}
136136

137137
// Add current state as initial frame.
@@ -153,5 +153,5 @@ export const transitionFrames = (input: TransitionInput): TransitionOutput => {
153153
}
154154
}
155155

156-
return {cache, newFrames: internalFrames};
156+
return {renderCache, newFrames: internalFrames};
157157
};

public/animate.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ const removeExpiredFrameCallbacks = (
4848
return newStore;
4949
};
5050

51+
const canvasBlobGenerator = (keyframe: CanvasKeyframe): Point[] => {
52+
return mapPoints(genFromOptions(keyframe.blobOptions), ({curr}) => {
53+
curr.x += keyframe?.canvasOptions?.offsetX || 0;
54+
curr.y += keyframe?.canvasOptions?.offsetY || 0;
55+
return curr;
56+
});
57+
}
58+
5159
export const canvasPath = (): CanvasAnimation => {
5260
let internalFrames: InternalKeyframe[] = [];
5361
let renderCache: RenderCache = {};
@@ -57,38 +65,31 @@ export const canvasPath = (): CanvasAnimation => {
5765
const renderTime = Date.now();
5866
internalFrames = removeStaleFrames(internalFrames, renderTime);
5967
const renderOutput = renderFramesAt({
60-
cache: renderCache,
68+
renderCache: renderCache,
6169
timestamp: renderTime,
6270
currentFrames: internalFrames,
6371
});
64-
renderCache = renderOutput.cache;
72+
renderCache = renderOutput.renderCache;
6573
if (renderOutput.lastFrameId && callbackStore[renderOutput.lastFrameId]) {
6674
callbackStore[renderOutput.lastFrameId]();
6775
delete callbackStore[renderOutput.lastFrameId];
6876
}
6977
return renderPath2D(renderOutput.points);
7078
};
7179

72-
const genBlob = (keyframe: CanvasKeyframe): Point[] => {
73-
return mapPoints(genFromOptions(keyframe.blobOptions), ({curr}) => {
74-
curr.x += keyframe?.canvasOptions?.offsetX || 0;
75-
curr.y += keyframe?.canvasOptions?.offsetY || 0;
76-
return curr;
77-
});
78-
}
79-
8080
const transition: CanvasAnimation["transition"] = (...keyframes) => {
8181
const transitionTime = Date.now();
8282
const transitionOutput = transitionFrames({
83-
cache: renderCache,
83+
renderCache: renderCache,
8484
timestamp: transitionTime,
8585
currentFrames: internalFrames,
8686
newFrames: keyframes,
87+
blobGenerator: canvasBlobGenerator,
8788
});
88-
renderCache = transitionOutput.cache;
89+
renderCache = transitionOutput.renderCache;
8990
internalFrames = transitionOutput.newFrames;
9091

91-
// Remove callbacks that are no longer associated with a known frame.
92+
// Cleanup stored data that is no longer associated with a known frame.
9293
callbackStore = removeExpiredFrameCallbacks(internalFrames, callbackStore);
9394
renderCache = cleanRenderCache(internalFrames, renderCache);
9495

0 commit comments

Comments
 (0)