@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.
Files changed (53) hide show
  1. package/.eslintrc.json +20 -20
  2. package/README.md +12 -12
  3. package/package.json +34 -31
  4. package/package.json.bak +34 -0
  5. package/src/animations/blur.tsx +60 -0
  6. package/src/animations/breathe.tsx +60 -0
  7. package/src/animations/fade.tsx +60 -0
  8. package/src/animations/photo-rise.tsx +66 -0
  9. package/src/animations/photo-zoom.tsx +73 -0
  10. package/src/animations/rise.tsx +118 -0
  11. package/src/animations/succession.tsx +77 -0
  12. package/src/components/frame-effects.tsx +188 -190
  13. package/src/components/track.tsx +237 -0
  14. package/src/controllers/animation.controller.ts +39 -0
  15. package/src/controllers/element.controller.ts +43 -0
  16. package/src/controllers/frame-effect.controller.tsx +30 -0
  17. package/src/controllers/text-effect.controller.ts +33 -0
  18. package/src/elements/audio.element.tsx +17 -0
  19. package/src/elements/caption.element.tsx +87 -0
  20. package/src/elements/circle.element.tsx +20 -0
  21. package/src/elements/icon.element.tsx +20 -0
  22. package/src/elements/image.element.tsx +53 -0
  23. package/src/elements/rect.element.tsx +22 -0
  24. package/src/elements/scene.element.tsx +29 -0
  25. package/src/elements/text.element.tsx +28 -0
  26. package/src/elements/video.element.tsx +55 -0
  27. package/src/frame-effects/circle.frame.tsx +103 -0
  28. package/src/frame-effects/rect.frame.tsx +103 -0
  29. package/src/global.css +11 -11
  30. package/src/helpers/caption.utils.ts +30 -40
  31. package/src/helpers/constants.ts +162 -158
  32. package/src/helpers/element.utils.ts +239 -85
  33. package/src/helpers/event.utils.ts +6 -0
  34. package/src/helpers/filters.ts +127 -127
  35. package/src/helpers/log.utils.ts +29 -32
  36. package/src/helpers/timing.utils.ts +110 -129
  37. package/src/helpers/types.ts +242 -146
  38. package/src/helpers/utils.ts +20 -0
  39. package/src/index.ts +6 -4
  40. package/src/live.tsx +16 -16
  41. package/src/project.ts +6 -6
  42. package/src/sample.ts +247 -449
  43. package/src/text-effects/elastic.tsx +39 -0
  44. package/src/text-effects/erase.tsx +58 -0
  45. package/src/text-effects/stream-word.tsx +60 -0
  46. package/src/text-effects/typewriter.tsx +59 -0
  47. package/src/visualizer.tsx +98 -78
  48. package/tsconfig.json +11 -10
  49. package/typedoc.json +14 -14
  50. package/vite.config.ts +15 -15
  51. package/src/components/animation.tsx +0 -7
  52. package/src/components/element.tsx +0 -344
  53. package/src/components/timeline.tsx +0 -225
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Track component that handles the creation and management of different types of tracks
3
+ * including video, audio, captions, scenes, and elements.
4
+ */
5
+
6
+ import { Layout, Rect, View2D, Audio } from "@twick/2d";
7
+ import { VisualizerTrack } from "../helpers/types";
8
+ import { all, Color, createRef, ThreadGenerator, waitFor } from "@twick/core";
9
+ import {
10
+ CAPTION_STYLE,
11
+ DEFAULT_CAPTION_COLORS,
12
+ DEFAULT_CAPTION_FONT,
13
+ } from "../helpers/constants";
14
+ import { logger } from "../helpers/log.utils";
15
+ import elementController from "../controllers/element.controller";
16
+ import { hexToRGB } from "../helpers/utils";
17
+
18
+ /**
19
+ * Creates a video track with specified configuration
20
+ * @param {Object} params - Parameters for video track creation
21
+ * @param {View2D} params.view - The 2D view to render the video in
22
+ * @param {VideoTrack} params.track - Video track configuration
23
+ * @returns {Generator} Generator function for video track animation
24
+ */
25
+ export function* makeVideoTrack({
26
+ view,
27
+ track,
28
+ }: {
29
+ view: View2D;
30
+ track: VisualizerTrack;
31
+ }) {
32
+ const frameRef = createRef<any>();
33
+ let prevTime = 0;
34
+ view.add(<Layout size={"100%"} ref={frameRef} layout />);
35
+ for (const element of track.elements || []) {
36
+ yield* waitFor(element?.s - prevTime);
37
+ yield* elementController.get("video")?.create({
38
+ containerRef: frameRef,
39
+ element,
40
+ view,
41
+ });
42
+ prevTime = element.e;
43
+ }
44
+ yield frameRef().remove();
45
+ }
46
+
47
+ /**
48
+ * Creates an audio track with specified configuration
49
+ * @param {Object} params - Parameters for audio track creation
50
+ * @param {View2D} params.view - The 2D view to render the audio in
51
+ * @param {AudioTrack} params.track - Audio track configuration
52
+ * @returns {Generator} Generator function for audio track animation
53
+ */
54
+ export function* makeAudioTrack({
55
+ view,
56
+ track,
57
+ }: {
58
+ view: View2D;
59
+ track: VisualizerTrack;
60
+ }) {
61
+ let prevTime = 0;
62
+ for (const audioElement of track.elements) {
63
+ const audioRef = createRef<any>();
64
+ yield* waitFor(audioElement?.s - prevTime);
65
+ prevTime = audioElement?.e;
66
+ logger(`Adding audio element ${audioElement.id}`);
67
+ view.add(
68
+ <Audio ref={audioRef} key={audioElement.id} {...audioElement.props} />
69
+ );
70
+ yield* waitFor(Math.max(0, audioElement.e - audioElement.s));
71
+ yield audioRef().playing(false);
72
+ yield audioRef().remove();
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Creates a caption track with specified configuration
78
+ * @param {Object} params - Parameters for caption track creation
79
+ * @param {View2D} params.view - The 2D view to render the caption in
80
+ * @param {CaptionTrack} params.track - Caption track configuration
81
+ * @returns {Generator} Generator function for caption track animation
82
+ */
83
+ export function* makeCaptionTrack({
84
+ view,
85
+ track,
86
+ }: {
87
+ view: View2D;
88
+ track: VisualizerTrack;
89
+ }) {
90
+ let prevTime = 0;
91
+ const captionTrackRef = createRef<any>();
92
+ view.add(<Layout size={"100%"} ref={captionTrackRef} />);
93
+
94
+ const tProps = track?.props;
95
+
96
+ const trackDefaultProps =
97
+ (CAPTION_STYLE[tProps?.capStyle ?? ""] || {}).word || {};
98
+
99
+ for (const element of track.elements) {
100
+ const eProps = element.props;
101
+ const rectStyle =
102
+ (CAPTION_STYLE[eProps?.capStyle ?? tProps?.capStyle ?? ""] || {}).rect ||
103
+ {};
104
+ // Cast alignItems/justifyContent as any to satisfy RectProps
105
+ const mappedRectStyle = {
106
+ ...rectStyle,
107
+ justifyContent: rectStyle.justifyContent as any,
108
+ alignItems: rectStyle.alignItems as any,
109
+ };
110
+ const phraseProps = {
111
+ ...trackDefaultProps,
112
+ colors: {
113
+ text:
114
+ eProps?.colors?.text ??
115
+ tProps?.colors?.text ??
116
+ DEFAULT_CAPTION_COLORS.text,
117
+ background:
118
+ eProps?.colors?.background ??
119
+ tProps?.colors?.background ??
120
+ DEFAULT_CAPTION_COLORS.background,
121
+ },
122
+ font: {
123
+ family:
124
+ eProps?.font?.family ??
125
+ tProps?.font?.family ??
126
+ DEFAULT_CAPTION_FONT.family,
127
+ size:
128
+ eProps?.font?.size ?? tProps?.font?.size ?? DEFAULT_CAPTION_FONT.size,
129
+ weight:
130
+ eProps?.font?.weight ??
131
+ tProps?.font?.weight ??
132
+ DEFAULT_CAPTION_FONT.weight,
133
+ },
134
+ fill:
135
+ eProps?.colors?.text ??
136
+ tProps?.colors?.text ??
137
+ DEFAULT_CAPTION_COLORS.text,
138
+ bgColor:
139
+ eProps?.colors?.background ??
140
+ tProps?.colors?.background ??
141
+ DEFAULT_CAPTION_COLORS.background,
142
+ bgOpacity: eProps?.bgOpacity ?? tProps?.bgOpacity ?? 1,
143
+ ...(tProps?.captionProps || {}),
144
+ };
145
+
146
+ yield* waitFor(element?.s - prevTime);
147
+ const phraseRef = createRef<any>();
148
+ captionTrackRef().add(
149
+ <Rect
150
+ ref={phraseRef}
151
+ key={element.id}
152
+ {...mappedRectStyle}
153
+ x={eProps?.x ?? tProps?.x}
154
+ y={eProps?.y ?? tProps?.y}
155
+ layout
156
+ />
157
+ );
158
+ if (tProps?.capStyle === "word_by_word_with_bg") {
159
+ const _color = new Color({...hexToRGB(phraseProps.bgColor), a: phraseProps?.bgOpacity ?? 1});
160
+ phraseRef().fill(_color);
161
+ }
162
+ yield* elementController.get("caption")?.create({
163
+ containerRef: phraseRef,
164
+ caption: {
165
+ ...element,
166
+ t: element.t ?? "",
167
+ capStyle: eProps?.capStyle ?? tProps?.capStyle,
168
+ props: phraseProps,
169
+ },
170
+ view,
171
+ });
172
+ prevTime = element.e;
173
+ yield phraseRef().remove();
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Creates a scene track with specified configuration
179
+ * @param {Object} params - Parameters for scene track creation
180
+ * @param {View2D} params.view - The 2D view to render the scene in
181
+ * @param {SceneTrack} params.track - Scene track configuration
182
+ * @returns {Generator} Generator function for scene track animation
183
+ */
184
+ export function* makeSceneTrack({
185
+ view,
186
+ track,
187
+ }: {
188
+ view: View2D;
189
+ track: VisualizerTrack;
190
+ }) {
191
+ const frameRef = createRef<any>();
192
+ view.add(<Layout size={"100%"} ref={frameRef} layout />);
193
+ for (const sceneElement of track.elements || []) {
194
+ yield* elementController.get("scene")?.create({
195
+ containerRef: frameRef,
196
+ element: sceneElement,
197
+ view,
198
+ });
199
+ }
200
+ yield frameRef().remove();
201
+ }
202
+
203
+ /**
204
+ * Creates an element track with specified configuration
205
+ * @param {Object} params - Parameters for element track creation
206
+ * @param {View2D} params.view - The 2D view to render the element in
207
+ * @param {ElementTrack} params.track - Element track configuration
208
+ * @returns {Generator} Generator function for element track animation
209
+ */
210
+ export function* makeElementTrack({
211
+ view,
212
+ track,
213
+ }: {
214
+ view: View2D;
215
+ track: VisualizerTrack;
216
+ }) {
217
+ const elementTrackRef = createRef<any>();
218
+ view.add(<Layout size={"100%"} ref={elementTrackRef} />);
219
+
220
+ const sequence: ThreadGenerator[] = [];
221
+ try {
222
+ for (const element of track.elements) {
223
+ sequence.push(
224
+ elementController.get(element.type)?.create({
225
+ containerRef: elementTrackRef,
226
+ element,
227
+ view,
228
+ })
229
+ );
230
+ }
231
+ } catch (error) {
232
+ logger("Error creating element track", error);
233
+ }
234
+
235
+ yield* all(...sequence);
236
+ yield elementTrackRef().remove();
237
+ }
@@ -0,0 +1,39 @@
1
+ import { BlurAnimation } from "../animations/blur";
2
+ import { BreatheAnimation } from "../animations/breathe";
3
+ import { FadeAnimation } from "../animations/fade";
4
+ import { PhotoRiseAnimation } from "../animations/photo-rise";
5
+ import { PhotoZoomAnimation } from "../animations/photo-zoom";
6
+ import { RiseAnimation } from "../animations/rise";
7
+ import { SuccessionAnimation } from "../animations/succession";
8
+ import { Animation } from "../helpers/types";
9
+
10
+ export class AnimationController {
11
+ private animations: Map<string, Animation> = new Map();
12
+
13
+ register(animation: Animation) {
14
+ this.animations.set(animation.name, animation);
15
+ }
16
+
17
+ get(name: string): Animation | undefined {
18
+ return this.animations.get(name);
19
+ }
20
+
21
+ list(): string[] {
22
+ return Array.from(this.animations.keys());
23
+ }
24
+ }
25
+
26
+ export const registerAnimations = () => {
27
+ animationController.register(FadeAnimation);
28
+ animationController.register(RiseAnimation);
29
+ animationController.register(BreatheAnimation);
30
+ animationController.register(SuccessionAnimation);
31
+ animationController.register(BlurAnimation);
32
+ animationController.register(PhotoZoomAnimation);
33
+ animationController.register(PhotoRiseAnimation);
34
+ }
35
+
36
+ const animationController = new AnimationController();
37
+ registerAnimations();
38
+
39
+ export default animationController;
@@ -0,0 +1,43 @@
1
+ import { AudioElement } from "../elements/audio.element";
2
+ import { CaptionElement } from "../elements/caption.element";
3
+ import { CircleElement } from "../elements/circle.element";
4
+ import { IconElement } from "../elements/icon.element";
5
+ import { ImageElement } from "../elements/image.element";
6
+ import { RectElement } from "../elements/rect.element";
7
+ import { SceneElement } from "../elements/scene.element";
8
+ import { TextElement } from "../elements/text.element";
9
+ import { VideoElement } from "../elements/video.element";
10
+ import { Element } from "../helpers/types";
11
+
12
+ export class ElementController {
13
+ private elements: Map<string, Element> = new Map();
14
+
15
+ register(element: Element) {
16
+ this.elements.set(element.name, element);
17
+ }
18
+
19
+ get(name: string): Element | undefined {
20
+ return this.elements.get(name);
21
+ }
22
+
23
+ list(): string[] {
24
+ return Array.from(this.elements.keys());
25
+ }
26
+ }
27
+
28
+ export const registerElements = () => {
29
+ elementController.register(VideoElement);
30
+ elementController.register(CaptionElement);
31
+ elementController.register(SceneElement);
32
+ elementController.register(ImageElement);
33
+ elementController.register(TextElement);
34
+ elementController.register(AudioElement);
35
+ elementController.register(CircleElement);
36
+ elementController.register(IconElement);
37
+ elementController.register(RectElement);
38
+ }
39
+
40
+ const elementController = new ElementController();
41
+ registerElements();
42
+
43
+ export default elementController;
@@ -0,0 +1,30 @@
1
+
2
+ import { CircleFrameEffect } from "../frame-effects/circle.frame";
3
+ import { RectFrameEffect } from "../frame-effects/rect.frame";
4
+ import { FrameEffectPlugin } from "../helpers/types";
5
+
6
+ export class FrameEffectController {
7
+ private frameEffects: Map<string, FrameEffectPlugin> = new Map();
8
+
9
+ register(frameEffect: FrameEffectPlugin) {
10
+ this.frameEffects.set(frameEffect.name, frameEffect);
11
+ }
12
+
13
+ get(name: string): FrameEffectPlugin | undefined {
14
+ return this.frameEffects.get(name);
15
+ }
16
+
17
+ list(): string[] {
18
+ return Array.from(this.frameEffects.keys());
19
+ }
20
+ }
21
+
22
+ export const registerFrameEffects = () => {
23
+ frameEffectController.register(CircleFrameEffect);
24
+ frameEffectController.register(RectFrameEffect);
25
+ }
26
+
27
+ const frameEffectController = new FrameEffectController();
28
+ registerFrameEffects();
29
+
30
+ export default frameEffectController;
@@ -0,0 +1,33 @@
1
+ import { ElasticEffect } from "../text-effects/elastic";
2
+ import { EraseEffect } from "../text-effects/erase";
3
+ import { StreamWordEffect } from "../text-effects/stream-word";
4
+ import { TypewriterEffect } from "../text-effects/typewriter";
5
+ import { TextEffect } from "../helpers/types";
6
+
7
+ export class TextEffectController {
8
+ private effects: Map<string, TextEffect> = new Map();
9
+
10
+ register(effect: TextEffect) {
11
+ this.effects.set(effect.name, effect);
12
+ }
13
+
14
+ get(name: string): TextEffect | undefined {
15
+ return this.effects.get(name);
16
+ }
17
+
18
+ list(): string[] {
19
+ return Array.from(this.effects.keys());
20
+ }
21
+ }
22
+
23
+ export const registerTextEffects = () => {
24
+ textEffectController.register(TypewriterEffect);
25
+ textEffectController.register(StreamWordEffect);
26
+ textEffectController.register(EraseEffect);
27
+ textEffectController.register(ElasticEffect);
28
+ }
29
+
30
+ const textEffectController = new TextEffectController();
31
+ registerTextEffects();
32
+
33
+ export default textEffectController;
@@ -0,0 +1,17 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { createRef, waitFor } from "@twick/core";
3
+ import { Audio } from "@twick/2d";
4
+
5
+ export const AudioElement = {
6
+ name: "audio",
7
+ *create({ containerRef, element, view }: ElementParams) {
8
+ const elementRef = createRef<any>();
9
+ yield* waitFor(element?.s);
10
+ yield containerRef().add(
11
+ <Audio ref={elementRef} key={element.id} play={true} {...element.props} />
12
+ );
13
+ yield* waitFor(Math.max(0, element.e - element.s));
14
+ yield elementRef().play(false);
15
+ yield elementRef().remove();
16
+ },
17
+ };
@@ -0,0 +1,87 @@
1
+ import { CaptionProps, ElementParams } from "../helpers/types";
2
+ import { Color, createRef, Reference, waitFor } from "@twick/core";
3
+ import { Rect, Txt } from "@twick/2d";
4
+ import { splitPhraseTiming } from "../helpers/caption.utils";
5
+ import { TRANSPARENT_COLOR } from "../helpers/constants";
6
+ import { hexToRGB } from "../helpers/utils";
7
+
8
+ export const CaptionElement = {
9
+ name: "caption",
10
+ *create({ containerRef, caption }: ElementParams) {
11
+ const words = splitPhraseTiming(caption);
12
+ let phraseStart = 0;
13
+ if (words?.length) {
14
+ phraseStart = words[0].s;
15
+ }
16
+ let wordsState: {
17
+ refs: Array<{ bgRef?: Reference<any>; textRef: Reference<any> }>;
18
+ props: CaptionProps[];
19
+ idx: number;
20
+ prevTime: number;
21
+ } = {
22
+ refs: [],
23
+ props: [],
24
+ idx: 0,
25
+ prevTime: phraseStart,
26
+ };
27
+ for (const word of words) {
28
+ wordsState.props.push(caption.props);
29
+ const textRef = createRef<Txt>();
30
+ const captionProps = caption.props;
31
+ containerRef().add(
32
+ <Txt ref={textRef} {...captionProps} text={word.t} opacity={0} />
33
+ );
34
+ if (caption.capStyle == "highlight_bg") {
35
+ const bgContainerRef = createRef();
36
+ const childTextRef = createRef();
37
+ const _color = new Color({...hexToRGB(captionProps.colors.background), a: captionProps?.bgOpacity ?? 1});
38
+ containerRef().add(
39
+ <Rect
40
+ ref={bgContainerRef}
41
+ fill={_color}
42
+ width={textRef().width() + (captionProps.bgOffsetWidth ?? 30)}
43
+ height={textRef().height() + (captionProps.bgOffsetHeight ?? 10)}
44
+ margin={captionProps.bgMargin ?? [0, -5]}
45
+ radius={captionProps.bgRadius ?? 10}
46
+ padding={captionProps.bgPadding ?? [0, 15]}
47
+ opacity={0}
48
+ alignItems={"center"}
49
+ justifyContent={"center"}
50
+ layout
51
+ >
52
+ <Txt ref={childTextRef} {...captionProps} text={word.t} />
53
+ </Rect>
54
+ );
55
+ textRef().remove();
56
+ wordsState.refs.push({
57
+ bgRef: bgContainerRef,
58
+ textRef: childTextRef,
59
+ });
60
+ } else {
61
+ wordsState.refs.push({
62
+ textRef: textRef,
63
+ });
64
+ }
65
+ wordsState.prevTime = word.e;
66
+ wordsState.idx = wordsState.idx + 1;
67
+ }
68
+
69
+ wordsState.prevTime = phraseStart;
70
+ wordsState.idx = 0;
71
+
72
+ for (const word of words) {
73
+ if (caption.capStyle == "highlight_bg") {
74
+ yield* wordsState.refs[wordsState.idx]?.bgRef?.().opacity(1, 0);
75
+ yield* waitFor(Math.max(0, word.e - word.s));
76
+ yield* wordsState.refs[wordsState.idx]
77
+ ?.bgRef?.()
78
+ .fill(TRANSPARENT_COLOR, 0);
79
+ } else {
80
+ yield* wordsState.refs[wordsState.idx]?.textRef?.().opacity(1, 0);
81
+ yield* waitFor(Math.max(0, word.e - word.s));
82
+ }
83
+ wordsState.prevTime = word.e;
84
+ wordsState.idx = wordsState.idx + 1;
85
+ }
86
+ },
87
+ };
@@ -0,0 +1,20 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { all, createRef, waitFor } from "@twick/core";
3
+ import { Circle } from "@twick/2d";
4
+ import { addAnimation } from "../helpers/element.utils";
5
+
6
+ export const CircleElement = {
7
+ name: "circle",
8
+ *create({ containerRef, element, view }: ElementParams) {
9
+ const elementRef = createRef<any>();
10
+ yield* waitFor(element?.s);
11
+ yield containerRef().add(
12
+ <Circle ref={elementRef} key={element.id} {...element.props} />
13
+ );
14
+ yield* all(
15
+ addAnimation({ elementRef: elementRef, element: element, view }),
16
+ waitFor(Math.max(0, element.e - element.s))
17
+ );
18
+ yield elementRef().remove();
19
+ },
20
+ };
@@ -0,0 +1,20 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { all, createRef, waitFor } from "@twick/core";
3
+ import { Icon } from "@twick/2d";
4
+ import { addAnimation } from "../helpers/element.utils";
5
+
6
+ export const IconElement = {
7
+ name: "icon",
8
+ *create({ containerRef, element, view }: ElementParams) {
9
+ const elementRef = createRef<any>();
10
+ yield* waitFor(element?.s);
11
+ yield containerRef().add(
12
+ <Icon ref={elementRef} key={element.id} {...element.props} />
13
+ );
14
+ yield* all(
15
+ addAnimation({ elementRef: elementRef, element: element, view }),
16
+ waitFor(Math.max(0, element.e - element.s))
17
+ );
18
+ yield elementRef().remove();
19
+ },
20
+ };
@@ -0,0 +1,53 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { all, createRef, waitFor } from "@twick/core";
3
+ import { Img, Rect } from "@twick/2d";
4
+ import { addAnimation, addFrameEffect, fitElement } from "../helpers/element.utils";
5
+ import { applyColorFilter } from "../helpers/filters";
6
+
7
+ export const ImageElement = {
8
+ name: "image",
9
+ *create({ containerRef, element, view }: ElementParams) {
10
+ yield* waitFor(element?.s);
11
+ const frameContainerRef = createRef<any>();
12
+ const frameElementRef = createRef<any>();
13
+
14
+ yield containerRef().add(
15
+ <Rect ref={frameContainerRef} key={element.id} {...element.frame}>
16
+ <Img
17
+ ref={frameElementRef}
18
+ key={`child-${element.id}`}
19
+ {...element.props}
20
+ />
21
+ </Rect>
22
+ );
23
+ if (frameContainerRef()) {
24
+ yield fitElement({
25
+ elementRef: frameElementRef,
26
+ containerSize: frameContainerRef().size(),
27
+ elementSize: frameElementRef().size(),
28
+ objectFit: element.objectFit,
29
+ });
30
+
31
+ if (element?.props?.mediaFilter) {
32
+ applyColorFilter(frameElementRef, element.props.mediaFilter);
33
+ }
34
+
35
+ yield* all(
36
+ addAnimation({
37
+ elementRef: frameElementRef,
38
+ containerRef: frameContainerRef,
39
+ element: element,
40
+ view,
41
+ }),
42
+ addFrameEffect({
43
+ containerRef: frameContainerRef,
44
+ elementRef: frameElementRef,
45
+ element,
46
+ }),
47
+ waitFor(Math.max(0, element.e - element.s))
48
+ );
49
+ yield frameElementRef().remove();
50
+ yield frameContainerRef().remove();
51
+ }
52
+ },
53
+ };
@@ -0,0 +1,22 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { all, createRef, waitFor } from "@twick/core";
3
+ import { Rect } from "@twick/2d";
4
+ import { addAnimation } from "../helpers/element.utils";
5
+ import { logger } from "../helpers/log.utils";
6
+
7
+ export const RectElement = {
8
+ name: "rect",
9
+ *create({ containerRef, element, view }: ElementParams) {
10
+ const elementRef = createRef<any>();
11
+ yield* waitFor(element?.s);
12
+ logger(`RectElement: ${JSON.stringify(element)}`);
13
+ yield containerRef().add(
14
+ <Rect ref={elementRef} key={element.id} {...element.props}/>
15
+ );
16
+ yield* all(
17
+ addAnimation({ elementRef: elementRef, element: element, view }),
18
+ waitFor(Math.max(0, element.e - element.s))
19
+ );
20
+ yield elementRef().remove();
21
+ },
22
+ };
@@ -0,0 +1,29 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { createRef, waitFor } from "@twick/core";
3
+ import { Rect } from "@twick/2d";
4
+ import { DEFAULT_BACKGROUND_COLOR, ELEMENT_TYPES } from "../helpers/constants";
5
+ import { ImageElement } from "./image.element";
6
+ import { VideoElement } from "./video.element";
7
+ import { logger } from "../helpers/log.utils";
8
+
9
+ export const SceneElement = {
10
+ name: "scene",
11
+ *create({ containerRef, element, view }: ElementParams) {
12
+ yield* waitFor(element?.s);
13
+ const mediaContainerRef = createRef<any>();
14
+ logger(`SceneElement: ${JSON.stringify(element)}`);
15
+ yield containerRef().add(
16
+ <Rect
17
+ ref={mediaContainerRef}
18
+ fill={element.backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
19
+ size={"100%"}
20
+ />
21
+ );
22
+ if (element.type === ELEMENT_TYPES.IMAGE) {
23
+ yield* ImageElement.create({ containerRef, element, view });
24
+ } else if (element.type === ELEMENT_TYPES.VIDEO) {
25
+ yield* VideoElement.create({ containerRef, element, view });
26
+ }
27
+ yield mediaContainerRef().remove();
28
+ },
29
+ };
@@ -0,0 +1,28 @@
1
+ import { ElementParams } from "../helpers/types";
2
+ import { all, createRef, waitFor } from "@twick/core";
3
+ import { Txt } from "@twick/2d";
4
+ import { addAnimation, addTextEffect } from "../helpers/element.utils";
5
+
6
+ export const TextElement = {
7
+ name: "text",
8
+ *create({ containerRef, element, view }: ElementParams) {
9
+ const elementRef = createRef<any>();
10
+
11
+ yield* waitFor(element?.s);
12
+ yield containerRef().add(
13
+ <Txt
14
+ ref={elementRef}
15
+ key={element.id}
16
+ text={element.t}
17
+ {...element.props}
18
+ />
19
+ );
20
+ yield* all(
21
+ addAnimation({ elementRef: elementRef, element: element, view }),
22
+ addTextEffect({ elementRef: elementRef, element: element }),
23
+ waitFor(Math.max(0, element.e - element.s))
24
+ );
25
+ yield elementRef().remove();
26
+ }
27
+ }
28
+