@twick/visualizer 0.0.1 → 0.14.0
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/.turbo/turbo-build.log +19 -0
- package/.turbo/turbo-docs.log +7 -0
- package/LICENSE +197 -0
- package/README.md +1 -1
- package/dist/mp4.wasm +0 -0
- package/dist/project.css +1 -0
- package/dist/project.js +145 -0
- package/docs/.nojekyll +1 -0
- package/docs/README.md +13 -0
- package/docs/interfaces/Animation.md +47 -0
- package/docs/interfaces/Element.md +47 -0
- package/docs/interfaces/FrameEffectPlugin.md +47 -0
- package/docs/interfaces/TextEffect.md +47 -0
- package/docs/modules.md +535 -0
- package/package.json +34 -31
- 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 +2 -4
- package/src/components/track.tsx +232 -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 +55 -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 +56 -0
- package/src/frame-effects/circle.frame.tsx +103 -0
- package/src/frame-effects/rect.frame.tsx +103 -0
- package/src/helpers/caption.utils.ts +4 -14
- package/src/helpers/constants.ts +1 -1
- package/src/helpers/element.utils.ts +222 -68
- package/src/helpers/filters.ts +1 -1
- package/src/helpers/log.utils.ts +0 -3
- package/src/helpers/timing.utils.ts +2 -21
- package/src/helpers/types.ts +103 -8
- package/src/helpers/utils.ts +20 -0
- package/src/index.ts +4 -2
- package/src/live.tsx +1 -1
- package/src/project.ts +1 -1
- package/src/sample.ts +16 -218
- 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 +27 -27
- package/tsconfig.json +3 -2
- package/vite.config.ts +1 -1
- package/src/components/animation.tsx +0 -7
- package/src/components/element.tsx +0 -344
- package/src/components/timeline.tsx +0 -225
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { waitFor } from "@twick/core";
|
|
2
|
+
import { TextEffectParams } from "../helpers/types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* TypewriterEffect animates text appearing one character at a time,
|
|
6
|
+
* mimicking the behavior of a classic typewriter.
|
|
7
|
+
*
|
|
8
|
+
* Behavior:
|
|
9
|
+
* - Optionally waits for a delay before starting.
|
|
10
|
+
* - Clears the text initially and preserves the element's original size.
|
|
11
|
+
* - Reveals one character at a time at a consistent interval.
|
|
12
|
+
*
|
|
13
|
+
* @param elementRef - Reference to the text element to animate.
|
|
14
|
+
* @param duration - Total duration of the animation.
|
|
15
|
+
* @param delay - Optional delay before starting.
|
|
16
|
+
* @param bufferTime - Time reserved at the end of animation (default: 0.1).
|
|
17
|
+
*/
|
|
18
|
+
export const TypewriterEffect = {
|
|
19
|
+
name: "typewriter",
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generator function controlling the character-by-character typing animation.
|
|
23
|
+
*/
|
|
24
|
+
*run({
|
|
25
|
+
elementRef,
|
|
26
|
+
duration,
|
|
27
|
+
delay,
|
|
28
|
+
bufferTime = 0.1,
|
|
29
|
+
}: TextEffectParams) {
|
|
30
|
+
// Retrieve the full text content
|
|
31
|
+
const fullText = elementRef().text();
|
|
32
|
+
|
|
33
|
+
// Store the element's size to prevent resizing during animation
|
|
34
|
+
const size = elementRef().size();
|
|
35
|
+
|
|
36
|
+
// Clear the text and set fixed size
|
|
37
|
+
elementRef().setText("");
|
|
38
|
+
elementRef().size(size);
|
|
39
|
+
|
|
40
|
+
// Align text to the left for consistent typing effect
|
|
41
|
+
elementRef().textAlign("left");
|
|
42
|
+
|
|
43
|
+
// Wait for an optional initial delay
|
|
44
|
+
if (delay) {
|
|
45
|
+
yield* waitFor(delay);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let timeInterval =(duration - bufferTime) / fullText.length;
|
|
49
|
+
|
|
50
|
+
// Wait briefly before starting typing
|
|
51
|
+
yield* waitFor(timeInterval);
|
|
52
|
+
|
|
53
|
+
// Reveal each character one by one
|
|
54
|
+
for (let i = 0; i < fullText.length; i++) {
|
|
55
|
+
yield* waitFor(timeInterval);
|
|
56
|
+
elementRef().setText(fullText.substring(0, i + 1));
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
};
|
package/src/visualizer.tsx
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import "./global.css";
|
|
7
|
-
import { Rect, makeScene2D, View2D } from "@
|
|
8
|
-
import { all, useScene } from "@
|
|
7
|
+
import { Rect, makeScene2D, View2D } from "@twick/2d";
|
|
8
|
+
import { all, useScene } from "@twick/core";
|
|
9
9
|
|
|
10
|
-
import { DEFAULT_BACKGROUND_COLOR,
|
|
10
|
+
import { DEFAULT_BACKGROUND_COLOR, TRACK_TYPES } from "./helpers/constants";
|
|
11
11
|
import { VideoInput } from "./helpers/types";
|
|
12
12
|
import { logger } from "./helpers/log.utils";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from "./components/
|
|
14
|
+
makeAudioTrack,
|
|
15
|
+
makeCaptionTrack,
|
|
16
|
+
makeElementTrack,
|
|
17
|
+
makeSceneTrack,
|
|
18
|
+
makeVideoTrack,
|
|
19
|
+
} from "./components/track";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Creates and configures the main scene for video visualization
|
|
@@ -29,7 +29,7 @@ export const scene = makeScene2D("scene", function* (view: View2D) {
|
|
|
29
29
|
const input = useScene().variables.get("input", null)() as VideoInput | null;
|
|
30
30
|
|
|
31
31
|
if (input) {
|
|
32
|
-
logger("Scene updated");
|
|
32
|
+
logger("Scene updated", input);
|
|
33
33
|
|
|
34
34
|
// Add background rectangle with specified or default color
|
|
35
35
|
yield view.add(
|
|
@@ -39,39 +39,39 @@ export const scene = makeScene2D("scene", function* (view: View2D) {
|
|
|
39
39
|
/>
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
// Process
|
|
43
|
-
if (input.
|
|
42
|
+
// Process track elements if present
|
|
43
|
+
if (input.tracks) {
|
|
44
44
|
const movie = [];
|
|
45
45
|
let index = 1;
|
|
46
46
|
|
|
47
|
-
// Iterate through each
|
|
48
|
-
for (const
|
|
49
|
-
switch (
|
|
50
|
-
case
|
|
51
|
-
movie.push(
|
|
47
|
+
// Iterate through each track element and create appropriate visualization
|
|
48
|
+
for (const track of input.tracks) {
|
|
49
|
+
switch (track.type) {
|
|
50
|
+
case TRACK_TYPES.VIDEO:
|
|
51
|
+
movie.push(makeVideoTrack({ view, track }));
|
|
52
52
|
break;
|
|
53
|
-
case
|
|
54
|
-
movie.push(
|
|
53
|
+
case TRACK_TYPES.AUDIO:
|
|
54
|
+
movie.push(makeAudioTrack({ view, track }));
|
|
55
55
|
break;
|
|
56
|
-
case
|
|
56
|
+
case TRACK_TYPES.CAPTION:
|
|
57
57
|
movie.push(
|
|
58
|
-
|
|
58
|
+
makeCaptionTrack({
|
|
59
59
|
view,
|
|
60
|
-
|
|
60
|
+
track,
|
|
61
61
|
})
|
|
62
62
|
);
|
|
63
63
|
break;
|
|
64
|
-
case
|
|
65
|
-
movie.push(
|
|
64
|
+
case TRACK_TYPES.SCENE:
|
|
65
|
+
movie.push(makeSceneTrack({ view, track }));
|
|
66
66
|
break;
|
|
67
|
-
case
|
|
68
|
-
movie.push(
|
|
67
|
+
case TRACK_TYPES.ELEMENT:
|
|
68
|
+
movie.push(makeElementTrack({ view, track }));
|
|
69
69
|
break;
|
|
70
70
|
}
|
|
71
71
|
index++;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// Execute all
|
|
74
|
+
// Execute all track animations in parallel
|
|
75
75
|
yield* all(...movie);
|
|
76
76
|
}
|
|
77
77
|
}
|
package/tsconfig.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "@
|
|
2
|
+
"extends": "@twick/2d/tsconfig.project.json",
|
|
3
3
|
"include": ["src"],
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
"noEmit": false,
|
|
6
6
|
"outDir": "dist",
|
|
7
7
|
"module": "CommonJS",
|
|
8
|
-
"skipLibCheck": true
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"jsx": "react-jsx"
|
|
9
10
|
}
|
|
10
11
|
}
|
package/vite.config.ts
CHANGED
|
@@ -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
|
-
}
|