@meltemi/diagrams-motion 0.0.0-stage → 1.9.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 -0
- package/README.md +50 -2
- package/dist/css.d.ts +12 -0
- package/dist/css.d.ts.map +1 -0
- package/dist/css.js +194 -0
- package/dist/css.js.map +1 -0
- package/dist/drill.d.ts +41 -0
- package/dist/drill.d.ts.map +1 -0
- package/dist/drill.js +145 -0
- package/dist/drill.js.map +1 -0
- package/dist/frames.d.ts +31 -0
- package/dist/frames.d.ts.map +1 -0
- package/dist/frames.js +169 -0
- package/dist/frames.js.map +1 -0
- package/dist/geometry.d.ts +15 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +68 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/plan.d.ts +72 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +124 -0
- package/dist/plan.js.map +1 -0
- package/dist/story.d.ts +85 -0
- package/dist/story.d.ts.map +1 -0
- package/dist/story.js +501 -0
- package/dist/story.js.map +1 -0
- package/dist/time.d.ts +3 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +9 -0
- package/dist/time.js.map +1 -0
- package/package.json +40 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Architecture Studio contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,51 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @meltemi/diagrams-motion
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Motion on a deterministic clock: effects (flow particles, moving dashes, pulses, traces) planned on a
|
|
4
|
+
laid-out scene, the frame at any time, the CSS-animated SVG profile, and the timeline and frames
|
|
5
|
+
of stories.
|
|
6
|
+
|
|
7
|
+
It is part of [Meltemi Diagrams](https://github.com/askenaz-dev/meltemi-diagrams#readme), diagrams as code with a canvas, motion and
|
|
8
|
+
exports. Every package of the product has the same version.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @meltemi/diagrams-motion
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Node 22.12.0 or later. The package is an ES module with type declarations.
|
|
17
|
+
|
|
18
|
+
## Use
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { layoutDiagram } from "@meltemi/diagrams-layout";
|
|
22
|
+
import { createElkEngine } from "@meltemi/diagrams-layout-elk";
|
|
23
|
+
import { compile } from "@meltemi/diagrams-model";
|
|
24
|
+
import { planMotion, sceneAt } from "@meltemi/diagrams-motion";
|
|
25
|
+
import { renderSvg } from "@meltemi/diagrams-render";
|
|
26
|
+
|
|
27
|
+
const text = `language "0.2"
|
|
28
|
+
|
|
29
|
+
diagram shop: flow {
|
|
30
|
+
web -> api: "HTTPS" as call
|
|
31
|
+
animate call { effect flow; duration 1200ms; repeat forever }
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const compilation = compile(text);
|
|
36
|
+
const diagram = compilation.document.diagrams[0]!;
|
|
37
|
+
const { scene } = layoutDiagram(compilation, diagram, { engine: createElkEngine() });
|
|
38
|
+
const plan = planMotion(diagram, scene!);
|
|
39
|
+
const frame = renderSvg(sceneAt(scene!, plan, 600)); // the picture at 600 ms
|
|
40
|
+
console.log(plan.effects.length, frame.length > 0); // 1 true
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Documentation
|
|
44
|
+
|
|
45
|
+
- [Motion](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/docs/language/motion.md)
|
|
46
|
+
- [Stories](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/docs/language/stories.md)
|
|
47
|
+
- [All documentation](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/docs/README.md)
|
|
48
|
+
|
|
49
|
+
## Licence
|
|
50
|
+
|
|
51
|
+
MIT. Third-party components and their licences are listed in [THIRD_PARTY_LICENSES.md](https://github.com/askenaz-dev/meltemi-diagrams/blob/main/THIRD_PARTY_LICENSES.md).
|
package/dist/css.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Scene } from "@meltemi/diagrams-layout";
|
|
2
|
+
import { type MotionPlan } from "./plan.js";
|
|
3
|
+
/** The class every animated element carries, so reduced motion can stop them all. */
|
|
4
|
+
export declare const MOTION_CLASS = "mdg-m";
|
|
5
|
+
/**
|
|
6
|
+
* The scene with the animated SVG profile: a CSS style sheet and classes on the targets and on
|
|
7
|
+
* overlays that are invisible outside their animations, so the drawing without effects is what
|
|
8
|
+
* shows before a delay, after the last cycle, with reduced motion and where CSS animation is not
|
|
9
|
+
* supported. CSS only: opacity, motion paths, dash offsets and scale, all linear.
|
|
10
|
+
*/
|
|
11
|
+
export declare function animatedScene(scene: Scene, plan: MotionPlan): Scene;
|
|
12
|
+
//# sourceMappingURL=css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAa,MAAM,0BAA0B,CAAC;AAUjE,OAAO,EAOL,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAEnB,qFAAqF;AACrF,eAAO,MAAM,YAAY,UAAU,CAAC;AAuDpC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,GAAG,KAAK,CAoJnE"}
|
package/dist/css.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { circlePath, particleRadius, round, roundedRectPath, trackLength, trackPath, } from "./geometry.js";
|
|
2
|
+
import { beforeLabel, outlineIndex, targetKey, traceTrack, withTargets } from "./frames.js";
|
|
3
|
+
import { DASH_PATTERN, DASH_PERIOD, GLOW, HALO, TRACE, } from "./plan.js";
|
|
4
|
+
/** The class every animated element carries, so reduced motion can stop them all. */
|
|
5
|
+
export const MOTION_CLASS = "mdg-m";
|
|
6
|
+
const percent = (value) => `${round(value * 100)}%`;
|
|
7
|
+
/** `animation` of an effect: one keyframe set, linear, its delay and repeat, no fill mode. */
|
|
8
|
+
function animation(name, effect) {
|
|
9
|
+
const count = effect.repeat === "forever" ? "infinite" : String(effect.repeat);
|
|
10
|
+
return `animation: ${name} ${effect.durationMs}ms linear ${effect.delayMs}ms ${count} normal none;`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Keyframes of particle `i` of `k`: it starts at `i/k` of the track, reaches the end, jumps to the
|
|
14
|
+
* start and comes back to `i/k`, so every particle shares the effect's delay.
|
|
15
|
+
*/
|
|
16
|
+
function particleKeyframes(name, k, i, reverse) {
|
|
17
|
+
const at = (d) => `offset-distance: ${percent(reverse ? 1 - d : d)}; opacity: 1;`;
|
|
18
|
+
const s = i / k;
|
|
19
|
+
if (i === 0)
|
|
20
|
+
return `@keyframes ${name} { 0% { ${at(0)} } 100% { ${at(1)} } }`;
|
|
21
|
+
const turn = 1 - s;
|
|
22
|
+
return [
|
|
23
|
+
`@keyframes ${name} {`,
|
|
24
|
+
` 0% { ${at(s)} }`,
|
|
25
|
+
` ${percent(turn)} { ${at(1)} }`,
|
|
26
|
+
` ${round(turn * 100) + 0.001}% { ${at(0)} }`,
|
|
27
|
+
` 100% { ${at(s)} }`,
|
|
28
|
+
"}",
|
|
29
|
+
].join("\n");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Keyframes of a trace's line: one dash as long as the track, offset from the whole length to
|
|
33
|
+
* nothing while it grows, then the lit line fades. Per effect, since lengths differ.
|
|
34
|
+
*/
|
|
35
|
+
function traceKeyframes(name, length) {
|
|
36
|
+
const L = round(length);
|
|
37
|
+
const at = (offset, opacity) => `stroke-dasharray: ${L} ${L}; stroke-dashoffset: ${round(offset)}; opacity: ${opacity};`;
|
|
38
|
+
return [
|
|
39
|
+
`@keyframes ${name} {`,
|
|
40
|
+
` 0% { ${at(L, 1)} }`,
|
|
41
|
+
` ${percent(TRACE.fill)} { ${at(0, 1)} }`,
|
|
42
|
+
` 100% { ${at(0, 0)} }`,
|
|
43
|
+
"}",
|
|
44
|
+
].join("\n");
|
|
45
|
+
}
|
|
46
|
+
/** Keyframes of a trace's head dot, which rides the track while the line grows, then fades. */
|
|
47
|
+
const TRACE_DOT_KEYFRAMES = [
|
|
48
|
+
"@keyframes mdg-trace-dot {",
|
|
49
|
+
" 0% { offset-distance: 0%; opacity: 1; }",
|
|
50
|
+
` ${percent(TRACE.fill)} { offset-distance: 100%; opacity: 1; }`,
|
|
51
|
+
" 100% { offset-distance: 100%; opacity: 0; }",
|
|
52
|
+
"}",
|
|
53
|
+
].join("\n");
|
|
54
|
+
/**
|
|
55
|
+
* The scene with the animated SVG profile: a CSS style sheet and classes on the targets and on
|
|
56
|
+
* overlays that are invisible outside their animations, so the drawing without effects is what
|
|
57
|
+
* shows before a delay, after the last cycle, with reduced motion and where CSS animation is not
|
|
58
|
+
* supported. CSS only: opacity, motion paths, dash offsets and scale, all linear.
|
|
59
|
+
*/
|
|
60
|
+
export function animatedScene(scene, plan) {
|
|
61
|
+
if (plan.effects.length === 0)
|
|
62
|
+
return scene;
|
|
63
|
+
const rules = [];
|
|
64
|
+
const keyframes = new Map();
|
|
65
|
+
const particleRules = [];
|
|
66
|
+
const dashes = new Map();
|
|
67
|
+
const overlays = [];
|
|
68
|
+
const halos = [];
|
|
69
|
+
const traces = new Map();
|
|
70
|
+
for (const effect of plan.effects) {
|
|
71
|
+
const own = `mdg-e${effect.index}`;
|
|
72
|
+
if (effect.effect === "trace") {
|
|
73
|
+
// The line and its dot go into the relation's group, under its label, as in frames.
|
|
74
|
+
const points = traceTrack(effect);
|
|
75
|
+
const name = `mdg-trace-${effect.index}`;
|
|
76
|
+
keyframes.set(name, traceKeyframes(name, trackLength(points)));
|
|
77
|
+
keyframes.set("mdg-trace-dot", TRACE_DOT_KEYFRAMES);
|
|
78
|
+
rules.push(`.${own} { ${animation(name, effect)} }`);
|
|
79
|
+
particleRules.push(`.${own}-dot { offset-path: path("${trackPath(points)}"); offset-rotate: 0deg; ${animation("mdg-trace-dot", effect)} }`);
|
|
80
|
+
traces.set(targetKey(effect.role, effect.target), [
|
|
81
|
+
{
|
|
82
|
+
kind: "polyline",
|
|
83
|
+
points,
|
|
84
|
+
stroke: effect.color,
|
|
85
|
+
strokeWidth: round(effect.width + TRACE.extra),
|
|
86
|
+
dashed: false,
|
|
87
|
+
opacity: 0,
|
|
88
|
+
className: `${MOTION_CLASS} ${own}`,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
kind: "path",
|
|
92
|
+
d: circlePath(0, 0, effect.width + TRACE.dot),
|
|
93
|
+
fill: effect.color,
|
|
94
|
+
stroke: "none",
|
|
95
|
+
strokeWidth: 0,
|
|
96
|
+
dashed: false,
|
|
97
|
+
opacity: 0,
|
|
98
|
+
className: `${MOTION_CLASS} ${own}-dot`,
|
|
99
|
+
},
|
|
100
|
+
]);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (effect.effect === "dash") {
|
|
104
|
+
dashes.set(targetKey(effect.role, effect.target), effect);
|
|
105
|
+
const name = effect.reverse ? "mdg-dash-reverse" : "mdg-dash";
|
|
106
|
+
keyframes.set(name, `@keyframes ${name} { from { stroke-dasharray: ${DASH_PATTERN.join(" ")}; stroke-dashoffset: 0; } to { stroke-dasharray: ${DASH_PATTERN.join(" ")}; stroke-dashoffset: ${effect.reverse ? DASH_PERIOD : -DASH_PERIOD}; } }`);
|
|
107
|
+
rules.push(`.${own} { ${animation(name, effect)} }`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (effect.effect === "pulse") {
|
|
111
|
+
if (effect.bounds) {
|
|
112
|
+
keyframes.set("mdg-halo", `@keyframes mdg-halo { from { opacity: ${HALO.opacity}; transform: scale(1); } to { opacity: 0; transform: scale(${1 + HALO.scale}); } }`);
|
|
113
|
+
rules.push(`.${own} { transform-box: fill-box; transform-origin: center; ${animation("mdg-halo", effect)} }`);
|
|
114
|
+
halos.push({
|
|
115
|
+
kind: "path",
|
|
116
|
+
d: roundedRectPath(effect.bounds),
|
|
117
|
+
fill: "none",
|
|
118
|
+
stroke: effect.color,
|
|
119
|
+
strokeWidth: HALO.width,
|
|
120
|
+
dashed: false,
|
|
121
|
+
opacity: 0,
|
|
122
|
+
className: `${MOTION_CLASS} ${own}`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
keyframes.set("mdg-glow", `@keyframes mdg-glow { from { opacity: ${GLOW.opacity}; } to { opacity: 0; } }`);
|
|
127
|
+
rules.push(`.${own} { ${animation("mdg-glow", effect)} }`);
|
|
128
|
+
halos.push({
|
|
129
|
+
kind: "polyline",
|
|
130
|
+
points: effect.track.map((p) => ({ x: round(p.x), y: round(p.y) })),
|
|
131
|
+
stroke: effect.color,
|
|
132
|
+
strokeWidth: effect.width + GLOW.extra,
|
|
133
|
+
dashed: false,
|
|
134
|
+
opacity: 0,
|
|
135
|
+
className: `${MOTION_CLASS} ${own}`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Flow: one particle per class, moved along the track by a motion path.
|
|
141
|
+
const path = trackPath(effect.track);
|
|
142
|
+
const r = particleRadius(effect.width);
|
|
143
|
+
for (let i = 0; i < effect.particles; i++) {
|
|
144
|
+
// The first particle's keyframes do not depend on how many particles there are.
|
|
145
|
+
const name = `mdg-flow${effect.reverse ? "-reverse" : ""}${i === 0 ? "" : `-${effect.particles}-${i}`}`;
|
|
146
|
+
keyframes.set(name, particleKeyframes(name, effect.particles, i, effect.reverse));
|
|
147
|
+
const particle = `${own}-${i}`;
|
|
148
|
+
particleRules.push(`.${particle} { offset-path: path("${path}"); offset-rotate: 0deg; ${animation(name, effect)} }`);
|
|
149
|
+
overlays.push({
|
|
150
|
+
kind: "path",
|
|
151
|
+
d: circlePath(0, 0, r),
|
|
152
|
+
fill: effect.color,
|
|
153
|
+
stroke: "none",
|
|
154
|
+
strokeWidth: 0,
|
|
155
|
+
dashed: false,
|
|
156
|
+
opacity: 0,
|
|
157
|
+
className: `${MOTION_CLASS} ${particle}`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const items = withTargets(scene.items, (group) => {
|
|
162
|
+
const key = targetKey(group.role, group.id);
|
|
163
|
+
const effect = dashes.get(key);
|
|
164
|
+
const trace = traces.get(key);
|
|
165
|
+
if (!effect && !trace)
|
|
166
|
+
return null;
|
|
167
|
+
let list = group.items;
|
|
168
|
+
const index = effect ? outlineIndex(list) : -1;
|
|
169
|
+
if (effect && index >= 0) {
|
|
170
|
+
list = list.map((item, i) => i === index && item.kind !== "group" && item.kind !== "text" && item.kind !== "image"
|
|
171
|
+
? { ...item, className: `${MOTION_CLASS} mdg-e${effect.index}` }
|
|
172
|
+
: item);
|
|
173
|
+
}
|
|
174
|
+
if (trace)
|
|
175
|
+
list = beforeLabel(list, trace);
|
|
176
|
+
return list === group.items ? null : [...list];
|
|
177
|
+
});
|
|
178
|
+
const motion = [...halos, ...overlays];
|
|
179
|
+
if (motion.length > 0)
|
|
180
|
+
items.push({ kind: "group", id: "motion", role: "motion", items: motion });
|
|
181
|
+
const sheet = [
|
|
182
|
+
...[...keyframes.keys()].sort().map((k) => keyframes.get(k)),
|
|
183
|
+
...rules,
|
|
184
|
+
// Motion paths are newer than the rest; without them particles and trace dots stay invisible.
|
|
185
|
+
...(particleRules.length > 0
|
|
186
|
+
? [`@supports (offset-path: path("M0 0")) {`, ...particleRules.map((r) => ` ${r}`), "}"]
|
|
187
|
+
: []),
|
|
188
|
+
// Overlays never take pointer events, so a canvas can still be clicked through them.
|
|
189
|
+
`[data-role="motion"] { pointer-events: none; }`,
|
|
190
|
+
`@media (prefers-reduced-motion: reduce) { .${MOTION_CLASS} { animation: none !important; } }`,
|
|
191
|
+
];
|
|
192
|
+
return { ...scene, items, styleSheet: sheet.join("\n") };
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=css.js.map
|
package/dist/css.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css.js","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"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"}
|
package/dist/drill.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Scene } from "@meltemi/diagrams-layout";
|
|
2
|
+
import { type StoryFrameOptions, type StoryTimeline, type StoryViews } from "./story.js";
|
|
3
|
+
/** How long a drill-down's two phases last: the camera move, then the change of view. */
|
|
4
|
+
export declare const DRILL_DURATIONS: {
|
|
5
|
+
readonly cameraMs: 320;
|
|
6
|
+
readonly transitionMs: 480;
|
|
7
|
+
};
|
|
8
|
+
export type DrillTransition = "morph" | "fade";
|
|
9
|
+
export type DrillDirection = "down" | "up";
|
|
10
|
+
/**
|
|
11
|
+
* A move between a view and the view an element opens. Going down, `from` is the view that draws
|
|
12
|
+
* `element` and `to` the view it opens; going up, `from` is the view being left and `to` the view
|
|
13
|
+
* that draws `element`, and the frames are those of the way down played backwards.
|
|
14
|
+
*/
|
|
15
|
+
export interface DrillSpec {
|
|
16
|
+
readonly from: string;
|
|
17
|
+
readonly to: string;
|
|
18
|
+
readonly element: string;
|
|
19
|
+
readonly transition: DrillTransition;
|
|
20
|
+
readonly direction: DrillDirection;
|
|
21
|
+
readonly cameraMs: number;
|
|
22
|
+
readonly transitionMs: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The timeline of the way down: a scene on the parent view with a camera on the element, then a
|
|
26
|
+
* scene on the child view that the transition starts. Plain data; the way up plays it backwards.
|
|
27
|
+
*/
|
|
28
|
+
export declare function drillTimeline(spec: DrillSpec): StoryTimeline;
|
|
29
|
+
/**
|
|
30
|
+
* The scene of a drill-down at `t` milliseconds: the story frame of `drillTimeline`, with the
|
|
31
|
+
* camera carried into the change of view (the view box goes from the element's camera box to the
|
|
32
|
+
* whole child view) and the size of the larger view at every instant, so the picture never jumps.
|
|
33
|
+
* The view box is always set. Null when a view is missing or the element has no bounds. Pure.
|
|
34
|
+
*/
|
|
35
|
+
export declare function drillFrame(spec: DrillSpec, views: StoryViews, t: number, options?: StoryFrameOptions): Scene | null;
|
|
36
|
+
/**
|
|
37
|
+
* How a view opens another from one of its elements: `morph` when both scenes draw an element
|
|
38
|
+
* with that id and bounds (a system box becomes the boundary of its container view), else `fade`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function transitionFor(parent: Scene, child: Scene, element: string): DrillTransition;
|
|
41
|
+
//# sourceMappingURL=drill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drill.d.ts","sourceRoot":"","sources":["../src/drill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAa,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,yFAAyF;AACzF,eAAO,MAAM,eAAe;;;CAAgD,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAC/C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,IAAI,CAAC;AAE3C;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AASD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,GAAG,aAAa,CA+C5D;AAUD;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,MAAM,EACT,OAAO,GAAE,iBAAsB,GAC9B,KAAK,GAAG,IAAI,CA6Cd;AAWD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,eAAe,CAE3F"}
|
package/dist/drill.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { round } from "./geometry.js";
|
|
2
|
+
import { boundsOf, frameBox, storyFrame, } from "./story.js";
|
|
3
|
+
/** How long a drill-down's two phases last: the camera move, then the change of view. */
|
|
4
|
+
export const DRILL_DURATIONS = { cameraMs: 320, transitionMs: 480 };
|
|
5
|
+
/** The way down of a spec: from the view that draws the element to the one it opens. */
|
|
6
|
+
function downward(spec) {
|
|
7
|
+
return spec.direction === "down"
|
|
8
|
+
? { parent: spec.from, child: spec.to }
|
|
9
|
+
: { parent: spec.to, child: spec.from };
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The timeline of the way down: a scene on the parent view with a camera on the element, then a
|
|
13
|
+
* scene on the child view that the transition starts. Plain data; the way up plays it backwards.
|
|
14
|
+
*/
|
|
15
|
+
export function drillTimeline(spec) {
|
|
16
|
+
const { parent, child } = downward(spec);
|
|
17
|
+
const camera = Math.max(0, spec.cameraMs);
|
|
18
|
+
const change = Math.max(0, spec.transitionMs);
|
|
19
|
+
return {
|
|
20
|
+
id: "drill",
|
|
21
|
+
title: null,
|
|
22
|
+
durationMs: camera + change,
|
|
23
|
+
views: [parent, child],
|
|
24
|
+
scenes: [
|
|
25
|
+
{
|
|
26
|
+
id: "from",
|
|
27
|
+
title: null,
|
|
28
|
+
view: parent,
|
|
29
|
+
transition: null,
|
|
30
|
+
startMs: 0,
|
|
31
|
+
durationMs: camera,
|
|
32
|
+
line: 0,
|
|
33
|
+
actions: [
|
|
34
|
+
{
|
|
35
|
+
kind: "camera",
|
|
36
|
+
path: [0, 0],
|
|
37
|
+
targets: [{ id: spec.element, kind: "element" }],
|
|
38
|
+
all: false,
|
|
39
|
+
startMs: 0,
|
|
40
|
+
durationMs: camera,
|
|
41
|
+
children: [],
|
|
42
|
+
line: 0,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "to",
|
|
48
|
+
title: null,
|
|
49
|
+
view: child,
|
|
50
|
+
transition: {
|
|
51
|
+
kind: change > 0 ? spec.transition : "cut",
|
|
52
|
+
startMs: camera,
|
|
53
|
+
durationMs: change,
|
|
54
|
+
},
|
|
55
|
+
startMs: camera,
|
|
56
|
+
durationMs: change,
|
|
57
|
+
line: 0,
|
|
58
|
+
actions: [],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const lerp = (a, b, p) => a + (b - a) * p;
|
|
64
|
+
const whole = (scene) => ({
|
|
65
|
+
x: 0,
|
|
66
|
+
y: 0,
|
|
67
|
+
width: scene.width,
|
|
68
|
+
height: scene.height,
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* The scene of a drill-down at `t` milliseconds: the story frame of `drillTimeline`, with the
|
|
72
|
+
* camera carried into the change of view (the view box goes from the element's camera box to the
|
|
73
|
+
* whole child view) and the size of the larger view at every instant, so the picture never jumps.
|
|
74
|
+
* The view box is always set. Null when a view is missing or the element has no bounds. Pure.
|
|
75
|
+
*/
|
|
76
|
+
export function drillFrame(spec, views, t, options = {}) {
|
|
77
|
+
const { parent, child } = downward(spec);
|
|
78
|
+
const above = views(parent);
|
|
79
|
+
const below = views(child);
|
|
80
|
+
if (!above || !below)
|
|
81
|
+
return null;
|
|
82
|
+
// Only an element's box opens a view: a relation's track is no target.
|
|
83
|
+
if (!hasElement(above.scene.items, spec.element))
|
|
84
|
+
return null;
|
|
85
|
+
const bounds = boundsOf(above.scene, [spec.element]);
|
|
86
|
+
if (!bounds)
|
|
87
|
+
return null;
|
|
88
|
+
const timeline = drillTimeline(spec);
|
|
89
|
+
const duration = timeline.durationMs;
|
|
90
|
+
const clamped = Math.min(Math.max(0, t), duration);
|
|
91
|
+
// The way up is the way down played backwards.
|
|
92
|
+
const time = spec.direction === "down" ? clamped : duration - clamped;
|
|
93
|
+
const camera = Math.max(0, spec.cameraMs);
|
|
94
|
+
const frame = storyFrame(timeline, views, time, options);
|
|
95
|
+
if (!frame)
|
|
96
|
+
return null;
|
|
97
|
+
const width = Math.max(above.scene.width, below.scene.width);
|
|
98
|
+
const height = Math.max(above.scene.height, below.scene.height);
|
|
99
|
+
let box;
|
|
100
|
+
if (time < camera || duration === 0) {
|
|
101
|
+
box = duration === 0 ? whole(below.scene) : (frame.viewBox ?? whole(above.scene));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
const change = duration - camera;
|
|
105
|
+
const p = change <= 0 ? 1 : Math.min(1, (time - camera) / change);
|
|
106
|
+
const from = frameBox(above.scene, bounds);
|
|
107
|
+
const to = whole(below.scene);
|
|
108
|
+
box = {
|
|
109
|
+
x: lerp(from.x, to.x, p),
|
|
110
|
+
y: lerp(from.y, to.y, p),
|
|
111
|
+
width: lerp(from.width, to.width, p),
|
|
112
|
+
height: lerp(from.height, to.height, p),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
...frame,
|
|
117
|
+
width,
|
|
118
|
+
height,
|
|
119
|
+
viewBox: {
|
|
120
|
+
x: round(box.x),
|
|
121
|
+
y: round(box.y),
|
|
122
|
+
width: round(box.width),
|
|
123
|
+
height: round(box.height),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function hasElement(items, id) {
|
|
128
|
+
for (const item of items) {
|
|
129
|
+
if (item.kind !== "group")
|
|
130
|
+
continue;
|
|
131
|
+
if (item.role === "element" && item.id === id && item.bounds)
|
|
132
|
+
return true;
|
|
133
|
+
if (hasElement(item.items, id))
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* How a view opens another from one of its elements: `morph` when both scenes draw an element
|
|
140
|
+
* with that id and bounds (a system box becomes the boundary of its container view), else `fade`.
|
|
141
|
+
*/
|
|
142
|
+
export function transitionFor(parent, child, element) {
|
|
143
|
+
return hasElement(parent.items, element) && hasElement(child.items, element) ? "morph" : "fade";
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=drill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drill.js","sourceRoot":"","sources":["../src/drill.ts"],"names":[],"mappings":"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"}
|
package/dist/frames.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { GroupItem, Scene, SceneItem } from "@meltemi/diagrams-layout";
|
|
2
|
+
import type { Point } from "@meltemi/diagrams-model";
|
|
3
|
+
import { type MotionEffect, type MotionPlan } from "./plan.js";
|
|
4
|
+
/** The items with `change` applied to every group; unchanged groups keep their identity. */
|
|
5
|
+
export declare function withTargets(items: readonly SceneItem[], change: (group: GroupItem) => readonly SceneItem[] | null): SceneItem[];
|
|
6
|
+
/** The index of the first stroked line or outline of a group, or -1. */
|
|
7
|
+
export declare function outlineIndex(items: readonly SceneItem[]): number;
|
|
8
|
+
export declare const targetKey: (role: string, id: string) => string;
|
|
9
|
+
/** The track a trace runs along, from where it starts: reversed for `direction reverse`. */
|
|
10
|
+
export declare function traceTrack(effect: MotionEffect): Point[];
|
|
11
|
+
/** How far a trace has grown at `phase` (0 to 1) and how visible it is. */
|
|
12
|
+
export declare function traceState(phase: number): {
|
|
13
|
+
grown: number;
|
|
14
|
+
opacity: number;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A trace at `phase`: the track drawn with one dash as long as the track, offset so that the part
|
|
18
|
+
* grown so far shows, and a dot at its head; the animated profile draws the same values.
|
|
19
|
+
*/
|
|
20
|
+
export declare function traceAt(effect: MotionEffect, phase: number): SceneItem[];
|
|
21
|
+
/** The items of a relation's group with `extra` inserted before its label, so the label stays on top. */
|
|
22
|
+
export declare function beforeLabel(items: readonly SceneItem[], extra: readonly SceneItem[]): SceneItem[];
|
|
23
|
+
/** The halo, glow or particles an effect draws at `phase`, above everything else. */
|
|
24
|
+
export declare function overlayAt(effect: MotionEffect, phase: number): SceneItem[];
|
|
25
|
+
/**
|
|
26
|
+
* The scene at `t` milliseconds: dashes moved along their lines and outlines, traces grown along
|
|
27
|
+
* their relations, halos and glows, particles on their tracks. Targets outside their effect's
|
|
28
|
+
* window are drawn as without effects. Pure: the same scene, plan and time give the same result.
|
|
29
|
+
*/
|
|
30
|
+
export declare function sceneAt(scene: Scene, plan: MotionPlan, t: number): Scene;
|
|
31
|
+
//# sourceMappingURL=frames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AASrD,OAAO,EAOL,KAAK,YAAY,EACjB,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAEnB,4FAA4F;AAC5F,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,MAAM,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,SAAS,EAAE,GAAG,IAAI,GACxD,SAAS,EAAE,CAQb;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAMhE;AAED,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,IAAI,MAAM,WAAyB,CAAC;AAE5E,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,CAGxD;AAED,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAI5E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,CAyBxE;AAED,yGAAyG;AACzG,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,EAAE,CAIjG;AAED,qFAAqF;AACrF,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,CA+C1E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAuCxE"}
|