fragment-tools 0.1.17 → 0.1.18
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/package.json +3 -3
- package/src/cli/build.js +4 -0
- package/src/cli/createConfig.js +0 -1
- package/src/cli/preview.js +9 -11
- package/src/cli/templates/blank/index.js +6 -1
- package/src/cli/templates/default/index.js +2 -2
- package/src/client/app/lib/gl/Renderer.js +3 -0
- package/src/client/app/renderers/2DRenderer.js +29 -0
- package/src/client/app/renderers/P5GLRenderer.js +48 -7
- package/src/client/app/renderers/P5Renderer.js +3 -7
- package/src/client/app/renderers/THREERenderer.js +10 -4
- package/src/client/app/ui/SketchRenderer.svelte +91 -90
- package/src/client/app/lib/canvas-recorder/H264Recorder.js +0 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fragment-tools",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "A web development environment for creative coding",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"homepage": "https://github.com/raphaelameaume/fragment#readme",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@clack/core": "^0.3.3",
|
|
25
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
25
|
+
"@sveltejs/vite-plugin-svelte": "^3.1.1",
|
|
26
26
|
"body-parser": "^1.20.0",
|
|
27
27
|
"changedpi": "^1.0.4",
|
|
28
28
|
"chokidar": "^3.5.2",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"sade": "^1.7.4",
|
|
36
36
|
"svelte": "^4.0.0",
|
|
37
37
|
"svelte-json-tree": "^2.2.0",
|
|
38
|
-
"vite": "^
|
|
38
|
+
"vite": "^5.3.3",
|
|
39
39
|
"webm-writer": "^1.0.0",
|
|
40
40
|
"ws": "^8.2.3"
|
|
41
41
|
},
|
package/src/cli/build.js
CHANGED
package/src/cli/createConfig.js
CHANGED
package/src/cli/preview.js
CHANGED
|
@@ -37,17 +37,15 @@ export async function preview(dir, options = {}) {
|
|
|
37
37
|
|
|
38
38
|
const { resolvedUrls } = previewServer;
|
|
39
39
|
|
|
40
|
-
let urls =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
p.note(urls);
|
|
40
|
+
let urls = [
|
|
41
|
+
...resolvedUrls.local.map(
|
|
42
|
+
(url) => `${bold('Local')}: ${bold(cyan(url))}`,
|
|
43
|
+
),
|
|
44
|
+
...resolvedUrls.network.map(
|
|
45
|
+
(url) => `${bold('Network')}: ${bold(cyan(url))}`,
|
|
46
|
+
),
|
|
47
|
+
];
|
|
48
|
+
p.note(urls.join(`\n`));
|
|
51
49
|
} catch (error) {
|
|
52
50
|
log.error(`Error\n`, prefix);
|
|
53
51
|
console.error(error);
|
|
@@ -30,4 +30,9 @@ export let update = ({ width, height, time, deltaTime }) => {};
|
|
|
30
30
|
* @param {number} params.height
|
|
31
31
|
* @param {number} params.pixelRatio
|
|
32
32
|
*/
|
|
33
|
-
export let resize = ({ width, height, pixelRatio }) => {
|
|
33
|
+
export let resize = ({ canvas, width, height, pixelRatio }) => {
|
|
34
|
+
canvas.width = width * pixelRatio;
|
|
35
|
+
canvas.height = height * pixelRatio;
|
|
36
|
+
canvas.style.width = `${width}px`;
|
|
37
|
+
canvas.style.height = `${height}px`;
|
|
38
|
+
};
|
|
@@ -23,8 +23,8 @@ export let init = ({ canvas, context, width, height }) => {};
|
|
|
23
23
|
* @param {number} params.playhead
|
|
24
24
|
* @param {number} params.playcount
|
|
25
25
|
*/
|
|
26
|
-
export let update = ({ context, width, height,
|
|
27
|
-
context.clearRect(0, 0, width, height);
|
|
26
|
+
export let update = ({ context, width, height, pixelRatio }) => {
|
|
27
|
+
context.clearRect(0, 0, width * pixelRatio, height * pixelRatio);
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -137,6 +137,9 @@ class Renderer {
|
|
|
137
137
|
this.canvas.width = this.state.width * this.state.pixelRatio;
|
|
138
138
|
this.canvas.height = this.state.height * this.state.pixelRatio;
|
|
139
139
|
|
|
140
|
+
this.canvas.style.width = `${this.state.width}px`;
|
|
141
|
+
this.canvas.style.height = `${this.state.height}px`;
|
|
142
|
+
|
|
140
143
|
this.setViewport();
|
|
141
144
|
}
|
|
142
145
|
|
|
@@ -1,5 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} MountParams2DRenderer
|
|
3
|
+
* @property {CanvasRenderingContext2D} context
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {object} params
|
|
8
|
+
* @param {number} params.id
|
|
9
|
+
* @param {HTMLDivElement} params.container
|
|
10
|
+
* @param {HTMLCanvasElement} params.canvas
|
|
11
|
+
* @param {number} params.width
|
|
12
|
+
* @param {number} params.height
|
|
13
|
+
* @param {number} params.pixelRatio
|
|
14
|
+
* @returns {MountParams2DRenderer}
|
|
15
|
+
*/
|
|
1
16
|
export let onMountPreview = ({ canvas }) => {
|
|
2
17
|
return {
|
|
3
18
|
context: canvas.getContext('2d'),
|
|
4
19
|
};
|
|
5
20
|
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {object} params
|
|
24
|
+
* @param {HTMLCanvasElement} params.canvas
|
|
25
|
+
* @param {number} params.width
|
|
26
|
+
* @param {number} params.height
|
|
27
|
+
* @param {number} params.pixelRatio
|
|
28
|
+
*/
|
|
29
|
+
export let onResizePreview = ({ canvas, width, height, pixelRatio }) => {
|
|
30
|
+
canvas.width = width * pixelRatio;
|
|
31
|
+
canvas.height = height * pixelRatio;
|
|
32
|
+
canvas.style.width = `${width}px`;
|
|
33
|
+
canvas.style.height = `${height}px`;
|
|
34
|
+
};
|
|
@@ -3,8 +3,39 @@ import { client } from '@fragment/client';
|
|
|
3
3
|
import { getShaderPath } from '../utils/glsl.utils';
|
|
4
4
|
import { clearError } from '../stores/errors';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {object} PreviewP5GLRenderer
|
|
8
|
+
* @property {number} id
|
|
9
|
+
* @property {p5} p
|
|
10
|
+
* @property {boolean} rendered
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} MountParamsP5GLRenderer
|
|
15
|
+
* @property {HTMLCanvasElement} canvas
|
|
16
|
+
* @property {p5} p
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {object} PreviewParamsP5GLRenderer
|
|
21
|
+
* @property {number} params.id
|
|
22
|
+
* @property {HTMLDivElement} params.container
|
|
23
|
+
* @property {HTMLCanvasElement} params.canvas
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** @type {PreviewP5GLRenderer[]} */
|
|
6
27
|
let previews = [];
|
|
7
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @param {object} params
|
|
31
|
+
* @param {number} params.id
|
|
32
|
+
* @param {HTMLDivElement} params.container
|
|
33
|
+
* @param {HTMLCanvasElement} params.canvas
|
|
34
|
+
* @param {number} params.width
|
|
35
|
+
* @param {number} params.height
|
|
36
|
+
* @param {number} params.pixelRatio
|
|
37
|
+
* @returns {MountParamsP5GLRenderer}
|
|
38
|
+
*/
|
|
8
39
|
export let onMountPreview = ({ id, width, height }) => {
|
|
9
40
|
const p = new p5((sketch) => {
|
|
10
41
|
sketch.setup = () => {
|
|
@@ -12,9 +43,11 @@ export let onMountPreview = ({ id, width, height }) => {
|
|
|
12
43
|
};
|
|
13
44
|
});
|
|
14
45
|
|
|
46
|
+
/** @type {PreviewP5GLRenderer} */
|
|
15
47
|
const preview = {
|
|
16
48
|
id,
|
|
17
49
|
p,
|
|
50
|
+
rendered: false,
|
|
18
51
|
};
|
|
19
52
|
|
|
20
53
|
previews.push(preview);
|
|
@@ -25,6 +58,9 @@ export let onMountPreview = ({ id, width, height }) => {
|
|
|
25
58
|
};
|
|
26
59
|
};
|
|
27
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @param {PreviewParamsP5GLRenderer} params
|
|
63
|
+
*/
|
|
28
64
|
export let onBeforeUpdatePreview = ({ id }) => {
|
|
29
65
|
const preview = previews.find((p) => p.id === id);
|
|
30
66
|
|
|
@@ -34,6 +70,9 @@ export let onBeforeUpdatePreview = ({ id }) => {
|
|
|
34
70
|
}
|
|
35
71
|
};
|
|
36
72
|
|
|
73
|
+
/**
|
|
74
|
+
* @param {PreviewParamsP5GLRenderer} params
|
|
75
|
+
*/
|
|
37
76
|
export let onAfterUpdatePreview = ({ id }) => {
|
|
38
77
|
const preview = previews.find((p) => p.id === id);
|
|
39
78
|
|
|
@@ -49,15 +88,17 @@ export let onAfterUpdatePreview = ({ id }) => {
|
|
|
49
88
|
}
|
|
50
89
|
};
|
|
51
90
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
91
|
+
/**
|
|
92
|
+
* @param {PreviewParamsP5GLRenderer} params
|
|
93
|
+
*/
|
|
94
|
+
export let onResizePreview = ({ p, width, height, pixelRatio }) => {
|
|
95
|
+
p.pixelDensity(pixelRatio);
|
|
96
|
+
p.resizeCanvas(width, height, false);
|
|
59
97
|
};
|
|
60
98
|
|
|
99
|
+
/**
|
|
100
|
+
* @param {PreviewParamsP5GLRenderer} params
|
|
101
|
+
*/
|
|
61
102
|
export let onDestroyPreview = ({ id }) => {
|
|
62
103
|
const previewIndex = previews.findIndex((preview) => preview.id === id);
|
|
63
104
|
const preview = previews[previewIndex];
|
|
@@ -30,13 +30,9 @@ export let onBeforeUpdatePreview = ({ id }) => {
|
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export let onResizePreview = ({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (preview) {
|
|
37
|
-
preview.p.pixelDensity(pixelRatio);
|
|
38
|
-
preview.p.resizeCanvas(width, height, false);
|
|
39
|
-
}
|
|
33
|
+
export let onResizePreview = ({ p, width, height, pixelRatio }) => {
|
|
34
|
+
p.pixelDensity(pixelRatio);
|
|
35
|
+
p.resizeCanvas(width, height, false);
|
|
40
36
|
};
|
|
41
37
|
|
|
42
38
|
export let onDestroyPreview = ({ id }) => {
|
|
@@ -4,8 +4,11 @@ import { client } from '@fragment/client';
|
|
|
4
4
|
import { getShaderPath } from '../utils/glsl.utils';
|
|
5
5
|
import { clearError } from '../stores/errors';
|
|
6
6
|
|
|
7
|
-
let renderer;
|
|
8
7
|
let previews = [];
|
|
8
|
+
|
|
9
|
+
/** @type {WebGLRenderer} */
|
|
10
|
+
let renderer;
|
|
11
|
+
|
|
9
12
|
let fragmentShader = /* glsl */ `
|
|
10
13
|
precision highp float;
|
|
11
14
|
uniform sampler2D uSampler;
|
|
@@ -66,7 +69,7 @@ export let onMountPreview = ({ id, canvas, width, height, pixelRatio }) => {
|
|
|
66
69
|
};
|
|
67
70
|
};
|
|
68
71
|
|
|
69
|
-
export let onDestroyPreview = ({ id
|
|
72
|
+
export let onDestroyPreview = ({ id }) => {
|
|
70
73
|
const previewIndex = previews.findIndex((p) => p.id === id);
|
|
71
74
|
const preview = previews[previewIndex];
|
|
72
75
|
|
|
@@ -107,9 +110,12 @@ export let onAfterUpdatePreview = ({ id }) => {
|
|
|
107
110
|
export let resize = ({ width, height, pixelRatio }) => {
|
|
108
111
|
renderer.setPixelRatio(pixelRatio);
|
|
109
112
|
renderer.setSize(width, height);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export let onResizePreview = ({ id, width, height, pixelRatio }) => {
|
|
116
|
+
const preview = previews.find((p) => p.id === id);
|
|
110
117
|
|
|
111
|
-
|
|
112
|
-
const preview = previews[i];
|
|
118
|
+
if (preview) {
|
|
113
119
|
preview.resize({ width, height, pixelRatio });
|
|
114
120
|
}
|
|
115
121
|
};
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
export let paused = false;
|
|
36
36
|
export let visible = true;
|
|
37
37
|
|
|
38
|
-
let node
|
|
38
|
+
let node;
|
|
39
|
+
/** @type {HTMLDivElement} */
|
|
40
|
+
let container;
|
|
39
41
|
let framerate = 60;
|
|
40
42
|
let elapsed = 0;
|
|
41
43
|
let elapsedRenderingTime = 0;
|
|
@@ -60,44 +62,46 @@
|
|
|
60
62
|
$: beforeRecordCallbacks = $beforeRecord.get(key) || [];
|
|
61
63
|
$: afterRecordCallbacks = $afterRecord.get(key) || [];
|
|
62
64
|
|
|
63
|
-
function checkForResize() {
|
|
65
|
+
function checkForResize(resizing = $rendering.resizing) {
|
|
64
66
|
if (!node) return;
|
|
65
67
|
|
|
66
|
-
let
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
68
|
+
let isWindowResize = resizing === SIZES.WINDOW;
|
|
69
|
+
let isAspectResize = resizing === SIZES.ASPECT_RATIO;
|
|
70
|
+
let canUpdate = isWindowResize || isAspectResize;
|
|
71
|
+
|
|
72
|
+
if (canUpdate) {
|
|
73
|
+
let newWidth, newHeight;
|
|
74
|
+
|
|
75
|
+
if (isWindowResize) {
|
|
76
|
+
newWidth = node.offsetWidth;
|
|
77
|
+
newHeight = node.offsetHeight;
|
|
78
|
+
} else if (isAspectResize) {
|
|
79
|
+
const { offsetWidth, offsetHeight } = node;
|
|
80
|
+
const aspectRatio = $rendering.aspectRatio;
|
|
81
|
+
const monitorRatio = offsetWidth / offsetHeight;
|
|
82
|
+
|
|
83
|
+
if (aspectRatio < monitorRatio) {
|
|
84
|
+
newHeight = offsetHeight;
|
|
85
|
+
newWidth = newHeight * aspectRatio;
|
|
86
|
+
} else {
|
|
87
|
+
newWidth = offsetWidth;
|
|
88
|
+
newHeight = newWidth / aspectRatio;
|
|
89
|
+
}
|
|
86
90
|
}
|
|
87
|
-
}
|
|
88
91
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
let needsUpdate =
|
|
93
|
+
newWidth !== $rendering.width ||
|
|
94
|
+
newHeight !== $rendering.height;
|
|
95
|
+
|
|
96
|
+
if (needsUpdate) {
|
|
97
|
+
rendering.update((curr) => {
|
|
98
|
+
return {
|
|
99
|
+
...curr,
|
|
100
|
+
width: newWidth,
|
|
101
|
+
height: newHeight,
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
}
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
|
|
@@ -127,9 +131,6 @@
|
|
|
127
131
|
});
|
|
128
132
|
|
|
129
133
|
function createCanvas(canvas = document.createElement('canvas')) {
|
|
130
|
-
canvas.width = $rendering.width * $rendering.pixelRatio;
|
|
131
|
-
canvas.height = $rendering.height * $rendering.pixelRatio;
|
|
132
|
-
|
|
133
134
|
canvas.onmousedown = (event) => checkForTriggersDown(event, key);
|
|
134
135
|
canvas.onmousemove = (event) => checkForTriggersMove(event, key);
|
|
135
136
|
canvas.onmouseup = (event) => checkForTriggersUp(event, key);
|
|
@@ -182,7 +183,7 @@
|
|
|
182
183
|
async function createSketch(key) {
|
|
183
184
|
_created = false;
|
|
184
185
|
|
|
185
|
-
sketch?.dispose?.();
|
|
186
|
+
sketch?.dispose?.(params);
|
|
186
187
|
|
|
187
188
|
sketch = $sketches[key];
|
|
188
189
|
|
|
@@ -202,7 +203,7 @@
|
|
|
202
203
|
|
|
203
204
|
if (canvas) {
|
|
204
205
|
if (renderer && typeof renderer.onDestroyPreview === 'function') {
|
|
205
|
-
renderer.onDestroyPreview({ id, canvas });
|
|
206
|
+
renderer.onDestroyPreview({ id, container, canvas });
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
destroyCanvas(canvas);
|
|
@@ -487,30 +488,6 @@
|
|
|
487
488
|
}
|
|
488
489
|
}
|
|
489
490
|
|
|
490
|
-
rendering.subscribe((current) => {
|
|
491
|
-
if (canvas && _created) {
|
|
492
|
-
if (current.resizing === SIZES.SCALE) {
|
|
493
|
-
canvas.style.transform = `scale(${current.scale})`;
|
|
494
|
-
} else {
|
|
495
|
-
canvas.style.transform = null;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
const { width, height, pixelRatio } = current;
|
|
499
|
-
const resize = sketch.resize || noop;
|
|
500
|
-
|
|
501
|
-
resize({
|
|
502
|
-
canvas,
|
|
503
|
-
width,
|
|
504
|
-
height,
|
|
505
|
-
pixelRatio,
|
|
506
|
-
...params,
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
_renderSketch = createRenderLoop();
|
|
510
|
-
needsRender = true;
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
|
|
514
491
|
async function save() {
|
|
515
492
|
paused = true;
|
|
516
493
|
|
|
@@ -649,21 +626,38 @@
|
|
|
649
626
|
$: {
|
|
650
627
|
checkForResize();
|
|
651
628
|
|
|
629
|
+
const { width, height, pixelRatio, resizing, scale } = $rendering;
|
|
630
|
+
|
|
652
631
|
if (renderer && typeof renderer.onResizePreview === 'function') {
|
|
653
632
|
renderer.onResizePreview({
|
|
654
633
|
id,
|
|
655
634
|
container,
|
|
656
|
-
width
|
|
657
|
-
height
|
|
658
|
-
pixelRatio
|
|
635
|
+
width,
|
|
636
|
+
height,
|
|
637
|
+
pixelRatio,
|
|
638
|
+
...params,
|
|
659
639
|
});
|
|
660
640
|
}
|
|
661
641
|
|
|
662
642
|
if (canvas) {
|
|
663
|
-
|
|
643
|
+
if (resizing === SIZES.SCALE) {
|
|
644
|
+
canvas.style.transform = `scale(${scale})`;
|
|
645
|
+
} else {
|
|
646
|
+
canvas.style.transform = null;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (_created) {
|
|
650
|
+
sketch?.resize?.({
|
|
651
|
+
canvas,
|
|
652
|
+
width,
|
|
653
|
+
height,
|
|
654
|
+
pixelRatio,
|
|
655
|
+
...params,
|
|
656
|
+
});
|
|
664
657
|
|
|
665
|
-
|
|
666
|
-
|
|
658
|
+
_renderSketch = createRenderLoop();
|
|
659
|
+
_renderSketch();
|
|
660
|
+
}
|
|
667
661
|
}
|
|
668
662
|
}
|
|
669
663
|
|
|
@@ -680,6 +674,10 @@
|
|
|
680
674
|
)) // if none of current monitors match the key
|
|
681
675
|
? $errors.get($errors.keys().next().value)
|
|
682
676
|
: null;
|
|
677
|
+
|
|
678
|
+
$: isSquare = $rendering.width === $rendering.height;
|
|
679
|
+
$: isLandscape = $rendering.width > $rendering.height;
|
|
680
|
+
$: isPortrait = $rendering.width < $rendering.height;
|
|
683
681
|
</script>
|
|
684
682
|
|
|
685
683
|
<div
|
|
@@ -691,7 +689,7 @@
|
|
|
691
689
|
>
|
|
692
690
|
<div
|
|
693
691
|
class="canvas-container"
|
|
694
|
-
style="
|
|
692
|
+
style="--aspect-ratio: {$rendering.width} / {$rendering.height}; --aspect-ratio-inverse: {$rendering.height} / {$rendering.width}; --width: {$rendering.width}px; --height: {$rendering.height}px;"
|
|
695
693
|
bind:this={container}
|
|
696
694
|
/>
|
|
697
695
|
{#if $recording}
|
|
@@ -709,7 +707,6 @@
|
|
|
709
707
|
|
|
710
708
|
<style>
|
|
711
709
|
.sketch-renderer {
|
|
712
|
-
position: absolute;
|
|
713
710
|
display: flex;
|
|
714
711
|
width: 100%;
|
|
715
712
|
height: 100%;
|
|
@@ -717,6 +714,8 @@
|
|
|
717
714
|
align-items: center;
|
|
718
715
|
|
|
719
716
|
background-color: var(--background-color, var(--color-lightblack));
|
|
717
|
+
|
|
718
|
+
container-type: size;
|
|
720
719
|
}
|
|
721
720
|
|
|
722
721
|
.sketch-renderer:not(.visible) {
|
|
@@ -724,13 +723,27 @@
|
|
|
724
723
|
}
|
|
725
724
|
|
|
726
725
|
.canvas-container {
|
|
726
|
+
--w: min(100cqw, calc(100cqh * var(--aspect-ratio)));
|
|
727
727
|
position: relative;
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
728
|
+
|
|
729
|
+
max-width: var(--width);
|
|
730
|
+
max-height: var(--height);
|
|
731
|
+
|
|
732
|
+
width: var(--w);
|
|
733
|
+
height: calc(var(--w) * var(--aspect-ratio-inverse));
|
|
734
|
+
|
|
735
|
+
background-color: red;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
:global(.canvas-container canvas) {
|
|
739
|
+
position: absolute;
|
|
740
|
+
top: 0;
|
|
741
|
+
left: 0;
|
|
742
|
+
|
|
743
|
+
width: 100% !important;
|
|
744
|
+
height: 100% !important;
|
|
745
|
+
|
|
746
|
+
background-color: var(--background-color, #000000);
|
|
734
747
|
}
|
|
735
748
|
|
|
736
749
|
.sketch-renderer.recording .canvas-container {
|
|
@@ -783,16 +796,4 @@
|
|
|
783
796
|
opacity: 0;
|
|
784
797
|
}
|
|
785
798
|
}
|
|
786
|
-
|
|
787
|
-
:global(.canvas-container canvas) {
|
|
788
|
-
max-width: 100%;
|
|
789
|
-
max-height: 100%;
|
|
790
|
-
|
|
791
|
-
flex: none;
|
|
792
|
-
|
|
793
|
-
width: auto !important;
|
|
794
|
-
height: auto !important;
|
|
795
|
-
|
|
796
|
-
background-color: var(--background-color, #000000);
|
|
797
|
-
}
|
|
798
799
|
</style>
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import * as HME from 'h264-mp4-encoder';
|
|
2
|
-
import CanvasRecorder from './CanvasRecorder';
|
|
3
|
-
|
|
4
|
-
class H264Recorder extends CanvasRecorder {
|
|
5
|
-
getBitmapRGBA(bitmap, width = bitmap.width, height = bitmap.height) {
|
|
6
|
-
this.tmpCanvas.width = width;
|
|
7
|
-
this.tmpCanvas.height = height;
|
|
8
|
-
this.tmpContext.clearRect(0, 0, width, height);
|
|
9
|
-
this.tmpContext.drawImage(bitmap, 0, 0, width, height);
|
|
10
|
-
return this.tmpContext.getImageData(0, 0, width, height).data;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async start() {
|
|
14
|
-
this.encoder = await HME.createH264MP4Encoder();
|
|
15
|
-
|
|
16
|
-
this.tmpCanvas = document.createElement('canvas');
|
|
17
|
-
this.tmpContext = this.tmpCanvas.getContext('2d');
|
|
18
|
-
|
|
19
|
-
this.encoder.width = this.canvas.width;
|
|
20
|
-
this.encoder.height = this.canvas.height;
|
|
21
|
-
this.encoder.frameRate = this.framerate;
|
|
22
|
-
this.encoder.kbps = 30000;
|
|
23
|
-
this.encoder.initialize();
|
|
24
|
-
|
|
25
|
-
super.start();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
tick() {
|
|
29
|
-
const { width, height } = this.canvas;
|
|
30
|
-
const pixels = this.getBitmapRGBA(this.canvas, width, height);
|
|
31
|
-
|
|
32
|
-
this.encoder.addFrameRgba(pixels);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async end() {
|
|
36
|
-
this.encoder.finalize();
|
|
37
|
-
|
|
38
|
-
const data = this.encoder.FS.readFile(this.encoder.outputFilename);
|
|
39
|
-
this.result = new Blob([data], { type: 'video/mp4' });
|
|
40
|
-
|
|
41
|
-
super.end();
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export default H264Recorder;
|