@twick/visualizer 0.0.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +20 -20
- package/README.md +12 -12
- package/package.json +34 -31
- package/package.json.bak +34 -0
- package/src/animations/blur.tsx +60 -0
- package/src/animations/breathe.tsx +60 -0
- package/src/animations/fade.tsx +60 -0
- package/src/animations/photo-rise.tsx +66 -0
- package/src/animations/photo-zoom.tsx +73 -0
- package/src/animations/rise.tsx +118 -0
- package/src/animations/succession.tsx +77 -0
- package/src/components/frame-effects.tsx +188 -190
- package/src/components/track.tsx +237 -0
- package/src/controllers/animation.controller.ts +39 -0
- package/src/controllers/element.controller.ts +43 -0
- package/src/controllers/frame-effect.controller.tsx +30 -0
- package/src/controllers/text-effect.controller.ts +33 -0
- package/src/elements/audio.element.tsx +17 -0
- package/src/elements/caption.element.tsx +87 -0
- package/src/elements/circle.element.tsx +20 -0
- package/src/elements/icon.element.tsx +20 -0
- package/src/elements/image.element.tsx +53 -0
- package/src/elements/rect.element.tsx +22 -0
- package/src/elements/scene.element.tsx +29 -0
- package/src/elements/text.element.tsx +28 -0
- package/src/elements/video.element.tsx +55 -0
- package/src/frame-effects/circle.frame.tsx +103 -0
- package/src/frame-effects/rect.frame.tsx +103 -0
- package/src/global.css +11 -11
- package/src/helpers/caption.utils.ts +30 -40
- package/src/helpers/constants.ts +162 -158
- package/src/helpers/element.utils.ts +239 -85
- package/src/helpers/event.utils.ts +6 -0
- package/src/helpers/filters.ts +127 -127
- package/src/helpers/log.utils.ts +29 -32
- package/src/helpers/timing.utils.ts +110 -129
- package/src/helpers/types.ts +242 -146
- package/src/helpers/utils.ts +20 -0
- package/src/index.ts +6 -4
- package/src/live.tsx +16 -16
- package/src/project.ts +6 -6
- package/src/sample.ts +247 -449
- package/src/text-effects/elastic.tsx +39 -0
- package/src/text-effects/erase.tsx +58 -0
- package/src/text-effects/stream-word.tsx +60 -0
- package/src/text-effects/typewriter.tsx +59 -0
- package/src/visualizer.tsx +98 -78
- package/tsconfig.json +11 -10
- package/typedoc.json +14 -14
- package/vite.config.ts +15 -15
- package/src/components/animation.tsx +0 -7
- package/src/components/element.tsx +0 -344
- package/src/components/timeline.tsx +0 -225
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Element component that handles the creation and management of visual elements
|
|
3
|
-
* with various properties like position, size, rotation, and effects.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { createRef, waitFor, all, Reference, Color } from "@revideo/core";
|
|
7
|
-
import { Audio, Circle, Icon, Img, Rect, Txt, Video } from "@revideo/2d";
|
|
8
|
-
import { logger } from "../helpers/log.utils";
|
|
9
|
-
import {
|
|
10
|
-
DEFAULT_BACKGROUND_COLOR,
|
|
11
|
-
ELEMENT_TYPES,
|
|
12
|
-
TRANSPARENT_COLOR,
|
|
13
|
-
} from "../helpers/constants";
|
|
14
|
-
import { fitElement } from "../helpers/element.utils";
|
|
15
|
-
import { applyColorFilter } from "../helpers/filters";
|
|
16
|
-
import { addFrameEffect } from "./frame-effects";
|
|
17
|
-
import { Caption, CaptionProps, VisualizerElement } from "../helpers/types";
|
|
18
|
-
import { splitPhraseTiming } from "../helpers/caption.utils";
|
|
19
|
-
import { addAnimations } from "./animation";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export function* addMediaElement({
|
|
23
|
-
containerRef,
|
|
24
|
-
element,
|
|
25
|
-
mediaType,
|
|
26
|
-
waitOnStart = true,
|
|
27
|
-
}: {
|
|
28
|
-
containerRef: Reference<any>;
|
|
29
|
-
element: VisualizerElement;
|
|
30
|
-
mediaType: string;
|
|
31
|
-
waitOnStart?: boolean;
|
|
32
|
-
}) {
|
|
33
|
-
if (waitOnStart) {
|
|
34
|
-
yield* waitFor(element.s);
|
|
35
|
-
}
|
|
36
|
-
const frameContainerRef = createRef<any>();
|
|
37
|
-
const frameElementRef = createRef<any>();
|
|
38
|
-
if (mediaType === ELEMENT_TYPES.VIDEO) {
|
|
39
|
-
const frameProps = element.frame || element.props;
|
|
40
|
-
logger(`Adding video element ${element.id}`);
|
|
41
|
-
yield containerRef().add(
|
|
42
|
-
<Rect ref={frameContainerRef} key={element.id} {...frameProps}>
|
|
43
|
-
<Video
|
|
44
|
-
ref={frameElementRef}
|
|
45
|
-
key={`child-${element.id}`}
|
|
46
|
-
{...element.props}
|
|
47
|
-
/>
|
|
48
|
-
</Rect>
|
|
49
|
-
);
|
|
50
|
-
} else if (mediaType === ELEMENT_TYPES.IMAGE) {
|
|
51
|
-
logger(`Adding image element ${element.id}`);
|
|
52
|
-
yield containerRef().add(
|
|
53
|
-
<Rect ref={frameContainerRef} key={element.id} {...element.frame}>
|
|
54
|
-
<Img
|
|
55
|
-
ref={frameElementRef}
|
|
56
|
-
key={`child-${element.id}`}
|
|
57
|
-
{...element.props}
|
|
58
|
-
/>
|
|
59
|
-
</Rect>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
if (frameContainerRef()) {
|
|
63
|
-
yield fitElement({
|
|
64
|
-
elementRef: frameElementRef,
|
|
65
|
-
containerSize: frameContainerRef().size(),
|
|
66
|
-
elementSize: frameElementRef().size(),
|
|
67
|
-
objectFit: element.objectFit,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (element?.props?.mediaFilter) {
|
|
71
|
-
applyColorFilter(frameElementRef, element.props.mediaFilter);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
yield* all(
|
|
75
|
-
addAnimations({
|
|
76
|
-
elementRef: frameElementRef,
|
|
77
|
-
}),
|
|
78
|
-
addFrameEffect({
|
|
79
|
-
containerRef: frameContainerRef,
|
|
80
|
-
elementRef: frameElementRef,
|
|
81
|
-
frameElement,
|
|
82
|
-
}),
|
|
83
|
-
waitFor(Math.max(0, element.e - element.s))
|
|
84
|
-
);
|
|
85
|
-
if (element.type === ELEMENT_TYPES.VIDEO) {
|
|
86
|
-
yield frameElementRef().playing(false);
|
|
87
|
-
}
|
|
88
|
-
yield frameElementRef().remove();
|
|
89
|
-
yield frameContainerRef().remove();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function* addCaptionElement({
|
|
94
|
-
caption,
|
|
95
|
-
captionProps,
|
|
96
|
-
containerRef,
|
|
97
|
-
capStyle,
|
|
98
|
-
}: {
|
|
99
|
-
caption: Caption;
|
|
100
|
-
captionProps: CaptionProps;
|
|
101
|
-
containerRef: Reference<any>;
|
|
102
|
-
capStyle: string;
|
|
103
|
-
}) {
|
|
104
|
-
const words = splitPhraseTiming(caption);
|
|
105
|
-
let phraseStart = 0;
|
|
106
|
-
if (words?.length) {
|
|
107
|
-
phraseStart = words[0].s;
|
|
108
|
-
}
|
|
109
|
-
let wordsState: {
|
|
110
|
-
refs: Array<{ bgRef?: Reference<any>; textRef: Reference<any> }>;
|
|
111
|
-
props: CaptionProps[];
|
|
112
|
-
idx: number;
|
|
113
|
-
prevTime: number;
|
|
114
|
-
} = {
|
|
115
|
-
refs: [],
|
|
116
|
-
props: [],
|
|
117
|
-
idx: 0,
|
|
118
|
-
prevTime: phraseStart,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
for (const word of words) {
|
|
122
|
-
wordsState.props.push(captionProps);
|
|
123
|
-
const textRef = createRef<Txt>();
|
|
124
|
-
containerRef().add(
|
|
125
|
-
<Txt ref={textRef} {...captionProps} text={word.t} opacity={0} />
|
|
126
|
-
);
|
|
127
|
-
if (capStyle == "highlight_bg") {
|
|
128
|
-
const bgContainerRef = createRef();
|
|
129
|
-
const childTextRef = createRef();
|
|
130
|
-
containerRef().add(
|
|
131
|
-
<Rect
|
|
132
|
-
ref={bgContainerRef}
|
|
133
|
-
fill={new Color(captionProps.colors.background).alpha(
|
|
134
|
-
captionProps?.bgOpacity ?? 1
|
|
135
|
-
)}
|
|
136
|
-
width={textRef().width() + (captionProps.bgOffsetWidth ?? 30)}
|
|
137
|
-
height={textRef().height() + (captionProps.bgOffsetHeight ?? 10)}
|
|
138
|
-
margin={captionProps.bgMargin ?? [0, -5]}
|
|
139
|
-
radius={captionProps.bgRadius ?? 10}
|
|
140
|
-
padding={captionProps.bgPadding ?? [0, 15]}
|
|
141
|
-
opacity={0}
|
|
142
|
-
alignItems={"center"}
|
|
143
|
-
justifyContent={"center"}
|
|
144
|
-
layout
|
|
145
|
-
>
|
|
146
|
-
<Txt ref={childTextRef} {...captionProps} text={word.t} />
|
|
147
|
-
</Rect>
|
|
148
|
-
);
|
|
149
|
-
textRef().remove();
|
|
150
|
-
wordsState.refs.push({
|
|
151
|
-
bgRef: bgContainerRef,
|
|
152
|
-
textRef: childTextRef,
|
|
153
|
-
});
|
|
154
|
-
} else {
|
|
155
|
-
wordsState.refs.push({
|
|
156
|
-
textRef: textRef,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
wordsState.prevTime = word.e;
|
|
160
|
-
wordsState.idx = wordsState.idx + 1;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
wordsState.prevTime = phraseStart;
|
|
164
|
-
wordsState.idx = 0;
|
|
165
|
-
|
|
166
|
-
for (const word of words) {
|
|
167
|
-
if (capStyle == "highlight_bg") {
|
|
168
|
-
yield* wordsState.refs[wordsState.idx]?.bgRef?.().opacity(1, 0);
|
|
169
|
-
yield* waitFor(Math.max(0, word.e - word.s));
|
|
170
|
-
yield* wordsState.refs[wordsState.idx]
|
|
171
|
-
?.bgRef?.()
|
|
172
|
-
.fill(TRANSPARENT_COLOR, 0);
|
|
173
|
-
} else {
|
|
174
|
-
yield* wordsState.refs[wordsState.idx]?.textRef?.().opacity(1, 0);
|
|
175
|
-
yield* waitFor(Math.max(0, word.e - word.s));
|
|
176
|
-
}
|
|
177
|
-
wordsState.prevTime = word.e;
|
|
178
|
-
wordsState.idx = wordsState.idx + 1;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export function* makeSceneElements({
|
|
183
|
-
containerRef,
|
|
184
|
-
element,
|
|
185
|
-
}: {
|
|
186
|
-
containerRef: Reference<any>;
|
|
187
|
-
element: VisualizerElement;
|
|
188
|
-
}) {
|
|
189
|
-
switch (element.type) {
|
|
190
|
-
case ELEMENT_TYPES.RECT:
|
|
191
|
-
yield* addSceneRectElement({ containerRef, element });
|
|
192
|
-
break;
|
|
193
|
-
case ELEMENT_TYPES.IMAGE:
|
|
194
|
-
case ELEMENT_TYPES.VIDEO:
|
|
195
|
-
const mediaContainerRef = createRef<any>();
|
|
196
|
-
yield containerRef().add(
|
|
197
|
-
<Rect
|
|
198
|
-
ref={mediaContainerRef}
|
|
199
|
-
fill={element.backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
|
|
200
|
-
size={"100%"}
|
|
201
|
-
/>
|
|
202
|
-
);
|
|
203
|
-
yield* addMediaElement({
|
|
204
|
-
containerRef: mediaContainerRef,
|
|
205
|
-
element,
|
|
206
|
-
mediaType: element.type,
|
|
207
|
-
waitOnStart: false,
|
|
208
|
-
});
|
|
209
|
-
yield mediaContainerRef().remove();
|
|
210
|
-
break;
|
|
211
|
-
default:
|
|
212
|
-
yield* waitFor(Math.max(0, element.e - element.s));
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function* addSceneRectElement({
|
|
218
|
-
containerRef,
|
|
219
|
-
element,
|
|
220
|
-
}: {
|
|
221
|
-
containerRef: Reference<any>;
|
|
222
|
-
element: VisualizerElement;
|
|
223
|
-
}) {
|
|
224
|
-
const elementRef = createRef<any>();
|
|
225
|
-
let sequence: any[] = [];
|
|
226
|
-
yield containerRef().add(
|
|
227
|
-
<Rect ref={elementRef} key={element.id} {...element.props}></Rect>
|
|
228
|
-
);
|
|
229
|
-
for (const childElement of element.elements || []) {
|
|
230
|
-
sequence.push(
|
|
231
|
-
makeSceneElements({
|
|
232
|
-
containerRef: elementRef,
|
|
233
|
-
element: childElement,
|
|
234
|
-
})
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
yield* all(
|
|
239
|
-
...sequence,
|
|
240
|
-
addAnimations({
|
|
241
|
-
elementRef,
|
|
242
|
-
}),
|
|
243
|
-
waitFor(Math.max(0, element.e - element.s))
|
|
244
|
-
);
|
|
245
|
-
yield elementRef().remove();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export function* addRectElement({
|
|
249
|
-
containerRef,
|
|
250
|
-
element,
|
|
251
|
-
}: {
|
|
252
|
-
containerRef: Reference<any>;
|
|
253
|
-
element: VisualizerElement;
|
|
254
|
-
}) {
|
|
255
|
-
const elementRef = createRef<any>();
|
|
256
|
-
yield* waitFor(element?.s);
|
|
257
|
-
yield containerRef().add(
|
|
258
|
-
<Rect ref={elementRef} key={element.id} {...element.props} />
|
|
259
|
-
);
|
|
260
|
-
yield* all(
|
|
261
|
-
addAnimations({ elementRef: elementRef }),
|
|
262
|
-
waitFor(Math.max(0, element.e - element.s))
|
|
263
|
-
);
|
|
264
|
-
yield elementRef().remove();
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export function* addTextElement({
|
|
268
|
-
containerRef,
|
|
269
|
-
element,
|
|
270
|
-
}: {
|
|
271
|
-
containerRef: Reference<any>;
|
|
272
|
-
element: VisualizerElement;
|
|
273
|
-
}) {
|
|
274
|
-
const elementRef = createRef<any>();
|
|
275
|
-
yield* waitFor(element?.s);
|
|
276
|
-
yield containerRef().add(
|
|
277
|
-
<Txt
|
|
278
|
-
ref={elementRef}
|
|
279
|
-
key={element.id}
|
|
280
|
-
text={element.t}
|
|
281
|
-
{...element.props}
|
|
282
|
-
/>
|
|
283
|
-
);
|
|
284
|
-
yield* all(
|
|
285
|
-
addAnimations({ elementRef: elementRef }),
|
|
286
|
-
waitFor(Math.max(0, element.e - element.s))
|
|
287
|
-
);
|
|
288
|
-
yield elementRef().remove();
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
export function* addCircleElement({
|
|
292
|
-
containerRef,
|
|
293
|
-
element,
|
|
294
|
-
}: {
|
|
295
|
-
containerRef: Reference<any>;
|
|
296
|
-
element: VisualizerElement;
|
|
297
|
-
}) {
|
|
298
|
-
const elementRef = createRef<any>();
|
|
299
|
-
yield* waitFor(element?.s);
|
|
300
|
-
yield containerRef().add(
|
|
301
|
-
<Circle ref={elementRef} key={element.id} {...element.props} />
|
|
302
|
-
);
|
|
303
|
-
yield* all(
|
|
304
|
-
addAnimations({ elementRef: elementRef }),
|
|
305
|
-
waitFor(Math.max(0, element.e - element.s))
|
|
306
|
-
);
|
|
307
|
-
yield elementRef().remove();
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
export function* addIconElement({
|
|
311
|
-
containerRef,
|
|
312
|
-
element,
|
|
313
|
-
}: {
|
|
314
|
-
containerRef: Reference<any>;
|
|
315
|
-
element: VisualizerElement;
|
|
316
|
-
}) {
|
|
317
|
-
const elementRef = createRef<any>();
|
|
318
|
-
yield* waitFor(element?.s);
|
|
319
|
-
yield containerRef().add(
|
|
320
|
-
<Icon ref={elementRef} key={element.id} {...element.props} />
|
|
321
|
-
);
|
|
322
|
-
yield* all(
|
|
323
|
-
addAnimations({ elementRef: elementRef }),
|
|
324
|
-
waitFor(Math.max(0, element.e - element.s))
|
|
325
|
-
);
|
|
326
|
-
yield elementRef().remove();
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
export function* addAudioElement({
|
|
330
|
-
containerRef,
|
|
331
|
-
element,
|
|
332
|
-
}: {
|
|
333
|
-
containerRef: Reference<any>;
|
|
334
|
-
element: VisualizerElement;
|
|
335
|
-
}) {
|
|
336
|
-
const elementRef = createRef<any>();
|
|
337
|
-
yield* waitFor(element?.s);
|
|
338
|
-
yield containerRef().add(
|
|
339
|
-
<Audio ref={elementRef} key={element.id} {...element.props} />
|
|
340
|
-
);
|
|
341
|
-
yield* waitFor(Math.max(0, element.e - element.s));
|
|
342
|
-
yield elementRef().playing(false);
|
|
343
|
-
yield elementRef().remove();
|
|
344
|
-
}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Timeline component that handles the creation and management of different types of timelines
|
|
3
|
-
* including video, audio, captions, scenes, and elements.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Layout, Rect, View2D, Audio } from "@revideo/2d";
|
|
7
|
-
import { VisualizerTimeline } from "../helpers/types";
|
|
8
|
-
import { all, Color, createRef, waitFor } from "@revideo/core";
|
|
9
|
-
import { addAudioElement, addCaptionElement, addCircleElement, addIconElement, addMediaElement, addRectElement, addTextElement, makeSceneElements } from "./element";
|
|
10
|
-
import { CAPTION_STYLE, DEFAULT_CAPTION_COLORS, DEFAULT_CAPTION_FONT, ELEMENT_TYPES } from "../helpers/constants";
|
|
11
|
-
import { logger } from "../helpers/log.utils";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Creates a video timeline with specified configuration
|
|
15
|
-
* @param {Object} params - Parameters for video timeline creation
|
|
16
|
-
* @param {View2D} params.view - The 2D view to render the video in
|
|
17
|
-
* @param {VideoTimeline} params.timeline - Video timeline configuration
|
|
18
|
-
* @returns {Generator} Generator function for video timeline animation
|
|
19
|
-
*/
|
|
20
|
-
export function* makeVideoTimeline({
|
|
21
|
-
view,
|
|
22
|
-
timeline,
|
|
23
|
-
}: {
|
|
24
|
-
view: View2D;
|
|
25
|
-
timeline: VisualizerTimeline;
|
|
26
|
-
}) {
|
|
27
|
-
const frameRef = createRef<any>();
|
|
28
|
-
let prevTime = 0;
|
|
29
|
-
view.add(<Layout size={"100%"} ref={frameRef} layout />);
|
|
30
|
-
for (const element of timeline.elements || []) {
|
|
31
|
-
yield* waitFor(element?.s - prevTime);
|
|
32
|
-
yield* addMediaElement({
|
|
33
|
-
containerRef: frameRef,
|
|
34
|
-
element,
|
|
35
|
-
mediaType: ELEMENT_TYPES.VIDEO,
|
|
36
|
-
waitOnStart: false,
|
|
37
|
-
});
|
|
38
|
-
prevTime = element.e;
|
|
39
|
-
}
|
|
40
|
-
yield frameRef().remove();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Creates an audio timeline with specified configuration
|
|
45
|
-
* @param {Object} params - Parameters for audio timeline creation
|
|
46
|
-
* @param {View2D} params.view - The 2D view to render the audio in
|
|
47
|
-
* @param {AudioTimeline} params.timeline - Audio timeline configuration
|
|
48
|
-
* @returns {Generator} Generator function for audio timeline animation
|
|
49
|
-
*/
|
|
50
|
-
export function* makeAudioTimeline({
|
|
51
|
-
view,
|
|
52
|
-
timeline,
|
|
53
|
-
}: {
|
|
54
|
-
view: View2D;
|
|
55
|
-
timeline: VisualizerTimeline;
|
|
56
|
-
}) {
|
|
57
|
-
let prevTime = 0;
|
|
58
|
-
for (const audioElement of timeline.elements) {
|
|
59
|
-
const audioRef = createRef<any>();
|
|
60
|
-
yield* waitFor(audioElement?.s - prevTime);
|
|
61
|
-
prevTime = audioElement?.e;
|
|
62
|
-
logger(`Adding audio element ${audioElement.id}`);
|
|
63
|
-
view.add(
|
|
64
|
-
<Audio ref={audioRef} key={audioElement.id} {...audioElement.props} />
|
|
65
|
-
);
|
|
66
|
-
yield* waitFor(Math.max(0, audioElement.e - audioElement.s));
|
|
67
|
-
yield audioRef().playing(false);
|
|
68
|
-
yield audioRef().remove();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Creates a caption timeline with specified configuration
|
|
74
|
-
* @param {Object} params - Parameters for caption timeline creation
|
|
75
|
-
* @param {View2D} params.view - The 2D view to render the caption in
|
|
76
|
-
* @param {CaptionTimeline} params.timeline - Caption timeline configuration
|
|
77
|
-
* @returns {Generator} Generator function for caption timeline animation
|
|
78
|
-
*/
|
|
79
|
-
export function* makeCaptionTimeline({ view, timeline }: { view: View2D; timeline: VisualizerTimeline }) {
|
|
80
|
-
let prevTime = 0;
|
|
81
|
-
const captionTimelineRef = createRef<any>();
|
|
82
|
-
view.add(<Layout size={"100%"} ref={captionTimelineRef} />);
|
|
83
|
-
|
|
84
|
-
const tProps = timeline?.props;
|
|
85
|
-
|
|
86
|
-
const timelineDefaultProps = (CAPTION_STYLE[tProps?.capStyle ?? ""] || {}).word || {};
|
|
87
|
-
|
|
88
|
-
for (const element of timeline.elements) {
|
|
89
|
-
const eProps = element.props;
|
|
90
|
-
const rectStyle = (CAPTION_STYLE[eProps?.capStyle ?? tProps?.capStyle ?? ""] || {}).rect || {};
|
|
91
|
-
// Cast alignItems/justifyContent as any to satisfy RectProps
|
|
92
|
-
const mappedRectStyle = {
|
|
93
|
-
...rectStyle,
|
|
94
|
-
justifyContent: rectStyle.justifyContent as any,
|
|
95
|
-
alignItems: rectStyle.alignItems as any,
|
|
96
|
-
};
|
|
97
|
-
const phraseProps = {
|
|
98
|
-
...timelineDefaultProps,
|
|
99
|
-
colors: {
|
|
100
|
-
text: eProps?.colors?.text ?? tProps?.colors?.text ?? DEFAULT_CAPTION_COLORS.text,
|
|
101
|
-
background: eProps?.colors?.background ?? tProps?.colors?.background ?? DEFAULT_CAPTION_COLORS.background,
|
|
102
|
-
},
|
|
103
|
-
font: {
|
|
104
|
-
family: eProps?.font?.family ?? tProps?.font?.family ?? DEFAULT_CAPTION_FONT.family,
|
|
105
|
-
size: eProps?.font?.size ?? tProps?.font?.size ?? DEFAULT_CAPTION_FONT.size,
|
|
106
|
-
weight: eProps?.font?.weight ?? tProps?.font?.weight ?? DEFAULT_CAPTION_FONT.weight
|
|
107
|
-
},
|
|
108
|
-
fill: eProps?.colors?.text ?? tProps?.colors?.text ?? DEFAULT_CAPTION_COLORS.text,
|
|
109
|
-
bgColor: eProps?.colors?.background ?? tProps?.colors?.background ??DEFAULT_CAPTION_COLORS.background,
|
|
110
|
-
bgOpacity: eProps?.bgOpacity ?? tProps?.bgOpacity ?? 1,
|
|
111
|
-
...(tProps?.captionProps || {}),
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
yield* waitFor(element?.s - prevTime);
|
|
115
|
-
const phraseRef = createRef<any>();
|
|
116
|
-
captionTimelineRef().add(
|
|
117
|
-
<Rect
|
|
118
|
-
ref={phraseRef}
|
|
119
|
-
key={element.id}
|
|
120
|
-
{...mappedRectStyle}
|
|
121
|
-
x={eProps?.x ?? tProps?.x}
|
|
122
|
-
y={eProps?.y ?? tProps?.y}
|
|
123
|
-
layout
|
|
124
|
-
/>
|
|
125
|
-
);
|
|
126
|
-
if (tProps?.capStyle === "word_by_word_with_bg") {
|
|
127
|
-
phraseRef().fill(
|
|
128
|
-
new Color(phraseProps.bgColor).alpha(phraseProps.bgOpacity)
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
yield* addCaptionElement({
|
|
132
|
-
caption: {...element, t: element.t ?? ""},
|
|
133
|
-
captionProps: phraseProps,
|
|
134
|
-
containerRef: phraseRef,
|
|
135
|
-
capStyle: eProps?.capStyle ?? tProps?.capStyle,
|
|
136
|
-
});
|
|
137
|
-
prevTime = element.e;
|
|
138
|
-
yield phraseRef().remove();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Creates a scene timeline with specified configuration
|
|
144
|
-
* @param {Object} params - Parameters for scene timeline creation
|
|
145
|
-
* @param {View2D} params.view - The 2D view to render the scene in
|
|
146
|
-
* @param {SceneTimeline} params.timeline - Scene timeline configuration
|
|
147
|
-
* @returns {Generator} Generator function for scene timeline animation
|
|
148
|
-
*/
|
|
149
|
-
export function* makeSceneTimeline({ view, timeline }: { view: View2D; timeline: VisualizerTimeline }) {
|
|
150
|
-
const frameRef = createRef<any>();
|
|
151
|
-
let prevTime = 0;
|
|
152
|
-
view.add(<Layout size={"100%"} ref={frameRef} layout />);
|
|
153
|
-
for (const sceneElement of timeline.elements || []) {
|
|
154
|
-
yield* waitFor(sceneElement?.s - prevTime);
|
|
155
|
-
yield* makeSceneElements({
|
|
156
|
-
containerRef: frameRef,
|
|
157
|
-
element: sceneElement,
|
|
158
|
-
});
|
|
159
|
-
prevTime = sceneElement.e;
|
|
160
|
-
}
|
|
161
|
-
yield frameRef().remove();
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Creates an element timeline with specified configuration
|
|
166
|
-
* @param {Object} params - Parameters for element timeline creation
|
|
167
|
-
* @param {View2D} params.view - The 2D view to render the element in
|
|
168
|
-
* @param {ElementTimeline} params.timeline - Element timeline configuration
|
|
169
|
-
* @returns {Generator} Generator function for element timeline animation
|
|
170
|
-
*/
|
|
171
|
-
export function* makeElementTimeline({ view, timeline }: { view: View2D; timeline: VisualizerTimeline }) {
|
|
172
|
-
const elementTimelineRef = createRef<any>();
|
|
173
|
-
view.add(<Layout size={"100%"} ref={elementTimelineRef} />);
|
|
174
|
-
|
|
175
|
-
const sequence = [];
|
|
176
|
-
for (const element of timeline.elements) {
|
|
177
|
-
switch (element.type) {
|
|
178
|
-
case ELEMENT_TYPES.RECT:
|
|
179
|
-
sequence.push(
|
|
180
|
-
addRectElement({ containerRef: elementTimelineRef, element })
|
|
181
|
-
);
|
|
182
|
-
break;
|
|
183
|
-
case ELEMENT_TYPES.TEXT:
|
|
184
|
-
sequence.push(
|
|
185
|
-
addTextElement({ containerRef: elementTimelineRef, element })
|
|
186
|
-
);
|
|
187
|
-
break;
|
|
188
|
-
case ELEMENT_TYPES.IMAGE:
|
|
189
|
-
sequence.push(
|
|
190
|
-
addMediaElement({
|
|
191
|
-
containerRef: elementTimelineRef,
|
|
192
|
-
element,
|
|
193
|
-
mediaType: ELEMENT_TYPES.IMAGE,
|
|
194
|
-
})
|
|
195
|
-
);
|
|
196
|
-
break;
|
|
197
|
-
case ELEMENT_TYPES.VIDEO:
|
|
198
|
-
sequence.push(
|
|
199
|
-
addMediaElement({
|
|
200
|
-
containerRef: elementTimelineRef,
|
|
201
|
-
element,
|
|
202
|
-
mediaType: ELEMENT_TYPES.VIDEO,
|
|
203
|
-
})
|
|
204
|
-
);
|
|
205
|
-
break;
|
|
206
|
-
case ELEMENT_TYPES.AUDIO:
|
|
207
|
-
sequence.push(
|
|
208
|
-
addAudioElement({ containerRef: elementTimelineRef, element })
|
|
209
|
-
);
|
|
210
|
-
break;
|
|
211
|
-
case ELEMENT_TYPES.CIRCLE:
|
|
212
|
-
sequence.push(
|
|
213
|
-
addCircleElement({ containerRef: elementTimelineRef, element })
|
|
214
|
-
);
|
|
215
|
-
break;
|
|
216
|
-
case ELEMENT_TYPES.ICON:
|
|
217
|
-
sequence.push(
|
|
218
|
-
addIconElement({ containerRef: elementTimelineRef, element })
|
|
219
|
-
);
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
yield* all(...sequence);
|
|
224
|
-
yield elementTimelineRef().remove();
|
|
225
|
-
}
|