effect-motion 0.2.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/README.md +40 -0
- package/dist/Camera.d.ts +49 -0
- package/dist/Camera.js +33 -0
- package/dist/Entity.d.ts +40 -0
- package/dist/Entity.js +32 -0
- package/dist/Fonts.d.ts +31 -0
- package/dist/Fonts.js +11 -0
- package/dist/Instance.d.ts +16 -0
- package/dist/Instance.js +18 -0
- package/dist/Motion.d.ts +74 -0
- package/dist/Motion.js +125 -0
- package/dist/Phaser.d.ts +65 -0
- package/dist/Phaser.js +170 -0
- package/dist/Physics.d.ts +78 -0
- package/dist/Physics.js +117 -0
- package/dist/Renderer.d.ts +69 -0
- package/dist/Renderer.js +90 -0
- package/dist/Runner.d.ts +360 -0
- package/dist/Runner.js +257 -0
- package/dist/Scene.d.ts +241 -0
- package/dist/Scene.js +454 -0
- package/dist/Time.d.ts +38 -0
- package/dist/Time.js +43 -0
- package/dist/Timing.d.ts +96 -0
- package/dist/Timing.js +151 -0
- package/dist/demo.d.ts +186 -0
- package/dist/demo.js +76 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/particles/Particle.d.ts +91 -0
- package/dist/particles/Particle.js +1 -0
- package/dist/particles/ParticleField.d.ts +170 -0
- package/dist/particles/ParticleField.js +69 -0
- package/dist/particles/Prng.d.ts +28 -0
- package/dist/particles/Prng.js +43 -0
- package/dist/particles/constructors.d.ts +78 -0
- package/dist/particles/constructors.js +15 -0
- package/dist/particles/index.d.ts +6 -0
- package/dist/particles/index.js +6 -0
- package/dist/particles/overLife.d.ts +16 -0
- package/dist/particles/overLife.js +21 -0
- package/dist/particles/render.d.ts +13 -0
- package/dist/particles/render.js +33 -0
- package/dist/particles/simulate.d.ts +39 -0
- package/dist/particles/simulate.js +81 -0
- package/dist/particles/step.d.ts +24 -0
- package/dist/particles/step.js +167 -0
- package/dist/shapes/Circle.d.ts +37 -0
- package/dist/shapes/Circle.js +9 -0
- package/dist/shapes/Ellipse.d.ts +41 -0
- package/dist/shapes/Ellipse.js +10 -0
- package/dist/shapes/Group.d.ts +150 -0
- package/dist/shapes/Group.js +82 -0
- package/dist/shapes/Layer.d.ts +9 -0
- package/dist/shapes/Layer.js +23 -0
- package/dist/shapes/Line.d.ts +47 -0
- package/dist/shapes/Line.js +30 -0
- package/dist/shapes/Path.d.ts +38 -0
- package/dist/shapes/Path.js +13 -0
- package/dist/shapes/Rect.d.ts +41 -0
- package/dist/shapes/Rect.js +10 -0
- package/dist/shapes/Shape2D.d.ts +40 -0
- package/dist/shapes/Shape2D.js +41 -0
- package/dist/shapes/Square.d.ts +37 -0
- package/dist/shapes/Square.js +11 -0
- package/dist/shapes/Text.d.ts +60 -0
- package/dist/shapes/Text.js +24 -0
- package/dist/shapes/index.d.ts +10 -0
- package/dist/shapes/index.js +10 -0
- package/dist/svg/SvgDomRenderer.d.ts +28 -0
- package/dist/svg/SvgDomRenderer.js +50 -0
- package/dist/svg/SvgNode.d.ts +13 -0
- package/dist/svg/SvgNode.js +18 -0
- package/dist/svg/SvgRenderer.d.ts +22 -0
- package/dist/svg/SvgRenderer.js +20 -0
- package/dist/svg/camera.d.ts +21 -0
- package/dist/svg/camera.js +43 -0
- package/dist/svg/index.d.ts +6 -0
- package/dist/svg/index.js +6 -0
- package/dist/svg/layers.d.ts +18 -0
- package/dist/svg/layers.js +13 -0
- package/dist/svg/shapes.d.ts +1089 -0
- package/dist/svg/shapes.js +119 -0
- package/package.json +51 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Layer } from "effect";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import { ParticleField } from "../particles/ParticleField";
|
|
4
|
+
import { particleField } from "../particles/render";
|
|
5
|
+
import * as Shapes from "../shapes";
|
|
6
|
+
import { entityRendererLayer } from "./layers";
|
|
7
|
+
// absent props are omitted, never emitted with placeholders; opacity 1
|
|
8
|
+
// (the SVG default) is omitted to keep output minimal
|
|
9
|
+
const styleAttrs = (data) => {
|
|
10
|
+
const attrs = {};
|
|
11
|
+
if (data.fill !== undefined) {
|
|
12
|
+
attrs.fill = data.fill;
|
|
13
|
+
}
|
|
14
|
+
if (data.stroke !== undefined) {
|
|
15
|
+
attrs.stroke = data.stroke;
|
|
16
|
+
}
|
|
17
|
+
if (data.strokeWidth !== undefined) {
|
|
18
|
+
attrs["stroke-width"] = data.strokeWidth;
|
|
19
|
+
}
|
|
20
|
+
if (data.opacity !== 1) {
|
|
21
|
+
attrs.opacity = data.opacity;
|
|
22
|
+
}
|
|
23
|
+
return attrs;
|
|
24
|
+
};
|
|
25
|
+
export const circle = ({ data, }) => Effect.succeed({
|
|
26
|
+
tag: "circle",
|
|
27
|
+
props: { cx: data.x, cy: data.y, r: data.radius, ...styleAttrs(data) },
|
|
28
|
+
});
|
|
29
|
+
export const rect = ({ data, }) => Effect.succeed({
|
|
30
|
+
tag: "rect",
|
|
31
|
+
props: {
|
|
32
|
+
x: data.x,
|
|
33
|
+
y: data.y,
|
|
34
|
+
width: data.width,
|
|
35
|
+
height: data.height,
|
|
36
|
+
...styleAttrs(data),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
export const square = ({ data, }) => Effect.succeed({
|
|
40
|
+
tag: "rect",
|
|
41
|
+
props: {
|
|
42
|
+
x: data.x,
|
|
43
|
+
y: data.y,
|
|
44
|
+
width: data.size,
|
|
45
|
+
height: data.size,
|
|
46
|
+
...styleAttrs(data),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
export const ellipse = ({ data }) => Effect.succeed({
|
|
50
|
+
tag: "ellipse",
|
|
51
|
+
props: {
|
|
52
|
+
cx: data.x,
|
|
53
|
+
cy: data.y,
|
|
54
|
+
rx: data.rx,
|
|
55
|
+
ry: data.ry,
|
|
56
|
+
...styleAttrs(data),
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
export const line = ({ data, }) => Effect.succeed({
|
|
60
|
+
tag: "line",
|
|
61
|
+
props: {
|
|
62
|
+
x1: data.x,
|
|
63
|
+
y1: data.y,
|
|
64
|
+
x2: data.x2,
|
|
65
|
+
y2: data.y2,
|
|
66
|
+
...styleAttrs(data),
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
export const path = ({ data, }) => Effect.succeed({
|
|
70
|
+
tag: "path",
|
|
71
|
+
props: {
|
|
72
|
+
d: data.d,
|
|
73
|
+
// x/y offset the whole path; translate only when it does something
|
|
74
|
+
...(data.x !== 0 || data.y !== 0
|
|
75
|
+
? { transform: `translate(${data.x} ${data.y})` }
|
|
76
|
+
: {}),
|
|
77
|
+
...styleAttrs(data),
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
export const text = ({ data, }) => Effect.succeed({
|
|
81
|
+
tag: "text",
|
|
82
|
+
props: {
|
|
83
|
+
x: data.x,
|
|
84
|
+
y: data.y,
|
|
85
|
+
"font-size": data.fontSize,
|
|
86
|
+
"font-family": data.fontFamily,
|
|
87
|
+
...(data.textAnchor !== undefined
|
|
88
|
+
? { "text-anchor": data.textAnchor }
|
|
89
|
+
: {}),
|
|
90
|
+
...(data.baseline !== undefined
|
|
91
|
+
? { "dominant-baseline": data.baseline }
|
|
92
|
+
: {}),
|
|
93
|
+
...styleAttrs(data),
|
|
94
|
+
},
|
|
95
|
+
// plain string content; the string sink escapes it
|
|
96
|
+
children: data.text,
|
|
97
|
+
});
|
|
98
|
+
// a group paints nothing itself: one <g> positioning its rendered children
|
|
99
|
+
export const group = ({ data, children, }) => {
|
|
100
|
+
const transform = Shapes.resolvedTransform(data);
|
|
101
|
+
return Effect.succeed({
|
|
102
|
+
tag: "g",
|
|
103
|
+
props: {
|
|
104
|
+
...(Shapes.isIdentityTransform(transform)
|
|
105
|
+
? {}
|
|
106
|
+
: {
|
|
107
|
+
transform: `matrix(${transform.a} ${transform.b} ${transform.c} ${transform.d} ${transform.e} ${transform.f})`,
|
|
108
|
+
}),
|
|
109
|
+
...styleAttrs(data),
|
|
110
|
+
},
|
|
111
|
+
children,
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
// a parallax layer is a bare container: one <g> holding its children. It has
|
|
115
|
+
// no position/opacity of its own; `depth` is consumed by the sink (svg/camera),
|
|
116
|
+
// not emitted as an attribute here.
|
|
117
|
+
export const layer = ({ children, }) => Effect.succeed({ tag: "g", props: {}, children });
|
|
118
|
+
/** Every built-in shape registered with both sinks. */
|
|
119
|
+
export const shapesLayer = Layer.mergeAll(entityRendererLayer(Shapes.Circle, circle), entityRendererLayer(Shapes.Rect, rect), entityRendererLayer(Shapes.Square, square), entityRendererLayer(Shapes.Ellipse, ellipse), entityRendererLayer(Shapes.Line, line), entityRendererLayer(Shapes.Path, path), entityRendererLayer(Shapes.Group, group), entityRendererLayer(Shapes.Layer, layer), entityRendererLayer(Shapes.Text, text), entityRendererLayer(ParticleField, particleField));
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "effect-motion",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Deterministic, frame-exact motion graphics in code, composed with Effect",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/julia-script/effect-motion.git",
|
|
10
|
+
"directory": "packages/motion"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/julia-script/effect-motion#readme",
|
|
13
|
+
"bugs": "https://github.com/julia-script/effect-motion/issues",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"effect",
|
|
16
|
+
"motion",
|
|
17
|
+
"animation",
|
|
18
|
+
"motion-graphics",
|
|
19
|
+
"svg",
|
|
20
|
+
"deterministic"
|
|
21
|
+
],
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"effect": ">=4.0.0-beta.94"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^26.1.1",
|
|
39
|
+
"effect": "4.0.0-beta.94",
|
|
40
|
+
"happy-dom": "^20.10.6",
|
|
41
|
+
"tsx": "^4.23.0",
|
|
42
|
+
"typescript": "^7.0.2",
|
|
43
|
+
"vitest": "^4.1.10"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc -p tsconfig.build.json",
|
|
47
|
+
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
|
|
48
|
+
"test": "vitest run",
|
|
49
|
+
"check": "tsc --noEmit"
|
|
50
|
+
}
|
|
51
|
+
}
|