@sliiu/present-transition-fx 0.0.0-stage → 0.1.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/COPYRIGHT +5 -0
- package/LICENSE +661 -0
- package/THIRD-PARTY-NOTICES.md +221 -0
- package/dist/cjs/2d.js +487 -0
- package/dist/cjs/3d.js +566 -0
- package/dist/cjs/geometry.js +141 -0
- package/dist/cjs/index.js +98 -0
- package/dist/cjs/morph-audit.js +603 -0
- package/dist/cjs/morph-match.js +103 -0
- package/dist/cjs/morph-path.js +649 -0
- package/dist/cjs/morph.js +223 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/registry.js +130 -0
- package/dist/cjs/snapshot.js +420 -0
- package/dist/cjs/twin.js +88 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/util.js +50 -0
- package/dist/cjs/webgl.js +271 -0
- package/dist/esm/2d.js +454 -0
- package/dist/esm/3d.js +538 -0
- package/dist/esm/geometry.js +127 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/morph-audit.js +558 -0
- package/dist/esm/morph-match.js +97 -0
- package/dist/esm/morph-path.js +636 -0
- package/dist/esm/morph.js +219 -0
- package/dist/esm/registry.js +91 -0
- package/dist/esm/snapshot.js +414 -0
- package/dist/esm/twin.js +84 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/util.js +43 -0
- package/dist/esm/webgl.js +231 -0
- package/dist/types/2d.d.ts +40 -0
- package/dist/types/3d.d.ts +38 -0
- package/dist/types/geometry.d.ts +38 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/morph-audit.d.ts +127 -0
- package/dist/types/morph-match.d.ts +28 -0
- package/dist/types/morph-path.d.ts +37 -0
- package/dist/types/morph.d.ts +2 -0
- package/dist/types/registry.d.ts +6 -0
- package/dist/types/snapshot.d.ts +19 -0
- package/dist/types/twin.d.ts +2 -0
- package/dist/types/types.d.ts +13 -0
- package/dist/types/util.d.ts +12 -0
- package/dist/types/webgl.d.ts +5 -0
- package/package.json +26 -4
- package/README.md +0 -3
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.morph = void 0;
|
|
4
|
+
const morph_path_1 = require("./morph-path");
|
|
5
|
+
const morph_match_1 = require("./morph-match");
|
|
6
|
+
const util_1 = require("./util");
|
|
7
|
+
const PATH_RE = /^path|polygon|polyline$/;
|
|
8
|
+
function readShapeId(el) {
|
|
9
|
+
const id = el.getAttribute("data-shape-id") ?? el.getAttribute("data-id");
|
|
10
|
+
if (!id || id.startsWith("__"))
|
|
11
|
+
return null;
|
|
12
|
+
return id;
|
|
13
|
+
}
|
|
14
|
+
function readShapeName(el, id) {
|
|
15
|
+
return el.getAttribute("data-shape-name") ?? el.getAttribute("data-name") ?? id;
|
|
16
|
+
}
|
|
17
|
+
// Nested shapes (grpSp children, the parser's `_base`/`_text` halves) ride on their outer shape's
|
|
18
|
+
// FLIP transform; matching them too would stack a second transform on top.
|
|
19
|
+
function hasShapeAncestor(el, root) {
|
|
20
|
+
for (let p = el.parentElement; p && p !== root; p = p.parentElement) {
|
|
21
|
+
if (readShapeId(p))
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
function collectMatchable(root) {
|
|
27
|
+
const out = [];
|
|
28
|
+
root.querySelectorAll("[data-shape-id], [data-id]").forEach((el) => {
|
|
29
|
+
const id = readShapeId(el);
|
|
30
|
+
if (!id || hasShapeAncestor(el, root))
|
|
31
|
+
return;
|
|
32
|
+
const name = readShapeName(el, id);
|
|
33
|
+
const rect = el.getBoundingClientRect();
|
|
34
|
+
if (rect.width < 1 && rect.height < 1)
|
|
35
|
+
return;
|
|
36
|
+
let pathD;
|
|
37
|
+
const tag = el.tagName.toLowerCase();
|
|
38
|
+
const pathEl = tag === "path"
|
|
39
|
+
? el
|
|
40
|
+
: el.querySelector("path");
|
|
41
|
+
if (pathEl) {
|
|
42
|
+
pathD = pathEl.getAttribute("d") ?? undefined;
|
|
43
|
+
}
|
|
44
|
+
else if (PATH_RE.test(tag)) {
|
|
45
|
+
pathD = (0, morph_path_1.polygonPointsToPath)(el.getAttribute("points") ?? "", tag === "polygon");
|
|
46
|
+
}
|
|
47
|
+
else if (tag === "ellipse" || tag === "circle") {
|
|
48
|
+
pathD = (0, morph_path_1.ellipsePathFromSize)(rect.width, rect.height);
|
|
49
|
+
}
|
|
50
|
+
else if (tag === "rect") {
|
|
51
|
+
pathD = (0, morph_path_1.rectPathFromSize)(rect.width, rect.height);
|
|
52
|
+
}
|
|
53
|
+
else if (tag === "line") {
|
|
54
|
+
const lineEl = el;
|
|
55
|
+
const x1 = Number(lineEl.getAttribute("x1") ?? 0);
|
|
56
|
+
const y1 = Number(lineEl.getAttribute("y1") ?? 0);
|
|
57
|
+
const x2 = Number(lineEl.getAttribute("x2") ?? rect.width);
|
|
58
|
+
const y2 = Number(lineEl.getAttribute("y2") ?? rect.height);
|
|
59
|
+
pathD = (0, morph_path_1.linePathFromPoints)(x1, y1, x2, y2);
|
|
60
|
+
}
|
|
61
|
+
const candidate = {
|
|
62
|
+
id,
|
|
63
|
+
name,
|
|
64
|
+
tag,
|
|
65
|
+
rect: { left: rect.left, top: rect.top, width: rect.width, height: rect.height },
|
|
66
|
+
pathD,
|
|
67
|
+
placeholderType: el.getAttribute("data-placeholder-type") ?? undefined,
|
|
68
|
+
};
|
|
69
|
+
const geomHash = (0, morph_match_1.morphGeometryHash)(candidate);
|
|
70
|
+
out.push({ id, name, geomHash, rect, pathD, el: el });
|
|
71
|
+
});
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
function toCandidate(m) {
|
|
75
|
+
return {
|
|
76
|
+
id: m.id,
|
|
77
|
+
name: m.name,
|
|
78
|
+
tag: m.geomHash.split("|")[0] ?? "g",
|
|
79
|
+
rect: {
|
|
80
|
+
left: m.rect.left,
|
|
81
|
+
top: m.rect.top,
|
|
82
|
+
width: m.rect.width,
|
|
83
|
+
height: m.rect.height,
|
|
84
|
+
},
|
|
85
|
+
pathD: m.pathD,
|
|
86
|
+
placeholderType: m.el.getAttribute("data-placeholder-type") ?? undefined,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function pairMatchable(ghost, stage) {
|
|
90
|
+
const ghostCands = ghost.map(toCandidate);
|
|
91
|
+
const stageCands = stage.map(toCandidate);
|
|
92
|
+
const out = new Map();
|
|
93
|
+
for (const { ghost: g, stage: s } of (0, morph_match_1.matchMorphShapePairs)(ghostCands, stageCands)) {
|
|
94
|
+
out.set(stage[stageCands.indexOf(s)], ghost[ghostCands.indexOf(g)]);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
function hasOwnTransform(el) {
|
|
99
|
+
if (!(el instanceof SVGGraphicsElement))
|
|
100
|
+
return false;
|
|
101
|
+
const m = el.transform.baseVal.consolidate()?.matrix;
|
|
102
|
+
return !!m && !(m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);
|
|
103
|
+
}
|
|
104
|
+
// Path tweening replaces FLIP only when the path is the whole shape and draws in slide space;
|
|
105
|
+
// otherwise text or siblings in the group would be left behind.
|
|
106
|
+
function soleUntransformedPath(el) {
|
|
107
|
+
const path = el.tagName.toLowerCase() === "path"
|
|
108
|
+
? el
|
|
109
|
+
: el.children.length === 1 && el.children[0].tagName.toLowerCase() === "path"
|
|
110
|
+
? el.children[0]
|
|
111
|
+
: null;
|
|
112
|
+
if (!path || hasOwnTransform(el) || (path !== el && hasOwnTransform(path)))
|
|
113
|
+
return null;
|
|
114
|
+
return path;
|
|
115
|
+
}
|
|
116
|
+
const morph = async (ctx) => {
|
|
117
|
+
const ghostMatched = collectMatchable(ctx.ghost);
|
|
118
|
+
const stageMatched = collectMatchable(ctx.stage);
|
|
119
|
+
if (ghostMatched.length === 0 || stageMatched.length === 0) {
|
|
120
|
+
const dur = (0, util_1.ms)(ctx);
|
|
121
|
+
const anims = [
|
|
122
|
+
ctx.ghost.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
123
|
+
duration: dur,
|
|
124
|
+
easing: util_1.STD_EASE,
|
|
125
|
+
fill: "forwards",
|
|
126
|
+
}),
|
|
127
|
+
];
|
|
128
|
+
if (stageMatched.length === 0 && ghostMatched.length > 0) {
|
|
129
|
+
anims.push(ctx.stage.animate([{ opacity: 0.92 }, { opacity: 1 }], {
|
|
130
|
+
duration: dur,
|
|
131
|
+
easing: util_1.STD_EASE,
|
|
132
|
+
fill: "forwards",
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
await (0, util_1.runAll)(anims);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const usedGhostIds = new Set();
|
|
139
|
+
const anims = [];
|
|
140
|
+
const pathTweens = [];
|
|
141
|
+
const dur = (0, util_1.ms)(ctx);
|
|
142
|
+
const pairs = pairMatchable(ghostMatched, stageMatched);
|
|
143
|
+
for (const s of stageMatched) {
|
|
144
|
+
const match = pairs.get(s);
|
|
145
|
+
if (!match) {
|
|
146
|
+
s.el.style.opacity = "0";
|
|
147
|
+
const a = s.el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
148
|
+
duration: dur,
|
|
149
|
+
easing: util_1.STD_EASE,
|
|
150
|
+
fill: "forwards",
|
|
151
|
+
});
|
|
152
|
+
anims.push(a);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
usedGhostIds.add(match.id);
|
|
156
|
+
// The stage shape starts on the ghost's geometry and carries the pair from here on.
|
|
157
|
+
match.el.style.visibility = "hidden";
|
|
158
|
+
const pathEl = soleUntransformedPath(s.el);
|
|
159
|
+
const tween = pathEl && soleUntransformedPath(match.el) && s.pathD && match.pathD
|
|
160
|
+
? (0, morph_path_1.makeMorphPathTween)(match.pathD, s.pathD)
|
|
161
|
+
: null;
|
|
162
|
+
if (pathEl && tween) {
|
|
163
|
+
// The ghost's d is already in slide coordinates, so the tween carries position and size.
|
|
164
|
+
pathTweens.push({ el: pathEl, tween });
|
|
165
|
+
pathEl.setAttribute("d", match.pathD);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// SVG CSS transforms are in user units and default to transform-box: view-box.
|
|
169
|
+
const svgScale = s.el instanceof SVGGraphicsElement ? (s.el.ownerSVGElement?.getScreenCTM()?.a ?? 1) : 1;
|
|
170
|
+
const dx = (match.rect.left - s.rect.left) / (svgScale || 1);
|
|
171
|
+
const dy = (match.rect.top - s.rect.top) / (svgScale || 1);
|
|
172
|
+
const sx = match.rect.width / Math.max(1, s.rect.width);
|
|
173
|
+
const sy = match.rect.height / Math.max(1, s.rect.height);
|
|
174
|
+
const el = s.el;
|
|
175
|
+
el.style.transformBox = "fill-box";
|
|
176
|
+
el.style.transformOrigin = "top left";
|
|
177
|
+
const a = el.animate([
|
|
178
|
+
{ transform: `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})`, opacity: 1 },
|
|
179
|
+
{ transform: "translate(0,0) scale(1,1)", opacity: 1 },
|
|
180
|
+
], { duration: dur, easing: util_1.STD_EASE, fill: "forwards" });
|
|
181
|
+
anims.push(a);
|
|
182
|
+
}
|
|
183
|
+
for (const leftover of ghostMatched) {
|
|
184
|
+
if (usedGhostIds.has(leftover.id))
|
|
185
|
+
continue;
|
|
186
|
+
const a = leftover.el.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
187
|
+
duration: dur,
|
|
188
|
+
easing: util_1.STD_EASE,
|
|
189
|
+
fill: "forwards",
|
|
190
|
+
});
|
|
191
|
+
anims.push(a);
|
|
192
|
+
}
|
|
193
|
+
const fadeGhost = ctx.ghost.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
194
|
+
duration: dur * 0.7,
|
|
195
|
+
delay: dur * 0.3,
|
|
196
|
+
easing: util_1.STD_EASE,
|
|
197
|
+
fill: "forwards",
|
|
198
|
+
});
|
|
199
|
+
anims.push(fadeGhost);
|
|
200
|
+
if (pathTweens.length > 0) {
|
|
201
|
+
const start = performance.now();
|
|
202
|
+
await new Promise((resolve) => {
|
|
203
|
+
const step = () => {
|
|
204
|
+
const t = Math.min(1, (performance.now() - start) / Math.max(1, dur));
|
|
205
|
+
for (const pt of pathTweens)
|
|
206
|
+
pt.el.setAttribute("d", pt.tween(t));
|
|
207
|
+
if (t < 1)
|
|
208
|
+
requestAnimationFrame(step);
|
|
209
|
+
else
|
|
210
|
+
resolve();
|
|
211
|
+
};
|
|
212
|
+
requestAnimationFrame(step);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
await (0, util_1.runAll)(anims);
|
|
216
|
+
for (const s of stageMatched) {
|
|
217
|
+
s.el.style.transform = "";
|
|
218
|
+
s.el.style.opacity = "";
|
|
219
|
+
s.el.style.transformOrigin = "";
|
|
220
|
+
s.el.style.transformBox = "";
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
exports.morph = morph;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getTransition = getTransition;
|
|
37
|
+
exports.listTransitions = listTransitions;
|
|
38
|
+
exports.registerTransition = registerTransition;
|
|
39
|
+
exports.runTransition = runTransition;
|
|
40
|
+
const fx2d = __importStar(require("./2d"));
|
|
41
|
+
const fx3d = __importStar(require("./3d"));
|
|
42
|
+
const fxGl = __importStar(require("./webgl"));
|
|
43
|
+
const morph_1 = require("./morph");
|
|
44
|
+
const registry = new Map();
|
|
45
|
+
function register(name, fn) {
|
|
46
|
+
registry.set(name, fn);
|
|
47
|
+
}
|
|
48
|
+
register("cut", fx2d.cut);
|
|
49
|
+
register("fade", fx2d.fade);
|
|
50
|
+
register("push", fx2d.push);
|
|
51
|
+
register("cover", fx2d.cover);
|
|
52
|
+
register("uncover", fx2d.uncover);
|
|
53
|
+
register("wipe", fx2d.wipe);
|
|
54
|
+
register("split", fx2d.split);
|
|
55
|
+
register("zoom", fx2d.zoom);
|
|
56
|
+
register("blinds", fx2d.blinds);
|
|
57
|
+
register("checker", fx2d.checker);
|
|
58
|
+
register("randomBar", fx2d.randomBar);
|
|
59
|
+
register("dissolve", fxGl.dissolveWebGL);
|
|
60
|
+
register("newsflash", fx2d.newsflash);
|
|
61
|
+
register("wheel", fx2d.wheel);
|
|
62
|
+
register("wheelReverse", fx2d.wheelReverse);
|
|
63
|
+
register("circle", fx2d.circle);
|
|
64
|
+
register("diamond", fx2d.diamond);
|
|
65
|
+
register("plus", fx2d.plus);
|
|
66
|
+
register("comb", fx2d.comb);
|
|
67
|
+
register("strips", fx2d.strips);
|
|
68
|
+
register("wedge", fx2d.wedge);
|
|
69
|
+
register("fall", fx2d.fall);
|
|
70
|
+
register("reveal", fx2d.reveal);
|
|
71
|
+
register("flash", fx2d.flash);
|
|
72
|
+
register("random", fx2d.random);
|
|
73
|
+
register("glitter", fx2d.glitter);
|
|
74
|
+
register("honeycomb", fx2d.honeycomb);
|
|
75
|
+
register("fracture", fx2d.fracture);
|
|
76
|
+
register("shred", fx2d.shred);
|
|
77
|
+
register("prestige", fx2d.prestige);
|
|
78
|
+
register("prism", fx3d.prism);
|
|
79
|
+
register("cube", fxGl.cubeWebGL);
|
|
80
|
+
register("box", fxGl.boxWebGL);
|
|
81
|
+
register("gallery", fx3d.gallery);
|
|
82
|
+
register("orbit", fx3d.orbit);
|
|
83
|
+
register("conveyor", fx3d.conveyor);
|
|
84
|
+
register("doors", fx3d.doors);
|
|
85
|
+
register("window", fx3d.window);
|
|
86
|
+
register("pageCurl", fxGl.pageCurlWebGL);
|
|
87
|
+
register("pageCurlSingle", fx3d.pageCurlSingle);
|
|
88
|
+
register("wind", fx3d.wind);
|
|
89
|
+
register("crush", fx3d.crush);
|
|
90
|
+
register("pageCurlCss", fx3d.pageCurl);
|
|
91
|
+
register("airplane", fx3d.airplane);
|
|
92
|
+
register("origami", fx3d.origami);
|
|
93
|
+
register("flythrough", fx3d.flythrough);
|
|
94
|
+
register("rotate", fx3d.rotate);
|
|
95
|
+
register("ferris", fx3d.ferris);
|
|
96
|
+
register("peelOff", fx3d.peelOff);
|
|
97
|
+
register("curtains", fx3d.curtains);
|
|
98
|
+
register("drape", fx3d.drape);
|
|
99
|
+
register("ripple", fx3d.ripple);
|
|
100
|
+
register("warp", fx3d.warp);
|
|
101
|
+
register("vortex", fx3d.vortex);
|
|
102
|
+
register("flip", fx3d.flip);
|
|
103
|
+
register("switch", fx3d.switchFx);
|
|
104
|
+
register("morph", morph_1.morph);
|
|
105
|
+
function getTransition(kind) {
|
|
106
|
+
return registry.get(kind);
|
|
107
|
+
}
|
|
108
|
+
function listTransitions() {
|
|
109
|
+
return [...registry.keys()];
|
|
110
|
+
}
|
|
111
|
+
function registerTransition(kind, fn) {
|
|
112
|
+
register(kind, fn);
|
|
113
|
+
}
|
|
114
|
+
async function runTransition(ghost, stage, transition) {
|
|
115
|
+
if (transition.kind === "cut" || transition.duration <= 0)
|
|
116
|
+
return;
|
|
117
|
+
const fn = registry.get(transition.kind) ?? registry.get("fade");
|
|
118
|
+
if (!fn)
|
|
119
|
+
return;
|
|
120
|
+
const rect = stage.getBoundingClientRect();
|
|
121
|
+
const ctx = {
|
|
122
|
+
ghost,
|
|
123
|
+
stage,
|
|
124
|
+
duration: transition.duration,
|
|
125
|
+
params: transition.params ?? {},
|
|
126
|
+
transition,
|
|
127
|
+
stageSize: { w: rect.width, h: rect.height },
|
|
128
|
+
};
|
|
129
|
+
await fn(ctx);
|
|
130
|
+
}
|