reframe-video 0.6.15 → 0.6.16
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/bin.js +5 -1
- package/dist/browserEntry.js +18 -6
- package/dist/cli.js +5 -1
- package/dist/diff.js +5 -1
- package/dist/index.js +21 -7
- package/dist/labels.js +5 -1
- package/dist/types/ir.d.ts +11 -0
- package/guides/edsl-guide.md +6 -0
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -162,6 +162,8 @@ function compileScene(ir) {
|
|
|
162
162
|
initialValues.set(key("camera", "zoom"), cam.zoom ?? 1);
|
|
163
163
|
initialValues.set(key("camera", "rotation"), cam.rotation ?? 0);
|
|
164
164
|
if (cam.perspective !== void 0) initialValues.set(key("camera", "perspective"), cam.perspective);
|
|
165
|
+
if (cam.focus !== void 0) initialValues.set(key("camera", "focus"), cam.focus);
|
|
166
|
+
if (cam.aperture !== void 0) initialValues.set(key("camera", "aperture"), cam.aperture);
|
|
165
167
|
}
|
|
166
168
|
const segments = /* @__PURE__ */ new Map();
|
|
167
169
|
const motionPaths = /* @__PURE__ */ new Map();
|
|
@@ -548,6 +550,8 @@ function validateScene(ir) {
|
|
|
548
550
|
problems.push(`camera.${key2} must be a number`);
|
|
549
551
|
} else if (key2 === "perspective" && value <= 0) {
|
|
550
552
|
problems.push(`camera.perspective must be > 0 (focal distance in px) \u2014 drop it to disable perspective`);
|
|
553
|
+
} else if (key2 === "aperture" && value < 0) {
|
|
554
|
+
problems.push(`camera.aperture must be >= 0 (blur px per unit depth) \u2014 0 disables depth of field`);
|
|
551
555
|
}
|
|
552
556
|
}
|
|
553
557
|
}
|
|
@@ -629,7 +633,7 @@ var init_validate = __esm({
|
|
|
629
633
|
]);
|
|
630
634
|
IMAGE_FITS = /* @__PURE__ */ new Set(["fill", "cover"]);
|
|
631
635
|
COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "scaleX", "scaleY", "skewX", "skewY", "z", "rotateX", "rotateY", "anchor", "fixed", ...FX_PROPS];
|
|
632
|
-
CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective"];
|
|
636
|
+
CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective", "focus", "aperture"];
|
|
633
637
|
PROPS_BY_TYPE = {
|
|
634
638
|
rect: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth", "radius"],
|
|
635
639
|
ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
|
package/dist/browserEntry.js
CHANGED
|
@@ -159,6 +159,8 @@
|
|
|
159
159
|
initialValues.set(key("camera", "zoom"), cam.zoom ?? 1);
|
|
160
160
|
initialValues.set(key("camera", "rotation"), cam.rotation ?? 0);
|
|
161
161
|
if (cam.perspective !== void 0) initialValues.set(key("camera", "perspective"), cam.perspective);
|
|
162
|
+
if (cam.focus !== void 0) initialValues.set(key("camera", "focus"), cam.focus);
|
|
163
|
+
if (cam.aperture !== void 0) initialValues.set(key("camera", "aperture"), cam.aperture);
|
|
162
164
|
}
|
|
163
165
|
const segments = /* @__PURE__ */ new Map();
|
|
164
166
|
const motionPaths = /* @__PURE__ */ new Map();
|
|
@@ -740,6 +742,14 @@
|
|
|
740
742
|
const dPersp = persp ? num("camera", "perspective", 0) : 0;
|
|
741
743
|
const vx = persp ? compiled2.ir.size.width / 2 : 0;
|
|
742
744
|
const vy = persp ? compiled2.ir.size.height / 2 : 0;
|
|
745
|
+
const aperture = persp ? num("camera", "aperture", 0) : 0;
|
|
746
|
+
const focus = persp ? num("camera", "focus", 0) : 0;
|
|
747
|
+
const dofFx = (fx, depth, project) => {
|
|
748
|
+
if (!project || aperture <= 0) return fx;
|
|
749
|
+
const extra = aperture * Math.abs(depth - focus);
|
|
750
|
+
if (extra <= 0) return fx;
|
|
751
|
+
return { ...fx, blur: z0((fx.blur ?? 0) + extra) };
|
|
752
|
+
};
|
|
743
753
|
const walk = (node, parent, parentOpacity, clips, zAcc, project) => {
|
|
744
754
|
const id = node.id;
|
|
745
755
|
const clipSpread = clips.length > 0 ? { clips } : void 0;
|
|
@@ -762,7 +772,8 @@
|
|
|
762
772
|
y2: y1 + (num(id, "y2", node.props.y2) - y1) * progress,
|
|
763
773
|
stroke: str(id, "stroke", node.props.stroke),
|
|
764
774
|
strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1),
|
|
765
|
-
|
|
775
|
+
// a line carries no z of its own — DOF uses the inherited subtree depth
|
|
776
|
+
...dofFx(fx, zAcc, project),
|
|
766
777
|
...clipSpread
|
|
767
778
|
});
|
|
768
779
|
return;
|
|
@@ -799,6 +810,7 @@
|
|
|
799
810
|
const tilted = rotX !== 0 || rotY !== 0 ? tiltSkew(m, rotX, rotY, hw, hh, dPersp) : m;
|
|
800
811
|
return projectDepth(tilted, depth, vx, vy, dPersp);
|
|
801
812
|
};
|
|
813
|
+
const leafFx = dofFx(fx, depth, project);
|
|
802
814
|
switch (node.type) {
|
|
803
815
|
case "group": {
|
|
804
816
|
const clipTf = projDraw(matrix, 0, 0);
|
|
@@ -839,7 +851,7 @@
|
|
|
839
851
|
...fill !== void 0 && { fill },
|
|
840
852
|
...stroke !== void 0 && { stroke, strokeWidth },
|
|
841
853
|
...node.type === "rect" && { radius: num(id, "radius", node.props.radius ?? 0) },
|
|
842
|
-
...
|
|
854
|
+
...leafFx,
|
|
843
855
|
...clipSpread
|
|
844
856
|
});
|
|
845
857
|
return;
|
|
@@ -859,7 +871,7 @@
|
|
|
859
871
|
offsetX: -width * ax,
|
|
860
872
|
offsetY: -height * ay,
|
|
861
873
|
...node.props.fit && node.props.fit !== "fill" ? { fit: node.props.fit } : {},
|
|
862
|
-
...
|
|
874
|
+
...leafFx,
|
|
863
875
|
...clipSpread
|
|
864
876
|
});
|
|
865
877
|
return;
|
|
@@ -886,7 +898,7 @@
|
|
|
886
898
|
offsetY: -height * ay,
|
|
887
899
|
frame,
|
|
888
900
|
...node.props.fit && node.props.fit !== "fill" ? { fit: node.props.fit } : {},
|
|
889
|
-
...
|
|
901
|
+
...leafFx,
|
|
890
902
|
...clipSpread
|
|
891
903
|
});
|
|
892
904
|
return;
|
|
@@ -911,7 +923,7 @@
|
|
|
911
923
|
...fill !== void 0 && { fill },
|
|
912
924
|
...stroke !== void 0 && { stroke, strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1) },
|
|
913
925
|
...needsBox && { bbox: pathBBox(dStr) },
|
|
914
|
-
...
|
|
926
|
+
...leafFx,
|
|
915
927
|
...clipSpread
|
|
916
928
|
});
|
|
917
929
|
return;
|
|
@@ -938,7 +950,7 @@
|
|
|
938
950
|
letterSpacing: num(id, "letterSpacing", node.props.letterSpacing ?? 0),
|
|
939
951
|
align: TEXT_ALIGN[ax] ?? "left",
|
|
940
952
|
baseline: TEXT_BASELINE[ay] ?? "top",
|
|
941
|
-
...
|
|
953
|
+
...leafFx,
|
|
942
954
|
...clipSpread
|
|
943
955
|
});
|
|
944
956
|
return;
|
package/dist/cli.js
CHANGED
|
@@ -149,6 +149,8 @@ function compileScene(ir) {
|
|
|
149
149
|
initialValues.set(key("camera", "zoom"), cam.zoom ?? 1);
|
|
150
150
|
initialValues.set(key("camera", "rotation"), cam.rotation ?? 0);
|
|
151
151
|
if (cam.perspective !== void 0) initialValues.set(key("camera", "perspective"), cam.perspective);
|
|
152
|
+
if (cam.focus !== void 0) initialValues.set(key("camera", "focus"), cam.focus);
|
|
153
|
+
if (cam.aperture !== void 0) initialValues.set(key("camera", "aperture"), cam.aperture);
|
|
152
154
|
}
|
|
153
155
|
const segments = /* @__PURE__ */ new Map();
|
|
154
156
|
const motionPaths = /* @__PURE__ */ new Map();
|
|
@@ -344,7 +346,7 @@ var BLEND_MODES = /* @__PURE__ */ new Set([
|
|
|
344
346
|
]);
|
|
345
347
|
var IMAGE_FITS = /* @__PURE__ */ new Set(["fill", "cover"]);
|
|
346
348
|
var COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "scaleX", "scaleY", "skewX", "skewY", "z", "rotateX", "rotateY", "anchor", "fixed", ...FX_PROPS];
|
|
347
|
-
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective"];
|
|
349
|
+
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective", "focus", "aperture"];
|
|
348
350
|
var PROPS_BY_TYPE = {
|
|
349
351
|
rect: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth", "radius"],
|
|
350
352
|
ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
|
|
@@ -562,6 +564,8 @@ function validateScene(ir) {
|
|
|
562
564
|
problems.push(`camera.${key2} must be a number`);
|
|
563
565
|
} else if (key2 === "perspective" && value <= 0) {
|
|
564
566
|
problems.push(`camera.perspective must be > 0 (focal distance in px) \u2014 drop it to disable perspective`);
|
|
567
|
+
} else if (key2 === "aperture" && value < 0) {
|
|
568
|
+
problems.push(`camera.aperture must be >= 0 (blur px per unit depth) \u2014 0 disables depth of field`);
|
|
565
569
|
}
|
|
566
570
|
}
|
|
567
571
|
}
|
package/dist/diff.js
CHANGED
|
@@ -155,6 +155,8 @@ function compileScene(ir) {
|
|
|
155
155
|
initialValues.set(key("camera", "zoom"), cam.zoom ?? 1);
|
|
156
156
|
initialValues.set(key("camera", "rotation"), cam.rotation ?? 0);
|
|
157
157
|
if (cam.perspective !== void 0) initialValues.set(key("camera", "perspective"), cam.perspective);
|
|
158
|
+
if (cam.focus !== void 0) initialValues.set(key("camera", "focus"), cam.focus);
|
|
159
|
+
if (cam.aperture !== void 0) initialValues.set(key("camera", "aperture"), cam.aperture);
|
|
158
160
|
}
|
|
159
161
|
const segments = /* @__PURE__ */ new Map();
|
|
160
162
|
const motionPaths = /* @__PURE__ */ new Map();
|
|
@@ -350,7 +352,7 @@ var BLEND_MODES = /* @__PURE__ */ new Set([
|
|
|
350
352
|
]);
|
|
351
353
|
var IMAGE_FITS = /* @__PURE__ */ new Set(["fill", "cover"]);
|
|
352
354
|
var COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "scaleX", "scaleY", "skewX", "skewY", "z", "rotateX", "rotateY", "anchor", "fixed", ...FX_PROPS];
|
|
353
|
-
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective"];
|
|
355
|
+
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective", "focus", "aperture"];
|
|
354
356
|
var PROPS_BY_TYPE = {
|
|
355
357
|
rect: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth", "radius"],
|
|
356
358
|
ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
|
|
@@ -568,6 +570,8 @@ function validateScene(ir) {
|
|
|
568
570
|
problems.push(`camera.${key2} must be a number`);
|
|
569
571
|
} else if (key2 === "perspective" && value <= 0) {
|
|
570
572
|
problems.push(`camera.perspective must be > 0 (focal distance in px) \u2014 drop it to disable perspective`);
|
|
573
|
+
} else if (key2 === "aperture" && value < 0) {
|
|
574
|
+
problems.push(`camera.aperture must be >= 0 (blur px per unit depth) \u2014 0 disables depth of field`);
|
|
571
575
|
}
|
|
572
576
|
}
|
|
573
577
|
}
|
package/dist/index.js
CHANGED
|
@@ -159,6 +159,8 @@ function compileScene(ir) {
|
|
|
159
159
|
initialValues.set(key("camera", "zoom"), cam.zoom ?? 1);
|
|
160
160
|
initialValues.set(key("camera", "rotation"), cam.rotation ?? 0);
|
|
161
161
|
if (cam.perspective !== void 0) initialValues.set(key("camera", "perspective"), cam.perspective);
|
|
162
|
+
if (cam.focus !== void 0) initialValues.set(key("camera", "focus"), cam.focus);
|
|
163
|
+
if (cam.aperture !== void 0) initialValues.set(key("camera", "aperture"), cam.aperture);
|
|
162
164
|
}
|
|
163
165
|
const segments = /* @__PURE__ */ new Map();
|
|
164
166
|
const motionPaths = /* @__PURE__ */ new Map();
|
|
@@ -354,7 +356,7 @@ var BLEND_MODES = /* @__PURE__ */ new Set([
|
|
|
354
356
|
]);
|
|
355
357
|
var IMAGE_FITS = /* @__PURE__ */ new Set(["fill", "cover"]);
|
|
356
358
|
var COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "scaleX", "scaleY", "skewX", "skewY", "z", "rotateX", "rotateY", "anchor", "fixed", ...FX_PROPS];
|
|
357
|
-
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective"];
|
|
359
|
+
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective", "focus", "aperture"];
|
|
358
360
|
var PROPS_BY_TYPE = {
|
|
359
361
|
rect: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth", "radius"],
|
|
360
362
|
ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
|
|
@@ -572,6 +574,8 @@ function validateScene(ir) {
|
|
|
572
574
|
problems.push(`camera.${key2} must be a number`);
|
|
573
575
|
} else if (key2 === "perspective" && value <= 0) {
|
|
574
576
|
problems.push(`camera.perspective must be > 0 (focal distance in px) \u2014 drop it to disable perspective`);
|
|
577
|
+
} else if (key2 === "aperture" && value < 0) {
|
|
578
|
+
problems.push(`camera.aperture must be >= 0 (blur px per unit depth) \u2014 0 disables depth of field`);
|
|
575
579
|
}
|
|
576
580
|
}
|
|
577
581
|
}
|
|
@@ -3214,6 +3218,14 @@ function evaluate(compiled, t) {
|
|
|
3214
3218
|
const dPersp = persp ? num("camera", "perspective", 0) : 0;
|
|
3215
3219
|
const vx = persp ? compiled.ir.size.width / 2 : 0;
|
|
3216
3220
|
const vy = persp ? compiled.ir.size.height / 2 : 0;
|
|
3221
|
+
const aperture = persp ? num("camera", "aperture", 0) : 0;
|
|
3222
|
+
const focus = persp ? num("camera", "focus", 0) : 0;
|
|
3223
|
+
const dofFx = (fx, depth, project) => {
|
|
3224
|
+
if (!project || aperture <= 0) return fx;
|
|
3225
|
+
const extra = aperture * Math.abs(depth - focus);
|
|
3226
|
+
if (extra <= 0) return fx;
|
|
3227
|
+
return { ...fx, blur: z0((fx.blur ?? 0) + extra) };
|
|
3228
|
+
};
|
|
3217
3229
|
const walk = (node, parent, parentOpacity, clips, zAcc, project) => {
|
|
3218
3230
|
const id = node.id;
|
|
3219
3231
|
const clipSpread = clips.length > 0 ? { clips } : void 0;
|
|
@@ -3236,7 +3248,8 @@ function evaluate(compiled, t) {
|
|
|
3236
3248
|
y2: y1 + (num(id, "y2", node.props.y2) - y1) * progress,
|
|
3237
3249
|
stroke: str(id, "stroke", node.props.stroke),
|
|
3238
3250
|
strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1),
|
|
3239
|
-
|
|
3251
|
+
// a line carries no z of its own — DOF uses the inherited subtree depth
|
|
3252
|
+
...dofFx(fx, zAcc, project),
|
|
3240
3253
|
...clipSpread
|
|
3241
3254
|
});
|
|
3242
3255
|
return;
|
|
@@ -3273,6 +3286,7 @@ function evaluate(compiled, t) {
|
|
|
3273
3286
|
const tilted = rotX !== 0 || rotY !== 0 ? tiltSkew(m, rotX, rotY, hw, hh, dPersp) : m;
|
|
3274
3287
|
return projectDepth(tilted, depth, vx, vy, dPersp);
|
|
3275
3288
|
};
|
|
3289
|
+
const leafFx = dofFx(fx, depth, project);
|
|
3276
3290
|
switch (node.type) {
|
|
3277
3291
|
case "group": {
|
|
3278
3292
|
const clipTf = projDraw(matrix, 0, 0);
|
|
@@ -3313,7 +3327,7 @@ function evaluate(compiled, t) {
|
|
|
3313
3327
|
...fill !== void 0 && { fill },
|
|
3314
3328
|
...stroke !== void 0 && { stroke, strokeWidth },
|
|
3315
3329
|
...node.type === "rect" && { radius: num(id, "radius", node.props.radius ?? 0) },
|
|
3316
|
-
...
|
|
3330
|
+
...leafFx,
|
|
3317
3331
|
...clipSpread
|
|
3318
3332
|
});
|
|
3319
3333
|
return;
|
|
@@ -3333,7 +3347,7 @@ function evaluate(compiled, t) {
|
|
|
3333
3347
|
offsetX: -width * ax,
|
|
3334
3348
|
offsetY: -height * ay,
|
|
3335
3349
|
...node.props.fit && node.props.fit !== "fill" ? { fit: node.props.fit } : {},
|
|
3336
|
-
...
|
|
3350
|
+
...leafFx,
|
|
3337
3351
|
...clipSpread
|
|
3338
3352
|
});
|
|
3339
3353
|
return;
|
|
@@ -3360,7 +3374,7 @@ function evaluate(compiled, t) {
|
|
|
3360
3374
|
offsetY: -height * ay,
|
|
3361
3375
|
frame,
|
|
3362
3376
|
...node.props.fit && node.props.fit !== "fill" ? { fit: node.props.fit } : {},
|
|
3363
|
-
...
|
|
3377
|
+
...leafFx,
|
|
3364
3378
|
...clipSpread
|
|
3365
3379
|
});
|
|
3366
3380
|
return;
|
|
@@ -3385,7 +3399,7 @@ function evaluate(compiled, t) {
|
|
|
3385
3399
|
...fill !== void 0 && { fill },
|
|
3386
3400
|
...stroke !== void 0 && { stroke, strokeWidth: num(id, "strokeWidth", node.props.strokeWidth ?? 1) },
|
|
3387
3401
|
...needsBox && { bbox: pathBBox(dStr) },
|
|
3388
|
-
...
|
|
3402
|
+
...leafFx,
|
|
3389
3403
|
...clipSpread
|
|
3390
3404
|
});
|
|
3391
3405
|
return;
|
|
@@ -3412,7 +3426,7 @@ function evaluate(compiled, t) {
|
|
|
3412
3426
|
letterSpacing: num(id, "letterSpacing", node.props.letterSpacing ?? 0),
|
|
3413
3427
|
align: TEXT_ALIGN[ax] ?? "left",
|
|
3414
3428
|
baseline: TEXT_BASELINE[ay] ?? "top",
|
|
3415
|
-
...
|
|
3429
|
+
...leafFx,
|
|
3416
3430
|
...clipSpread
|
|
3417
3431
|
});
|
|
3418
3432
|
return;
|
package/dist/labels.js
CHANGED
|
@@ -143,6 +143,8 @@ function compileScene(ir) {
|
|
|
143
143
|
initialValues.set(key("camera", "zoom"), cam.zoom ?? 1);
|
|
144
144
|
initialValues.set(key("camera", "rotation"), cam.rotation ?? 0);
|
|
145
145
|
if (cam.perspective !== void 0) initialValues.set(key("camera", "perspective"), cam.perspective);
|
|
146
|
+
if (cam.focus !== void 0) initialValues.set(key("camera", "focus"), cam.focus);
|
|
147
|
+
if (cam.aperture !== void 0) initialValues.set(key("camera", "aperture"), cam.aperture);
|
|
146
148
|
}
|
|
147
149
|
const segments = /* @__PURE__ */ new Map();
|
|
148
150
|
const motionPaths = /* @__PURE__ */ new Map();
|
|
@@ -338,7 +340,7 @@ var BLEND_MODES = /* @__PURE__ */ new Set([
|
|
|
338
340
|
]);
|
|
339
341
|
var IMAGE_FITS = /* @__PURE__ */ new Set(["fill", "cover"]);
|
|
340
342
|
var COMMON_PROPS = ["x", "y", "opacity", "rotation", "scale", "scaleX", "scaleY", "skewX", "skewY", "z", "rotateX", "rotateY", "anchor", "fixed", ...FX_PROPS];
|
|
341
|
-
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective"];
|
|
343
|
+
var CAMERA_PROPS = ["x", "y", "zoom", "rotation", "perspective", "focus", "aperture"];
|
|
342
344
|
var PROPS_BY_TYPE = {
|
|
343
345
|
rect: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth", "radius"],
|
|
344
346
|
ellipse: [...COMMON_PROPS, "width", "height", "fill", "stroke", "strokeWidth"],
|
|
@@ -556,6 +558,8 @@ function validateScene(ir) {
|
|
|
556
558
|
problems.push(`camera.${key2} must be a number`);
|
|
557
559
|
} else if (key2 === "perspective" && value <= 0) {
|
|
558
560
|
problems.push(`camera.perspective must be > 0 (focal distance in px) \u2014 drop it to disable perspective`);
|
|
561
|
+
} else if (key2 === "aperture" && value < 0) {
|
|
562
|
+
problems.push(`camera.aperture must be >= 0 (blur px per unit depth) \u2014 0 disables depth of field`);
|
|
559
563
|
}
|
|
560
564
|
}
|
|
561
565
|
}
|
package/dist/types/ir.d.ts
CHANGED
|
@@ -461,6 +461,17 @@ export interface CameraIR {
|
|
|
461
461
|
* focal pull). A node BEHIND the camera (`perspective + z <= 0`) is culled.
|
|
462
462
|
*/
|
|
463
463
|
perspective?: number;
|
|
464
|
+
/**
|
|
465
|
+
* Depth of field (requires `perspective`). `aperture` is the blur strength —
|
|
466
|
+
* screen-pixels of gaussian blur added per unit of depth away from the focal
|
|
467
|
+
* plane; absent / 0 ⇒ no DOF (byte-identical). `focus` is the in-focus depth
|
|
468
|
+
* (same units as a node's world `z`, default 0 = the camera plane). A drawn op
|
|
469
|
+
* at depth `d` gains `aperture · |d − focus|` blur on top of any authored blur,
|
|
470
|
+
* so far (and near) layers soften while the focal plane stays sharp. Both are
|
|
471
|
+
* keyframable — animate `focus` for a rack focus, `aperture` for an iris pull.
|
|
472
|
+
*/
|
|
473
|
+
focus?: number;
|
|
474
|
+
aperture?: number;
|
|
464
475
|
}
|
|
465
476
|
export interface SceneIR {
|
|
466
477
|
version: 1;
|
package/guides/edsl-guide.md
CHANGED
|
@@ -215,6 +215,12 @@ scene({
|
|
|
215
215
|
- A node needs a base value to tween (`rotateY: 0` on the card before tweening it to 360).
|
|
216
216
|
- A tilted **group** foreshortens its whole subtree (cos folds into children). Clips project
|
|
217
217
|
by the group's depth. A `fixed` HUD ignores depth (perspective is part of the camera).
|
|
218
|
+
- **Depth of field** (needs `perspective`): add `camera.aperture` (blur px per unit depth) and
|
|
219
|
+
`camera.focus` (the in-focus `z`, default 0). A layer at depth `d` softens by
|
|
220
|
+
`aperture·|d − focus|` while the focal plane stays sharp; keyframe `focus` for a **rack focus**,
|
|
221
|
+
`aperture` for an iris pull. Absent/`0` ⇒ no blur. HUD/UI text should be `fixed` so it stays
|
|
222
|
+
crisp (a `fixed` node opts out of DOF too). It feeds the same `blur` op, so it composes with an
|
|
223
|
+
authored `blur`.
|
|
218
224
|
- **Limits (honest):** `rotateX`/`rotateY` are an affine approximation (cos-foreshorten +
|
|
219
225
|
keystone skew) — a single rotated quad is really a trapezoid Canvas 2D can't draw, so it
|
|
220
226
|
reads as a flip/tilt, not a pixel-true 3D face (that needs WebGL). Depth positioning
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reframe-video",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.16",
|
|
4
4
|
"description": "Declarative motion graphics that AI can write and humans can tweak — human edits survive AI regeneration. Deterministic mp4 renders from a plain-data scene format.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"motion-graphics",
|