zdymak 0.7.0 → 0.13.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/LICENSE +21 -21
- package/README.md +733 -211
- package/SKILL.md +183 -84
- package/bin/zdymak.mjs +3 -3
- package/package.json +66 -40
- package/src/canvas.mjs +116 -116
- package/src/capture/index.mjs +318 -242
- package/src/capture/web.mjs +137 -0
- package/src/cli.mjs +298 -165
- package/src/config.mjs +159 -96
- package/src/destinations.mjs +103 -0
- package/src/easings.mjs +74 -0
- package/src/effects.mjs +335 -0
- package/src/encode.mjs +70 -44
- package/src/fonts.mjs +42 -42
- package/src/frames.mjs +186 -168
- package/src/graphic.mjs +107 -77
- package/src/index.mjs +27 -12
- package/src/montage.mjs +428 -0
- package/src/png.mjs +50 -50
- package/src/premium.mjs +362 -351
- package/src/reel.mjs +366 -245
- package/src/screenshots.mjs +118 -66
- package/src/specs.mjs +123 -88
- package/src/statusbar.mjs +163 -0
- package/src/still.mjs +72 -62
- package/src/transitions.mjs +653 -0
- package/src/validate.mjs +98 -0
- package/src/video.mjs +243 -240
- package/types/index.d.ts +559 -0
package/src/still.mjs
CHANGED
|
@@ -1,62 +1,72 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Still-image renderers — one store screenshot per scene, in a chosen style. Aspect-agnostic (cover-fit),
|
|
3
|
-
* so the same renderers serve iPhone, iPad, Mac and Watch dimensions.
|
|
4
|
-
*
|
|
5
|
-
* premium — the app screen floats on a brand matte (glow + vignette) with a bottom title pill.
|
|
6
|
-
* bleed — the app screen fills the frame, with an optional lower-third caption. Best for Watch (raw).
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
function coverCanvas(img, W, H) {
|
|
16
|
-
const c = createCanvas(W, H);
|
|
17
|
-
const ctx = c.getContext('2d');
|
|
18
|
-
const ia = img.height / img.width;
|
|
19
|
-
let dw = W;
|
|
20
|
-
let dh = W * ia;
|
|
21
|
-
if (dh < H) {
|
|
22
|
-
dh = H;
|
|
23
|
-
dw = H / ia;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
ctx.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Still-image renderers — one store screenshot per scene, in a chosen style. Aspect-agnostic (cover-fit),
|
|
3
|
+
* so the same renderers serve iPhone, iPad, Mac and Watch dimensions.
|
|
4
|
+
*
|
|
5
|
+
* premium — the app screen floats on a brand matte (glow + vignette) with a bottom title pill.
|
|
6
|
+
* bleed — the app screen fills the frame, with an optional lower-third caption. Best for Watch (raw).
|
|
7
|
+
*
|
|
8
|
+
* framed — the capture inside a device body (iPhone/iPad/Android/Watch), caption on top.
|
|
9
|
+
*/
|
|
10
|
+
import { createCanvas, loadImage } from '@napi-rs/canvas';
|
|
11
|
+
import { premiumStill } from './premium.mjs';
|
|
12
|
+
import { drawCaption, hexA } from './canvas.mjs';
|
|
13
|
+
import { loadCapture } from './statusbar.mjs';
|
|
14
|
+
|
|
15
|
+
function coverCanvas(img, W, H, anchor = 'center') {
|
|
16
|
+
const c = createCanvas(W, H);
|
|
17
|
+
const ctx = c.getContext('2d');
|
|
18
|
+
const ia = img.height / img.width;
|
|
19
|
+
let dw = W;
|
|
20
|
+
let dh = W * ia;
|
|
21
|
+
if (dh < H) {
|
|
22
|
+
dh = H;
|
|
23
|
+
dw = H / ia;
|
|
24
|
+
}
|
|
25
|
+
// A phone capture is taller than any store slot (Play caps at 2:1), so a cover fit must drop some of
|
|
26
|
+
// it. `anchor: 'top'` drops it from the BOTTOM — keeping the status bar and the screen's headline,
|
|
27
|
+
// which is what a plain, unframed store shot needs; centring would shave both ends.
|
|
28
|
+
const dy = anchor === 'top' ? 0 : (H - dh) / 2;
|
|
29
|
+
ctx.drawImage(img, (W - dw) / 2, dy, dw, dh);
|
|
30
|
+
return c;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function bleedStill({ W, H, img, caption, brand, theme }) {
|
|
34
|
+
const c = createCanvas(W, H);
|
|
35
|
+
const ctx = c.getContext('2d');
|
|
36
|
+
ctx.fillStyle = brand.ink;
|
|
37
|
+
ctx.fillRect(0, 0, W, H);
|
|
38
|
+
ctx.drawImage(coverCanvas(img, W, H, theme?.anchor), 0, 0);
|
|
39
|
+
if (caption.title || caption.sub) {
|
|
40
|
+
const g = ctx.createLinearGradient(0, H * 0.55, 0, H);
|
|
41
|
+
g.addColorStop(0, hexA(brand.ink, 0));
|
|
42
|
+
g.addColorStop(1, hexA(brand.ink, 0.85));
|
|
43
|
+
ctx.fillStyle = g;
|
|
44
|
+
ctx.fillRect(0, H * 0.55, W, H * 0.45);
|
|
45
|
+
drawCaption(ctx, {
|
|
46
|
+
title: caption.title,
|
|
47
|
+
subtitle: caption.sub,
|
|
48
|
+
centerX: W / 2,
|
|
49
|
+
top: H * 0.78,
|
|
50
|
+
maxWidth: W * 0.86,
|
|
51
|
+
titleSize: Math.round(W * 0.066),
|
|
52
|
+
subSize: Math.round(W * 0.036),
|
|
53
|
+
titleColor: brand.title,
|
|
54
|
+
subColor: brand.sub,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return c;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Render one still to a canvas. `style`: premium | framed (device bezel) | bleed.
|
|
62
|
+
*
|
|
63
|
+
* The status bar is painted onto the CAPTURE before any framing/scaling, so it lands at the capture's own
|
|
64
|
+
* density and gets scaled down with everything else — drawing it afterwards would size it to the output
|
|
65
|
+
* frame and look pasted on.
|
|
66
|
+
*/
|
|
67
|
+
export async function renderStill(style, { W, H, imgPath, caption, brand, theme, frame }) {
|
|
68
|
+
const img = await loadCapture(imgPath, theme, frame);
|
|
69
|
+
if (style === 'framed') return premiumStill({ W, H, img, caption, brand, theme, frame: frame || 'phone' });
|
|
70
|
+
if (style === 'premium') return premiumStill({ W, H, img, caption, brand, theme });
|
|
71
|
+
return bleedStill({ W, H, img, caption, brand, theme });
|
|
72
|
+
}
|