@remotion/transitions 4.0.495 → 4.0.497
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/dist/TransitionSeries.d.ts +2 -2
- package/dist/TransitionSeries.js +1 -0
- package/dist/esm/book-flip.mjs +96 -24
- package/dist/esm/cross-zoom.mjs +96 -24
- package/dist/esm/crosswarp.mjs +96 -24
- package/dist/esm/dissolve.mjs +96 -24
- package/dist/esm/dreamy-zoom.mjs +96 -24
- package/dist/esm/film-burn.mjs +96 -24
- package/dist/esm/index.mjs +106 -33
- package/dist/esm/linear-blur.mjs +96 -24
- package/dist/esm/ripple.mjs +96 -24
- package/dist/esm/swap.mjs +96 -24
- package/dist/esm/zoom-blur.mjs +96 -24
- package/dist/esm/zoom-in-out.mjs +96 -24
- package/dist/html-in-canvas-presentation.d.ts +2 -2
- package/dist/html-in-canvas-presentation.js +81 -16
- package/dist/presentations/book-flip.js +3 -2
- package/dist/presentations/cross-zoom.js +3 -2
- package/dist/presentations/crosswarp.js +3 -2
- package/dist/presentations/dissolve.js +3 -2
- package/dist/presentations/dreamy-zoom.js +3 -2
- package/dist/presentations/film-burn.js +3 -2
- package/dist/presentations/linear-blur.js +3 -2
- package/dist/presentations/ripple.js +3 -2
- package/dist/presentations/swap.js +3 -2
- package/dist/presentations/upload-element-image.d.ts +1 -0
- package/dist/presentations/upload-element-image.js +7 -0
- package/dist/presentations/zoom-blur.js +3 -2
- package/dist/presentations/zoom-in-out.js +3 -2
- package/dist/types.d.ts +1 -1
- package/package.json +8 -8
package/dist/esm/dissolve.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Internals,
|
|
8
8
|
useDelayRender
|
|
9
9
|
} from "remotion";
|
|
10
|
-
import { jsx } from "react/jsx-runtime";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
var HtmlInCanvasPresentation = ({
|
|
12
12
|
children,
|
|
13
13
|
onElementImage,
|
|
@@ -23,6 +23,7 @@ var HtmlInCanvasPresentation = ({
|
|
|
23
23
|
throw new Error(HTML_IN_CANVAS_UNSUPPORTED_MESSAGE);
|
|
24
24
|
}
|
|
25
25
|
const canvasRef = useRef(null);
|
|
26
|
+
const outputCanvasRef = useRef(null);
|
|
26
27
|
const canvasSubtreeStyle = useMemo(() => {
|
|
27
28
|
return {
|
|
28
29
|
width: "100%",
|
|
@@ -34,7 +35,21 @@ var HtmlInCanvasPresentation = ({
|
|
|
34
35
|
bottom: 0
|
|
35
36
|
};
|
|
36
37
|
}, []);
|
|
37
|
-
const
|
|
38
|
+
const outputCanvasStyle = useMemo(() => {
|
|
39
|
+
return {
|
|
40
|
+
width: "100%",
|
|
41
|
+
height: "100%",
|
|
42
|
+
position: "absolute",
|
|
43
|
+
top: 0,
|
|
44
|
+
left: 0,
|
|
45
|
+
right: 0,
|
|
46
|
+
bottom: 0,
|
|
47
|
+
pointerEvents: "none"
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
const captureCanvasRef = useRef(null);
|
|
51
|
+
const captureContextRef = useRef(null);
|
|
52
|
+
const [shaderCanvas] = useState(() => new OffscreenCanvas(1, 1));
|
|
38
53
|
const passedPropsRef = useRef(passedProps);
|
|
39
54
|
passedPropsRef.current = passedProps;
|
|
40
55
|
const memoizedEffects = Internals.useMemoizedEffects({
|
|
@@ -43,33 +58,58 @@ var HtmlInCanvasPresentation = ({
|
|
|
43
58
|
});
|
|
44
59
|
const effectsRef = useRef(memoizedEffects);
|
|
45
60
|
effectsRef.current = memoizedEffects;
|
|
46
|
-
const [instance] = useState(() => shader(
|
|
61
|
+
const [instance] = useState(() => shader(shaderCanvas));
|
|
47
62
|
useLayoutEffect(() => {
|
|
63
|
+
const canvas = canvasRef.current;
|
|
64
|
+
if (!canvas) {
|
|
65
|
+
return () => {
|
|
66
|
+
instance.cleanup();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const captureCanvas = canvas.transferControlToOffscreen();
|
|
70
|
+
const captureContext = captureCanvas.getContext("2d");
|
|
71
|
+
if (!captureContext) {
|
|
72
|
+
throw new Error("Failed to create capture canvas context");
|
|
73
|
+
}
|
|
74
|
+
captureCanvasRef.current = captureCanvas;
|
|
75
|
+
captureContextRef.current = captureContext;
|
|
48
76
|
return () => {
|
|
49
77
|
instance.cleanup();
|
|
78
|
+
captureCanvasRef.current = null;
|
|
79
|
+
captureContextRef.current = null;
|
|
50
80
|
};
|
|
51
|
-
}, [
|
|
81
|
+
}, [instance]);
|
|
52
82
|
const chainState = Internals.useEffectChainState();
|
|
53
83
|
const { delayRender, continueRender } = useDelayRender();
|
|
54
84
|
const draw = useCallback(async (prevImage, nextImage, progress) => {
|
|
55
|
-
|
|
85
|
+
const outputCanvas = outputCanvasRef.current;
|
|
86
|
+
if (!outputCanvas) {
|
|
56
87
|
throw new Error("Canvas not found");
|
|
57
88
|
}
|
|
58
89
|
const handle = delayRender("onPaint");
|
|
90
|
+
const clearOutput = () => {
|
|
91
|
+
const context = outputCanvas.getContext("2d");
|
|
92
|
+
if (!context) {
|
|
93
|
+
throw new Error("Failed to create output canvas context");
|
|
94
|
+
}
|
|
95
|
+
context.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
|
|
96
|
+
};
|
|
59
97
|
if (!prevImage && !nextImage) {
|
|
60
|
-
continueRender(handle);
|
|
61
98
|
instance.clear();
|
|
99
|
+
clearOutput();
|
|
100
|
+
continueRender(handle);
|
|
62
101
|
return;
|
|
63
102
|
}
|
|
64
103
|
const width = prevImage?.width ?? nextImage?.width ?? 0;
|
|
65
104
|
const height = prevImage?.height ?? nextImage?.height ?? 0;
|
|
66
105
|
if (width === 0 || height === 0) {
|
|
67
|
-
continueRender(handle);
|
|
68
106
|
instance.clear();
|
|
107
|
+
clearOutput();
|
|
108
|
+
continueRender(handle);
|
|
69
109
|
return;
|
|
70
110
|
}
|
|
71
|
-
|
|
72
|
-
|
|
111
|
+
shaderCanvas.width = width;
|
|
112
|
+
shaderCanvas.height = height;
|
|
73
113
|
instance.draw({
|
|
74
114
|
prevImage,
|
|
75
115
|
nextImage,
|
|
@@ -80,14 +120,14 @@ var HtmlInCanvasPresentation = ({
|
|
|
80
120
|
});
|
|
81
121
|
await Internals.runEffectChain({
|
|
82
122
|
state: chainState.get(width, height),
|
|
83
|
-
source:
|
|
123
|
+
source: shaderCanvas,
|
|
84
124
|
effects: effectsRef.current ?? [],
|
|
85
125
|
width,
|
|
86
126
|
height,
|
|
87
|
-
output:
|
|
127
|
+
output: outputCanvas
|
|
88
128
|
});
|
|
89
129
|
continueRender(handle);
|
|
90
|
-
}, [chainState,
|
|
130
|
+
}, [chainState, continueRender, delayRender, instance, shaderCanvas]);
|
|
91
131
|
const passThrough = bothEnteringAndExiting && presentationDirection === "exiting";
|
|
92
132
|
useLayoutEffect(() => {
|
|
93
133
|
if (passThrough) {
|
|
@@ -100,11 +140,19 @@ var HtmlInCanvasPresentation = ({
|
|
|
100
140
|
canvas.layoutSubtree = true;
|
|
101
141
|
const onPaint = () => {
|
|
102
142
|
const firstChild = canvas.firstChild;
|
|
103
|
-
|
|
143
|
+
const captureCanvas = captureCanvasRef.current;
|
|
144
|
+
const captureContext = captureContextRef.current;
|
|
145
|
+
if (!firstChild || !captureCanvas || !captureContext) {
|
|
104
146
|
return;
|
|
105
147
|
}
|
|
106
148
|
const elementImage = canvas.captureElementImage(firstChild);
|
|
107
|
-
|
|
149
|
+
try {
|
|
150
|
+
captureContext.reset();
|
|
151
|
+
captureContext.drawElementImage(elementImage, 0, 0);
|
|
152
|
+
} finally {
|
|
153
|
+
elementImage.close();
|
|
154
|
+
}
|
|
155
|
+
onElementImage(captureCanvas, draw);
|
|
108
156
|
};
|
|
109
157
|
canvas.addEventListener("paint", onPaint);
|
|
110
158
|
return () => {
|
|
@@ -138,20 +186,39 @@ var HtmlInCanvasPresentation = ({
|
|
|
138
186
|
return;
|
|
139
187
|
}
|
|
140
188
|
const observer = new ResizeObserver(([entry]) => {
|
|
141
|
-
|
|
142
|
-
|
|
189
|
+
const outputCanvas = outputCanvasRef.current;
|
|
190
|
+
const captureCanvas = captureCanvasRef.current;
|
|
191
|
+
if (!outputCanvas || !captureCanvas) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const width = entry.devicePixelContentBoxSize[0].inlineSize;
|
|
195
|
+
const height = entry.devicePixelContentBoxSize[0].blockSize;
|
|
196
|
+
captureCanvas.width = width;
|
|
197
|
+
captureCanvas.height = height;
|
|
198
|
+
outputCanvas.width = width;
|
|
199
|
+
outputCanvas.height = height;
|
|
200
|
+
canvas.requestPaint?.();
|
|
143
201
|
});
|
|
144
202
|
observer.observe(canvas, { box: "device-pixel-content-box" });
|
|
203
|
+
return () => {
|
|
204
|
+
observer.disconnect();
|
|
205
|
+
};
|
|
145
206
|
}, [passThrough]);
|
|
146
207
|
if (passThrough) {
|
|
147
208
|
return children;
|
|
148
209
|
}
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
children:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
210
|
+
return /* @__PURE__ */ jsxs(AbsoluteFill, {
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx("canvas", {
|
|
213
|
+
ref: canvasRef,
|
|
214
|
+
style: canvasSubtreeStyle,
|
|
215
|
+
children
|
|
216
|
+
}),
|
|
217
|
+
/* @__PURE__ */ jsx("canvas", {
|
|
218
|
+
ref: outputCanvasRef,
|
|
219
|
+
style: outputCanvasStyle
|
|
220
|
+
})
|
|
221
|
+
]
|
|
155
222
|
});
|
|
156
223
|
};
|
|
157
224
|
var makeHtmlInCanvasPresentation = (shader) => {
|
|
@@ -173,6 +240,11 @@ var makeHtmlInCanvasPresentation = (shader) => {
|
|
|
173
240
|
};
|
|
174
241
|
};
|
|
175
242
|
|
|
243
|
+
// src/presentations/upload-element-image.ts
|
|
244
|
+
var uploadElementImage = (gl, elementImage) => {
|
|
245
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elementImage);
|
|
246
|
+
};
|
|
247
|
+
|
|
176
248
|
// src/presentations/dissolve.tsx
|
|
177
249
|
var DEFAULT_LINE_WIDTH = 0.1;
|
|
178
250
|
var DEFAULT_SPREAD_COLOR = "#ff0000";
|
|
@@ -345,13 +417,13 @@ var dissolveShader = (canvas) => {
|
|
|
345
417
|
gl.activeTexture(gl.TEXTURE0);
|
|
346
418
|
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
347
419
|
if (prevImage) {
|
|
348
|
-
|
|
420
|
+
uploadElementImage(gl, prevImage);
|
|
349
421
|
}
|
|
350
422
|
gl.uniform1i(uPrev, 0);
|
|
351
423
|
gl.activeTexture(gl.TEXTURE1);
|
|
352
424
|
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
353
425
|
if (nextImage) {
|
|
354
|
-
|
|
426
|
+
uploadElementImage(gl, nextImage);
|
|
355
427
|
}
|
|
356
428
|
gl.uniform1i(uNext, 1);
|
|
357
429
|
const spread = parseHexColor(spreadColor);
|
package/dist/esm/dreamy-zoom.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Internals,
|
|
8
8
|
useDelayRender
|
|
9
9
|
} from "remotion";
|
|
10
|
-
import { jsx } from "react/jsx-runtime";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
var HtmlInCanvasPresentation = ({
|
|
12
12
|
children,
|
|
13
13
|
onElementImage,
|
|
@@ -23,6 +23,7 @@ var HtmlInCanvasPresentation = ({
|
|
|
23
23
|
throw new Error(HTML_IN_CANVAS_UNSUPPORTED_MESSAGE);
|
|
24
24
|
}
|
|
25
25
|
const canvasRef = useRef(null);
|
|
26
|
+
const outputCanvasRef = useRef(null);
|
|
26
27
|
const canvasSubtreeStyle = useMemo(() => {
|
|
27
28
|
return {
|
|
28
29
|
width: "100%",
|
|
@@ -34,7 +35,21 @@ var HtmlInCanvasPresentation = ({
|
|
|
34
35
|
bottom: 0
|
|
35
36
|
};
|
|
36
37
|
}, []);
|
|
37
|
-
const
|
|
38
|
+
const outputCanvasStyle = useMemo(() => {
|
|
39
|
+
return {
|
|
40
|
+
width: "100%",
|
|
41
|
+
height: "100%",
|
|
42
|
+
position: "absolute",
|
|
43
|
+
top: 0,
|
|
44
|
+
left: 0,
|
|
45
|
+
right: 0,
|
|
46
|
+
bottom: 0,
|
|
47
|
+
pointerEvents: "none"
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
const captureCanvasRef = useRef(null);
|
|
51
|
+
const captureContextRef = useRef(null);
|
|
52
|
+
const [shaderCanvas] = useState(() => new OffscreenCanvas(1, 1));
|
|
38
53
|
const passedPropsRef = useRef(passedProps);
|
|
39
54
|
passedPropsRef.current = passedProps;
|
|
40
55
|
const memoizedEffects = Internals.useMemoizedEffects({
|
|
@@ -43,33 +58,58 @@ var HtmlInCanvasPresentation = ({
|
|
|
43
58
|
});
|
|
44
59
|
const effectsRef = useRef(memoizedEffects);
|
|
45
60
|
effectsRef.current = memoizedEffects;
|
|
46
|
-
const [instance] = useState(() => shader(
|
|
61
|
+
const [instance] = useState(() => shader(shaderCanvas));
|
|
47
62
|
useLayoutEffect(() => {
|
|
63
|
+
const canvas = canvasRef.current;
|
|
64
|
+
if (!canvas) {
|
|
65
|
+
return () => {
|
|
66
|
+
instance.cleanup();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const captureCanvas = canvas.transferControlToOffscreen();
|
|
70
|
+
const captureContext = captureCanvas.getContext("2d");
|
|
71
|
+
if (!captureContext) {
|
|
72
|
+
throw new Error("Failed to create capture canvas context");
|
|
73
|
+
}
|
|
74
|
+
captureCanvasRef.current = captureCanvas;
|
|
75
|
+
captureContextRef.current = captureContext;
|
|
48
76
|
return () => {
|
|
49
77
|
instance.cleanup();
|
|
78
|
+
captureCanvasRef.current = null;
|
|
79
|
+
captureContextRef.current = null;
|
|
50
80
|
};
|
|
51
|
-
}, [
|
|
81
|
+
}, [instance]);
|
|
52
82
|
const chainState = Internals.useEffectChainState();
|
|
53
83
|
const { delayRender, continueRender } = useDelayRender();
|
|
54
84
|
const draw = useCallback(async (prevImage, nextImage, progress) => {
|
|
55
|
-
|
|
85
|
+
const outputCanvas = outputCanvasRef.current;
|
|
86
|
+
if (!outputCanvas) {
|
|
56
87
|
throw new Error("Canvas not found");
|
|
57
88
|
}
|
|
58
89
|
const handle = delayRender("onPaint");
|
|
90
|
+
const clearOutput = () => {
|
|
91
|
+
const context = outputCanvas.getContext("2d");
|
|
92
|
+
if (!context) {
|
|
93
|
+
throw new Error("Failed to create output canvas context");
|
|
94
|
+
}
|
|
95
|
+
context.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
|
|
96
|
+
};
|
|
59
97
|
if (!prevImage && !nextImage) {
|
|
60
|
-
continueRender(handle);
|
|
61
98
|
instance.clear();
|
|
99
|
+
clearOutput();
|
|
100
|
+
continueRender(handle);
|
|
62
101
|
return;
|
|
63
102
|
}
|
|
64
103
|
const width = prevImage?.width ?? nextImage?.width ?? 0;
|
|
65
104
|
const height = prevImage?.height ?? nextImage?.height ?? 0;
|
|
66
105
|
if (width === 0 || height === 0) {
|
|
67
|
-
continueRender(handle);
|
|
68
106
|
instance.clear();
|
|
107
|
+
clearOutput();
|
|
108
|
+
continueRender(handle);
|
|
69
109
|
return;
|
|
70
110
|
}
|
|
71
|
-
|
|
72
|
-
|
|
111
|
+
shaderCanvas.width = width;
|
|
112
|
+
shaderCanvas.height = height;
|
|
73
113
|
instance.draw({
|
|
74
114
|
prevImage,
|
|
75
115
|
nextImage,
|
|
@@ -80,14 +120,14 @@ var HtmlInCanvasPresentation = ({
|
|
|
80
120
|
});
|
|
81
121
|
await Internals.runEffectChain({
|
|
82
122
|
state: chainState.get(width, height),
|
|
83
|
-
source:
|
|
123
|
+
source: shaderCanvas,
|
|
84
124
|
effects: effectsRef.current ?? [],
|
|
85
125
|
width,
|
|
86
126
|
height,
|
|
87
|
-
output:
|
|
127
|
+
output: outputCanvas
|
|
88
128
|
});
|
|
89
129
|
continueRender(handle);
|
|
90
|
-
}, [chainState,
|
|
130
|
+
}, [chainState, continueRender, delayRender, instance, shaderCanvas]);
|
|
91
131
|
const passThrough = bothEnteringAndExiting && presentationDirection === "exiting";
|
|
92
132
|
useLayoutEffect(() => {
|
|
93
133
|
if (passThrough) {
|
|
@@ -100,11 +140,19 @@ var HtmlInCanvasPresentation = ({
|
|
|
100
140
|
canvas.layoutSubtree = true;
|
|
101
141
|
const onPaint = () => {
|
|
102
142
|
const firstChild = canvas.firstChild;
|
|
103
|
-
|
|
143
|
+
const captureCanvas = captureCanvasRef.current;
|
|
144
|
+
const captureContext = captureContextRef.current;
|
|
145
|
+
if (!firstChild || !captureCanvas || !captureContext) {
|
|
104
146
|
return;
|
|
105
147
|
}
|
|
106
148
|
const elementImage = canvas.captureElementImage(firstChild);
|
|
107
|
-
|
|
149
|
+
try {
|
|
150
|
+
captureContext.reset();
|
|
151
|
+
captureContext.drawElementImage(elementImage, 0, 0);
|
|
152
|
+
} finally {
|
|
153
|
+
elementImage.close();
|
|
154
|
+
}
|
|
155
|
+
onElementImage(captureCanvas, draw);
|
|
108
156
|
};
|
|
109
157
|
canvas.addEventListener("paint", onPaint);
|
|
110
158
|
return () => {
|
|
@@ -138,20 +186,39 @@ var HtmlInCanvasPresentation = ({
|
|
|
138
186
|
return;
|
|
139
187
|
}
|
|
140
188
|
const observer = new ResizeObserver(([entry]) => {
|
|
141
|
-
|
|
142
|
-
|
|
189
|
+
const outputCanvas = outputCanvasRef.current;
|
|
190
|
+
const captureCanvas = captureCanvasRef.current;
|
|
191
|
+
if (!outputCanvas || !captureCanvas) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const width = entry.devicePixelContentBoxSize[0].inlineSize;
|
|
195
|
+
const height = entry.devicePixelContentBoxSize[0].blockSize;
|
|
196
|
+
captureCanvas.width = width;
|
|
197
|
+
captureCanvas.height = height;
|
|
198
|
+
outputCanvas.width = width;
|
|
199
|
+
outputCanvas.height = height;
|
|
200
|
+
canvas.requestPaint?.();
|
|
143
201
|
});
|
|
144
202
|
observer.observe(canvas, { box: "device-pixel-content-box" });
|
|
203
|
+
return () => {
|
|
204
|
+
observer.disconnect();
|
|
205
|
+
};
|
|
145
206
|
}, [passThrough]);
|
|
146
207
|
if (passThrough) {
|
|
147
208
|
return children;
|
|
148
209
|
}
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
children:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
210
|
+
return /* @__PURE__ */ jsxs(AbsoluteFill, {
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx("canvas", {
|
|
213
|
+
ref: canvasRef,
|
|
214
|
+
style: canvasSubtreeStyle,
|
|
215
|
+
children
|
|
216
|
+
}),
|
|
217
|
+
/* @__PURE__ */ jsx("canvas", {
|
|
218
|
+
ref: outputCanvasRef,
|
|
219
|
+
style: outputCanvasStyle
|
|
220
|
+
})
|
|
221
|
+
]
|
|
155
222
|
});
|
|
156
223
|
};
|
|
157
224
|
var makeHtmlInCanvasPresentation = (shader) => {
|
|
@@ -173,6 +240,11 @@ var makeHtmlInCanvasPresentation = (shader) => {
|
|
|
173
240
|
};
|
|
174
241
|
};
|
|
175
242
|
|
|
243
|
+
// src/presentations/upload-element-image.ts
|
|
244
|
+
var uploadElementImage = (gl, elementImage) => {
|
|
245
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elementImage);
|
|
246
|
+
};
|
|
247
|
+
|
|
176
248
|
// src/presentations/dreamy-zoom.tsx
|
|
177
249
|
var DEFAULT_ROTATION = 6;
|
|
178
250
|
var DEFAULT_SCALE = 1.2;
|
|
@@ -320,13 +392,13 @@ var dreamyZoomShader = (canvas) => {
|
|
|
320
392
|
gl.activeTexture(gl.TEXTURE0);
|
|
321
393
|
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
322
394
|
if (prevImage) {
|
|
323
|
-
|
|
395
|
+
uploadElementImage(gl, prevImage);
|
|
324
396
|
}
|
|
325
397
|
gl.uniform1i(uPrev, 0);
|
|
326
398
|
gl.activeTexture(gl.TEXTURE1);
|
|
327
399
|
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
328
400
|
if (nextImage) {
|
|
329
|
-
|
|
401
|
+
uploadElementImage(gl, nextImage);
|
|
330
402
|
}
|
|
331
403
|
gl.uniform1i(uNext, 1);
|
|
332
404
|
gl.uniform1f(uTime, effectiveTime);
|
package/dist/esm/film-burn.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Internals,
|
|
8
8
|
useDelayRender
|
|
9
9
|
} from "remotion";
|
|
10
|
-
import { jsx } from "react/jsx-runtime";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
var HtmlInCanvasPresentation = ({
|
|
12
12
|
children,
|
|
13
13
|
onElementImage,
|
|
@@ -23,6 +23,7 @@ var HtmlInCanvasPresentation = ({
|
|
|
23
23
|
throw new Error(HTML_IN_CANVAS_UNSUPPORTED_MESSAGE);
|
|
24
24
|
}
|
|
25
25
|
const canvasRef = useRef(null);
|
|
26
|
+
const outputCanvasRef = useRef(null);
|
|
26
27
|
const canvasSubtreeStyle = useMemo(() => {
|
|
27
28
|
return {
|
|
28
29
|
width: "100%",
|
|
@@ -34,7 +35,21 @@ var HtmlInCanvasPresentation = ({
|
|
|
34
35
|
bottom: 0
|
|
35
36
|
};
|
|
36
37
|
}, []);
|
|
37
|
-
const
|
|
38
|
+
const outputCanvasStyle = useMemo(() => {
|
|
39
|
+
return {
|
|
40
|
+
width: "100%",
|
|
41
|
+
height: "100%",
|
|
42
|
+
position: "absolute",
|
|
43
|
+
top: 0,
|
|
44
|
+
left: 0,
|
|
45
|
+
right: 0,
|
|
46
|
+
bottom: 0,
|
|
47
|
+
pointerEvents: "none"
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
const captureCanvasRef = useRef(null);
|
|
51
|
+
const captureContextRef = useRef(null);
|
|
52
|
+
const [shaderCanvas] = useState(() => new OffscreenCanvas(1, 1));
|
|
38
53
|
const passedPropsRef = useRef(passedProps);
|
|
39
54
|
passedPropsRef.current = passedProps;
|
|
40
55
|
const memoizedEffects = Internals.useMemoizedEffects({
|
|
@@ -43,33 +58,58 @@ var HtmlInCanvasPresentation = ({
|
|
|
43
58
|
});
|
|
44
59
|
const effectsRef = useRef(memoizedEffects);
|
|
45
60
|
effectsRef.current = memoizedEffects;
|
|
46
|
-
const [instance] = useState(() => shader(
|
|
61
|
+
const [instance] = useState(() => shader(shaderCanvas));
|
|
47
62
|
useLayoutEffect(() => {
|
|
63
|
+
const canvas = canvasRef.current;
|
|
64
|
+
if (!canvas) {
|
|
65
|
+
return () => {
|
|
66
|
+
instance.cleanup();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const captureCanvas = canvas.transferControlToOffscreen();
|
|
70
|
+
const captureContext = captureCanvas.getContext("2d");
|
|
71
|
+
if (!captureContext) {
|
|
72
|
+
throw new Error("Failed to create capture canvas context");
|
|
73
|
+
}
|
|
74
|
+
captureCanvasRef.current = captureCanvas;
|
|
75
|
+
captureContextRef.current = captureContext;
|
|
48
76
|
return () => {
|
|
49
77
|
instance.cleanup();
|
|
78
|
+
captureCanvasRef.current = null;
|
|
79
|
+
captureContextRef.current = null;
|
|
50
80
|
};
|
|
51
|
-
}, [
|
|
81
|
+
}, [instance]);
|
|
52
82
|
const chainState = Internals.useEffectChainState();
|
|
53
83
|
const { delayRender, continueRender } = useDelayRender();
|
|
54
84
|
const draw = useCallback(async (prevImage, nextImage, progress) => {
|
|
55
|
-
|
|
85
|
+
const outputCanvas = outputCanvasRef.current;
|
|
86
|
+
if (!outputCanvas) {
|
|
56
87
|
throw new Error("Canvas not found");
|
|
57
88
|
}
|
|
58
89
|
const handle = delayRender("onPaint");
|
|
90
|
+
const clearOutput = () => {
|
|
91
|
+
const context = outputCanvas.getContext("2d");
|
|
92
|
+
if (!context) {
|
|
93
|
+
throw new Error("Failed to create output canvas context");
|
|
94
|
+
}
|
|
95
|
+
context.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
|
|
96
|
+
};
|
|
59
97
|
if (!prevImage && !nextImage) {
|
|
60
|
-
continueRender(handle);
|
|
61
98
|
instance.clear();
|
|
99
|
+
clearOutput();
|
|
100
|
+
continueRender(handle);
|
|
62
101
|
return;
|
|
63
102
|
}
|
|
64
103
|
const width = prevImage?.width ?? nextImage?.width ?? 0;
|
|
65
104
|
const height = prevImage?.height ?? nextImage?.height ?? 0;
|
|
66
105
|
if (width === 0 || height === 0) {
|
|
67
|
-
continueRender(handle);
|
|
68
106
|
instance.clear();
|
|
107
|
+
clearOutput();
|
|
108
|
+
continueRender(handle);
|
|
69
109
|
return;
|
|
70
110
|
}
|
|
71
|
-
|
|
72
|
-
|
|
111
|
+
shaderCanvas.width = width;
|
|
112
|
+
shaderCanvas.height = height;
|
|
73
113
|
instance.draw({
|
|
74
114
|
prevImage,
|
|
75
115
|
nextImage,
|
|
@@ -80,14 +120,14 @@ var HtmlInCanvasPresentation = ({
|
|
|
80
120
|
});
|
|
81
121
|
await Internals.runEffectChain({
|
|
82
122
|
state: chainState.get(width, height),
|
|
83
|
-
source:
|
|
123
|
+
source: shaderCanvas,
|
|
84
124
|
effects: effectsRef.current ?? [],
|
|
85
125
|
width,
|
|
86
126
|
height,
|
|
87
|
-
output:
|
|
127
|
+
output: outputCanvas
|
|
88
128
|
});
|
|
89
129
|
continueRender(handle);
|
|
90
|
-
}, [chainState,
|
|
130
|
+
}, [chainState, continueRender, delayRender, instance, shaderCanvas]);
|
|
91
131
|
const passThrough = bothEnteringAndExiting && presentationDirection === "exiting";
|
|
92
132
|
useLayoutEffect(() => {
|
|
93
133
|
if (passThrough) {
|
|
@@ -100,11 +140,19 @@ var HtmlInCanvasPresentation = ({
|
|
|
100
140
|
canvas.layoutSubtree = true;
|
|
101
141
|
const onPaint = () => {
|
|
102
142
|
const firstChild = canvas.firstChild;
|
|
103
|
-
|
|
143
|
+
const captureCanvas = captureCanvasRef.current;
|
|
144
|
+
const captureContext = captureContextRef.current;
|
|
145
|
+
if (!firstChild || !captureCanvas || !captureContext) {
|
|
104
146
|
return;
|
|
105
147
|
}
|
|
106
148
|
const elementImage = canvas.captureElementImage(firstChild);
|
|
107
|
-
|
|
149
|
+
try {
|
|
150
|
+
captureContext.reset();
|
|
151
|
+
captureContext.drawElementImage(elementImage, 0, 0);
|
|
152
|
+
} finally {
|
|
153
|
+
elementImage.close();
|
|
154
|
+
}
|
|
155
|
+
onElementImage(captureCanvas, draw);
|
|
108
156
|
};
|
|
109
157
|
canvas.addEventListener("paint", onPaint);
|
|
110
158
|
return () => {
|
|
@@ -138,20 +186,39 @@ var HtmlInCanvasPresentation = ({
|
|
|
138
186
|
return;
|
|
139
187
|
}
|
|
140
188
|
const observer = new ResizeObserver(([entry]) => {
|
|
141
|
-
|
|
142
|
-
|
|
189
|
+
const outputCanvas = outputCanvasRef.current;
|
|
190
|
+
const captureCanvas = captureCanvasRef.current;
|
|
191
|
+
if (!outputCanvas || !captureCanvas) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const width = entry.devicePixelContentBoxSize[0].inlineSize;
|
|
195
|
+
const height = entry.devicePixelContentBoxSize[0].blockSize;
|
|
196
|
+
captureCanvas.width = width;
|
|
197
|
+
captureCanvas.height = height;
|
|
198
|
+
outputCanvas.width = width;
|
|
199
|
+
outputCanvas.height = height;
|
|
200
|
+
canvas.requestPaint?.();
|
|
143
201
|
});
|
|
144
202
|
observer.observe(canvas, { box: "device-pixel-content-box" });
|
|
203
|
+
return () => {
|
|
204
|
+
observer.disconnect();
|
|
205
|
+
};
|
|
145
206
|
}, [passThrough]);
|
|
146
207
|
if (passThrough) {
|
|
147
208
|
return children;
|
|
148
209
|
}
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
children:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
210
|
+
return /* @__PURE__ */ jsxs(AbsoluteFill, {
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx("canvas", {
|
|
213
|
+
ref: canvasRef,
|
|
214
|
+
style: canvasSubtreeStyle,
|
|
215
|
+
children
|
|
216
|
+
}),
|
|
217
|
+
/* @__PURE__ */ jsx("canvas", {
|
|
218
|
+
ref: outputCanvasRef,
|
|
219
|
+
style: outputCanvasStyle
|
|
220
|
+
})
|
|
221
|
+
]
|
|
155
222
|
});
|
|
156
223
|
};
|
|
157
224
|
var makeHtmlInCanvasPresentation = (shader) => {
|
|
@@ -173,6 +240,11 @@ var makeHtmlInCanvasPresentation = (shader) => {
|
|
|
173
240
|
};
|
|
174
241
|
};
|
|
175
242
|
|
|
243
|
+
// src/presentations/upload-element-image.ts
|
|
244
|
+
var uploadElementImage = (gl, elementImage) => {
|
|
245
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, elementImage);
|
|
246
|
+
};
|
|
247
|
+
|
|
176
248
|
// src/presentations/film-burn.tsx
|
|
177
249
|
var DEFAULT_SEED = 2.31;
|
|
178
250
|
var VERTEX_SHADER = `#version 300 es
|
|
@@ -417,13 +489,13 @@ var filmBurnShader = (canvas) => {
|
|
|
417
489
|
gl.activeTexture(gl.TEXTURE0);
|
|
418
490
|
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
419
491
|
if (prevImage) {
|
|
420
|
-
|
|
492
|
+
uploadElementImage(gl, prevImage);
|
|
421
493
|
}
|
|
422
494
|
gl.uniform1i(uPrev, 0);
|
|
423
495
|
gl.activeTexture(gl.TEXTURE1);
|
|
424
496
|
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
425
497
|
if (nextImage) {
|
|
426
|
-
|
|
498
|
+
uploadElementImage(gl, nextImage);
|
|
427
499
|
}
|
|
428
500
|
gl.uniform1i(uNext, 1);
|
|
429
501
|
gl.uniform1f(uTime, effectiveTime);
|