svg-morpheus-ts
Version:
ESM TypeScript library enabling SVG icons to morph from one to the other. It implements Material Design's Delightful Details transitions. Refactored with modern TypeScript + Vite + pnpm stack. Supports both Chinese and English documentation.
1,263 lines (1,262 loc) • 50.6 kB
JavaScript
const R = window, ht = R.requestAnimationFrame || R.mozRequestAnimationFrame || R.webkitRequestAnimationFrame || R.oRequestAnimationFrame, kt = R.cancelAnimationFrame || R.mozCancelAnimationFrame || R.webkitCancelAnimationFrame || R.oCancelAnimationFrame;
function ft(t, s, e) {
const n = {};
for (const r in t) {
const o = r;
switch (o) {
case "fill":
case "stroke":
if (t[o] && s[o]) {
const i = t[o], a = s[o];
if (typeof i == "string" || typeof a == "string")
n[o] = e < 0.5 ? i : a;
else {
const h = i, l = a;
n[o] = L(h), n[o].r = h.r + (l.r - h.r) * e, n[o].g = h.g + (l.g - h.g) * e, n[o].b = h.b + (l.b - h.b) * e, n[o].opacity = h.opacity + (l.opacity - h.opacity) * e;
}
}
break;
case "opacity":
case "fill-opacity":
case "stroke-opacity":
case "stroke-width":
typeof t[o] == "number" && typeof s[o] == "number" && (n[o] = t[o] + (s[o] - t[o]) * e);
break;
}
}
return n;
}
function Y(t) {
const s = {};
for (const e in t) {
const n = e;
switch (n) {
case "fill":
case "stroke":
if (t[n]) {
const r = t[n];
typeof r == "string" ? s[n] = r : s[n] = St(r);
}
break;
case "opacity":
case "fill-opacity":
case "stroke-opacity":
case "stroke-width":
typeof t[n] == "number" && (s[n] = t[n]);
break;
}
}
return s;
}
function mt(t, s) {
const e = [{}, {}], n = (r) => typeof r == "string" && r.trim().startsWith("url(#");
for (const r in t) {
const o = r;
switch (o) {
case "fill":
case "stroke":
t[o] && (n(t[o]) ? (e[0][o] = t[o], s[o] === void 0 && (e[1][o] = t[o])) : (e[0][o] = Z(t[o]), s[o] === void 0 && (e[1][o] = Z(t[o]), e[1][o].opacity = 0)));
break;
case "opacity":
case "fill-opacity":
case "stroke-opacity":
case "stroke-width":
t[o] && (e[0][o] = t[o], s[o] === void 0 && (e[1][o] = 1));
break;
}
}
for (const r in s) {
const o = r;
switch (o) {
case "fill":
case "stroke":
s[o] && (n(s[o]) ? (e[1][o] = s[o], t[o] === void 0 && (e[0][o] = s[o])) : (e[1][o] = Z(s[o]), t[o] === void 0 && (e[0][o] = Z(s[o]), e[0][o].opacity = 0)));
break;
case "opacity":
case "fill-opacity":
case "stroke-opacity":
case "stroke-width":
s[o] && (e[1][o] = s[o], t[o] === void 0 && (e[0][o] = 1));
break;
}
}
return e;
}
function $t(t, s, e) {
const n = {};
for (const r in t) {
const o = r;
switch (o) {
case "rotate":
if (t[o] && s[o]) {
n[o] = [0, 0, 0];
for (let i = 0; i < 3; i++) {
const a = t[o][i], h = s[o][i];
isFinite(a) && isFinite(h) && isFinite(e) ? n[o][i] = a + (h - a) * e : n[o][i] = isFinite(a) ? a : 0;
}
}
break;
}
}
return n;
}
function Ct(t) {
let s = "";
if (t.rotate && t.rotate.length === 3) {
const [e, n, r] = t.rotate;
isFinite(e) && isFinite(n) && isFinite(r) ? s += "rotate(" + t.rotate.join(" ") + ")" : s += "rotate(0 0 0)";
}
return s;
}
function At(t, s, e) {
const n = [];
for (let r = 0, o = t.length; r < o; r++) {
if (n.push([t[r][0]]), !s[r]) {
for (let i = 1, a = t[r].length; i < a; i++)
n[r].push(t[r][i]);
continue;
}
for (let i = 1, a = t[r].length; i < a; i++) {
const h = t[r][i], l = s[r] && s[r][i] !== void 0 ? s[r][i] : h;
n[r].push(h + (l - h) * e);
}
}
return n;
}
function L(t) {
let s;
if (t instanceof Array) {
s = [];
for (let e = 0, n = t.length; e < n; e++)
s[e] = L(t[e]);
return s;
}
if (t instanceof Object) {
s = {};
for (const e in t)
t.hasOwnProperty(e) && (s[e] = L(t[e]));
return s;
}
return t;
}
const dt = `
\v\f\r \u2028\u2029`, Et = { hs: 1, rg: 1 }, Ft = "hasOwnProperty", Nt = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\))\s*$/i, rt = new RegExp("[" + dt + "]*,[" + dt + "]*"), St = function(t) {
const s = Math.round;
return "rgba(" + [s(t.r), s(t.g), s(t.b), +t.opacity.toFixed(2)] + ")";
}, Dt = function(t) {
const s = window.document.getElementsByTagName("head")[0] || window.document.getElementsByTagName("svg")[0], e = "rgb(255, 0, 0)";
return function(r) {
var i;
if (r.toLowerCase() === "red")
return e;
s.style.color = e, s.style.color = r;
const o = (i = window.document.defaultView) == null ? void 0 : i.getComputedStyle(s, "").getPropertyValue("color");
return o === e ? null : o || null;
}(t);
}, _t = function(t, s, e, n) {
const r = Math.round(t * 255), o = Math.round(s * 255), i = Math.round(e * 255);
return {
r,
g: o,
b: i,
opacity: isFinite(n) ? n : 1
};
}, qt = function(t, s, e, n) {
typeof t == "object" && "h" in t && "s" in t && "b" in t && (e = t.b, s = t.s, n = t.o, t = t.h);
const r = t * 360;
let o, i, a, h, l;
const u = r % 360 / 60;
l = e * s, h = l * (1 - Math.abs(u % 2 - 1)), o = i = a = e - l;
const m = ~~u;
return o += [l, h, 0, 0, h, l][m], i += [h, l, l, h, 0, 0][m], a += [0, 0, h, l, l, h][m], _t(o, i, a, n);
}, Gt = function(t, s, e, n) {
typeof t == "object" && "h" in t && "s" in t && "l" in t && (e = t.l, s = t.s, n = t.o, t = t.h);
let r = t, o = s, i = e;
(r > 1 || o > 1 || i > 1) && (r /= 360, o /= 100, i /= 100), r *= 360;
let a, h, l, u, m;
const I = r % 360 / 60;
m = 2 * o * (i < 0.5 ? i : 1 - i), u = m * (1 - Math.abs(I % 2 - 1)), a = h = l = i - m / 2;
const c = ~~I;
return a += [m, u, 0, 0, u, m][c], h += [u, m, m, u, 0, 0][c], l += [0, 0, u, m, m, u][c], _t(a, h, l, n);
}, Z = function(t) {
if (!t || (t = String(t)).indexOf("-") + 1)
return { r: -1, g: -1, b: -1, opacity: -1, error: 1 };
if (t === "none")
return { r: -1, g: -1, b: -1, opacity: -1 };
if (Et[Ft](t.toLowerCase().substring(0, 2)) || t.charAt(0) === "#" || (t = Dt(t) || ""), !t)
return { r: -1, g: -1, b: -1, opacity: -1, error: 1 };
let s = 0, e = 0, n = 0, r = 1, o, i;
const a = t.match(Nt);
return a ? (a[2] && (n = parseInt(a[2].substring(5), 16), e = parseInt(a[2].substring(3, 5), 16), s = parseInt(a[2].substring(1, 3), 16)), a[3] && (n = parseInt((o = a[3].charAt(3)) + o, 16), e = parseInt((o = a[3].charAt(2)) + o, 16), s = parseInt((o = a[3].charAt(1)) + o, 16)), a[4] && (i = a[4].split(rt), s = parseFloat(i[0]), i[0].slice(-1) === "%" && (s *= 2.55), e = parseFloat(i[1]), i[1].slice(-1) === "%" && (e *= 2.55), n = parseFloat(i[2]), i[2].slice(-1) === "%" && (n *= 2.55), a[1].toLowerCase().slice(0, 4) === "rgba" && (r = parseFloat(i[3])), i[3] && i[3].slice(-1) === "%" && (r /= 100)), a[5] ? (i = a[5].split(rt), s = parseFloat(i[0]), i[0].slice(-1) === "%" && (s /= 100), e = parseFloat(i[1]), i[1].slice(-1) === "%" && (e /= 100), n = parseFloat(i[2]), i[2].slice(-1) === "%" && (n /= 100), (i[0].slice(-3) === "deg" || i[0].slice(-1) === "°") && (s /= 360), a[1].toLowerCase().slice(0, 4) === "hsba" && (r = parseFloat(i[3])), i[3] && i[3].slice(-1) === "%" && (r /= 100), qt(s, e, n, r)) : a[6] ? (i = a[6].split(rt), s = parseFloat(i[0]), i[0].slice(-1) === "%" && (s /= 100), e = parseFloat(i[1]), i[1].slice(-1) === "%" && (e /= 100), n = parseFloat(i[2]), i[2].slice(-1) === "%" && (n /= 100), (i[0].slice(-3) === "deg" || i[0].slice(-1) === "°") && (s /= 360), a[1].toLowerCase().slice(0, 4) === "hsla" && (r = parseFloat(i[3])), i[3] && i[3].slice(-1) === "%" && (r /= 100), Gt(s, e, n, r)) : (s = Math.min(Math.round(s), 255), e = Math.min(Math.round(e), 255), n = Math.min(Math.round(n), 255), r = Math.min(Math.max(r, 0), 1), { r: s, g: e, b: n, opacity: isFinite(r) ? r : 1 })) : { r: -1, g: -1, b: -1, opacity: -1, error: 1 };
};
async function bt(t, s) {
const e = [];
for (const [a, h] of Object.entries(t)) {
let l;
if (Rt(h))
l = h;
else
try {
const d = await fetch(h);
if (!d.ok) {
console.warn(`Failed to load SVG from ${h}`);
continue;
}
l = await d.text();
} catch (d) {
console.warn(`Error loading SVG from ${h}:`, d);
continue;
}
const u = vt(l), m = at(l), c = ct(l).fill;
let f = Pt(l);
c && [
"path",
"polygon",
"rect",
"circle",
"ellipse",
"line",
"polyline"
].forEach((g) => {
const v = new RegExp(`<${g}(\\s[^>]*)?>`, "gi");
f = f.replace(v, (p) => /fill\s*=\s*['"][^'"]*['"]/i.test(p) ? p : p.endsWith("/>") ? p.replace(new RegExp(`<${g}(\\s*)`), `<${g}$1 fill="${c}" `) : p.replace(new RegExp(`<${g}(\\s*)`), `<${g}$1 fill="${c}" `));
});
let _ = `id="${a}"`;
u && (_ += ` data-original-viewbox="${u.original}"`), (Object.keys(m.gradients).length > 0 || Object.keys(m.patterns).length > 0) && (_ += ' data-has-defs="true"');
const b = `<g ${_}>${f}</g>`;
e.push(b);
}
const r = { ...{
xmlns: "http://www.w3.org/2000/svg",
style: "display:none;"
}, ...s };
return `<svg ${Object.entries(r).map(([a, h]) => `${a}="${h}"`).join(" ")}>
${e.join(`
`)}
</svg>`;
}
async function Tt(t, s) {
const e = await bt(t, s), n = new Blob([e], { type: "image/svg+xml" });
return URL.createObjectURL(n);
}
async function Ht(t, s) {
return bt(t, s);
}
function Rt(t) {
const s = t.trim();
return s.startsWith("<?xml") ? s.includes("<svg") : !!(s.startsWith("<svg") || s.startsWith("<!DOCTYPE svg"));
}
function Pt(t) {
let s = t.trim();
s = s.replace(/<\?xml[^?]*\?>\s*/gi, ""), s = s.replace(/<!DOCTYPE[^>]*>\s*/gi, ""), s = s.replace(/<\?[^?]*\?>\s*/gi, ""), s = s.trim();
const e = s.match(/<svg[^>]*>([\s\S]*?)<\/svg>/i);
if (e && e[1])
return e[1].trim();
if (s.startsWith("<svg")) {
const n = s.indexOf(">");
if (n !== -1) {
const r = s.substring(n + 1), o = r.lastIndexOf("</svg>");
if (o !== -1)
return r.substring(0, o).trim();
}
}
return s;
}
function vt(t) {
const s = t.match(/<svg[^>]*>/i);
if (!s) return null;
const n = s[0].match(/viewBox\s*=\s*["']([^"']+)["']/i);
if (!n) return null;
const r = n[1], o = r.trim().split(/\s+/).map(Number);
return o.length !== 4 ? null : {
values: [o[0], o[1], o[2], o[3]],
original: r
};
}
function at(t) {
const s = {
gradients: {},
patterns: {},
others: {},
raw: void 0
}, e = t.match(/<defs[^>]*>([\s\S]*?)<\/defs>/i);
if (!e) return s;
s.raw = e[0];
const n = e[1], r = n.match(/<linearGradient[^>]*>[\s\S]*?<\/linearGradient>/gi);
r && r.forEach((h) => {
const l = h.match(/id\s*=\s*["']([^"']+)["']/i);
l && (s.gradients[l[1]] = h);
});
const o = n.match(/<radialGradient[^>]*>[\s\S]*?<\/radialGradient>/gi);
o && o.forEach((h) => {
const l = h.match(/id\s*=\s*["']([^"']+)["']/i);
l && (s.gradients[l[1]] = h);
});
const i = n.match(/<pattern[^>]*>[\s\S]*?<\/pattern>/gi);
i && i.forEach((h) => {
const l = h.match(/id\s*=\s*["']([^"']+)["']/i);
l && (s.patterns[l[1]] = h);
});
const a = n.match(/<(?!linearGradient|radialGradient|pattern)[^>]+>[\s\S]*?<\/[^>]+>/gi);
return a && a.forEach((h) => {
const l = h.match(/id\s*=\s*["']([^"']+)["']/i);
l && (s.others[l[1]] = h);
}), s;
}
function ct(t) {
const s = t.match(/<svg([^>]*)>/i);
if (!s) return {};
const e = {}, r = s[1].match(/(\w+)\s*=\s*["']([^"']*)["']/g);
return r && r.forEach((o) => {
const [, i, a] = o.match(/(\w+)\s*=\s*["']([^"']*)["']/) || [];
i && a && (e[i] = a);
}), e;
}
const x = {};
x["circ-in"] = function(t) {
return -1 * (Math.sqrt(1 - t * t) - 1);
};
x["circ-out"] = function(t) {
return Math.sqrt(1 - (t = t - 1) * t);
};
x["circ-in-out"] = function(t) {
return (t /= 1 / 2) < 1 ? -1 / 2 * (Math.sqrt(1 - t * t) - 1) : 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
};
x["cubic-in"] = function(t) {
return t * t * t;
};
x["cubic-out"] = function(t) {
return --t * t * t + 1;
};
x["cubic-in-out"] = function(t) {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
};
x["elastic-in"] = function(t) {
var n = 1.70158, s = 0, e = 1;
if (t == 0) return 0;
if (t == 1) return 1;
if (s || (s = 0.3), e < Math.abs(1)) {
e = 1;
var n = s / 4;
} else var n = s / (2 * Math.PI) * Math.asin(1 / e);
return -(e * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - n) * (2 * Math.PI) / s));
};
x["elastic-out"] = function(t) {
var n = 1.70158, s = 0, e = 1;
if (t == 0) return 0;
if (t == 1) return 1;
if (s || (s = 0.3), e < Math.abs(1)) {
e = 1;
var n = s / 4;
} else var n = s / (2 * Math.PI) * Math.asin(1 / e);
return e * Math.pow(2, -10 * t) * Math.sin((t - n) * (2 * Math.PI) / s) + 1;
};
x["elastic-in-out"] = function(t) {
var n = 1.70158, s = 0, e = 1;
if (t == 0) return 0;
if ((t /= 1 / 2) == 2) return 1;
if (s || (s = 1 * (0.3 * 1.5)), e < Math.abs(1)) {
e = 1;
var n = s / 4;
} else var n = s / (2 * Math.PI) * Math.asin(1 / e);
return t < 1 ? -0.5 * (e * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - n) * (2 * Math.PI) / s)) : e * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - n) * (2 * Math.PI) / s) * 0.5 + 1;
};
x["expo-in"] = function(t) {
return t == 0 ? 0 : Math.pow(2, 10 * (t - 1));
};
x["expo-out"] = function(t) {
return t == 1 ? 1 : 1 - Math.pow(2, -10 * t);
};
x["expo-in-out"] = function(t) {
return t == 0 ? 0 : t == 1 ? 1 : (t /= 1 / 2) < 1 ? 1 / 2 * Math.pow(2, 10 * (t - 1)) : 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
};
x.linear = function(t) {
return t;
};
x["quad-in"] = function(t) {
return t * t;
};
x["quad-out"] = function(t) {
return t * (2 - t);
};
x["quad-in-out"] = function(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
};
x["quart-in"] = function(t) {
return t * t * t * t;
};
x["quart-out"] = function(t) {
return 1 - --t * t * t * t;
};
x["quart-in-out"] = function(t) {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
};
x["quint-in"] = function(t) {
return t * t * t * t * t;
};
x["quint-out"] = function(t) {
return 1 + --t * t * t * t * t;
};
x["quint-in-out"] = function(t) {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
};
x["sine-in"] = function(t) {
return 1 - Math.cos(t * (Math.PI / 2));
};
x["sine-out"] = function(t) {
return Math.sin(t * (Math.PI / 2));
};
x["sine-in-out"] = function(t) {
return 1 / 2 * (1 - Math.cos(Math.PI * t));
};
const H = `
\v\f\r \u2028\u2029`, Vt = new RegExp("([a-z])[" + H + ",]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[" + H + "]*,?[" + H + "]*)+)", "ig"), jt = new RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[" + H + "]*,?[" + H + "]*", "ig");
function wt(t) {
if (!t)
return null;
if (Array.isArray(t))
return t;
{
const s = {
a: 7,
c: 6,
o: 2,
h: 1,
l: 2,
m: 2,
r: 4,
q: 4,
s: 4,
t: 2,
v: 1,
u: 3,
z: 0
}, e = [];
return String(t).replace(Vt, function(n, r, o) {
const i = [];
let a = r.toLowerCase();
if (o.replace(jt, function(h, l) {
return l && i.push(+l), "";
}), a === "m" && i.length > 2 && (e.push([r.charCodeAt(0)].concat(i.splice(0, 2))), a = "l", r = r === "m" ? "l" : "L"), a === "o" && i.length === 1 && e.push([r.charCodeAt(0), i[0]]), a === "r")
e.push([r.charCodeAt(0)].concat(i));
else
for (; i.length >= s[a] && (e.push([r.charCodeAt(0)].concat(i.splice(0, s[a]))), !!s[a]); )
;
return "";
}), e;
}
}
function lt(t) {
const s = wt(t);
if (!s || !s.length)
return [["M", 0, 0]];
const e = [];
let n = 0, r = 0, o = 0, i = 0, a = 0;
s[0][0] === 77 && (n = +s[0][1], r = +s[0][2], o = n, i = r, a++, e[0] = ["M", n, r]);
for (let h = a, l = s.length; h < l; h++) {
const u = [], m = s[h], I = m[0], c = String.fromCharCode(I);
if (c !== c.toUpperCase())
switch (u[0] = c.toUpperCase(), u[0]) {
case "A":
u[1] = m[1], u[2] = m[2], u[3] = m[3], u[4] = m[4], u[5] = m[5], u[6] = +m[6] + n, u[7] = +m[7] + r;
break;
case "V":
u[1] = +m[1] + r;
break;
case "H":
u[1] = +m[1] + n;
break;
case "M":
o = +m[1] + n, i = +m[2] + r;
default:
for (let f = 1, _ = m.length; f < _; f++)
u[f] = +m[f] + (f % 2 ? n : r);
break;
}
else {
u[0] = c;
for (let f = 1, _ = m.length; f < _; f++)
u[f] = m[f];
}
switch (u[0]) {
case "Z":
n = o, r = i;
break;
case "H":
n = u[1];
break;
case "V":
r = u[1];
break;
case "M":
o = u[1], i = u[2], n = u[1], r = u[2];
break;
default:
n = u[u.length - 2], r = u[u.length - 1];
}
e.push(u);
}
return e;
}
function it(t, s) {
const e = lt(t), n = s && lt(s), r = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }, o = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }, i = function(c, f, _) {
let b, d;
if (!c)
return ["C", f.x, f.y, f.x, f.y, f.x, f.y];
switch (!(c[0] in { T: 1, Q: 1 }) && (f.qx = f.qy = null), c[0]) {
case "M":
f.X = c[1], f.Y = c[2];
break;
case "A":
c = ["C"].concat(yt.apply(0, [f.x, f.y].concat(c.slice(1))));
break;
case "S":
_ == "C" || _ == "S" ? (b = f.x * 2 - f.bx, d = f.y * 2 - f.by) : (b = f.x, d = f.y), c = ["C", b, d].concat(c.slice(1));
break;
case "T":
_ == "Q" || _ == "T" ? (f.qx = f.x * 2 - f.qx, f.qy = f.y * 2 - f.qy) : (f.qx = f.x, f.qy = f.y), c = ["C"].concat(gt(f.x, f.y, f.qx, f.qy, c[1], c[2]));
break;
case "Q":
f.qx = c[1], f.qy = c[2], c = ["C"].concat(gt(f.x, f.y, c[1], c[2], c[3], c[4]));
break;
case "L":
c = ["C"].concat(J(f.x, f.y, c[1], c[2]));
break;
case "H":
c = ["C"].concat(J(f.x, f.y, c[1], f.y));
break;
case "V":
c = ["C"].concat(J(f.x, f.y, f.x, c[1]));
break;
case "Z":
c = ["C"].concat(J(f.x, f.y, f.X, f.Y));
break;
}
return c;
}, a = function(c, f) {
if (c[f].length > 7) {
c[f].shift();
const _ = c[f];
for (; _.length; )
l[f] = "A", n && (u[f] = "A"), c.splice(f++, 0, ["C"].concat(_.splice(0, 6)));
c.splice(f, 1);
}
}, h = function(c, f, _, b, d) {
c && f && c[d][0] == "M" && f[d][0] != "M" && (f.splice(d, 0, ["M", b.x, b.y]), _.bx = 0, _.by = 0, _.x = c[d][1], _.y = c[d][2]);
}, l = [], u = [];
let m = "", I = "";
for (let c = 0, f = Math.max(e.length, n && n.length || 0); c < f; c++) {
e[c] && (m = e[c][0]), m != "C" && (l[c] = m, c && (I = l[c - 1])), e[c] = i(e[c], r, I), l[c] != "A" && m == "C" && (l[c] = "C"), a(e, c), n && (n[c] && (m = n[c][0]), m != "C" && (u[c] = m, c && (I = u[c - 1])), n[c] = i(n[c], o, I), u[c] != "A" && m == "C" && (u[c] = "C"), a(n, c)), h(e, n, r, o, c), h(n, e, o, r, c);
const _ = e[c], b = n && n[c], d = _.length, g = n && b.length;
r.x = _[d - 2], r.y = _[d - 1], r.bx = parseFloat(_[d - 4]) || r.x, r.by = parseFloat(_[d - 3]) || r.y, o.bx = n && (parseFloat(b[g - 4]) || o.x), o.by = n && (parseFloat(b[g - 3]) || o.y), o.x = n && b[g - 2], o.y = n && b[g - 1];
}
return n ? [e, n] : e;
}
const J = function(t, s, e, n) {
return [t, s, e, n, e, n];
}, gt = function(t, s, e, n, r, o) {
var i = 0.3333333333333333, a = 2 / 3;
return [
i * t + a * e,
i * s + a * n,
i * r + a * e,
i * o + a * n,
r,
o
];
}, yt = function(t, s, e, n, r, o, i, a, h, l) {
var u = Math.PI * 120 / 180, m = Math.PI / 180 * (+r || 0), I = [], c, f = function(U, Q, B) {
var ot = U * Math.cos(B) - Q * Math.sin(B), O = U * Math.sin(B) + Q * Math.cos(B);
return { x: ot, y: O };
};
if (l)
y = l[0], M = l[1], w = l[2], $ = l[3];
else {
c = f(t, s, -m), t = c.x, s = c.y, c = f(a, h, -m), a = c.x, h = c.y;
var _ = (t - a) / 2, b = (s - h) / 2, d = _ * _ / (e * e) + b * b / (n * n);
d > 1 && (d = Math.sqrt(d), e = d * e, n = d * n);
var g = e * e, v = n * n, p = (o == i ? -1 : 1) * Math.sqrt(Math.abs((g * v - g * b * b - v * _ * _) / (g * b * b + v * _ * _))), w = p * e * b / n + (t + a) / 2, $ = p * -n * _ / e + (s + h) / 2, y = Math.asin(+((s - $) / n).toFixed(9)), M = Math.asin(+((h - $) / n).toFixed(9));
y = t < w ? Math.PI - y : y, M = a < w ? Math.PI - M : M, y < 0 && (y = Math.PI * 2 + y), M < 0 && (M = Math.PI * 2 + M), i && y > M && (y = y - Math.PI * 2), !i && M > y && (M = M - Math.PI * 2);
}
var k = M - y;
if (Math.abs(k) > u) {
var E = M, N = a, D = h;
M = y + u * (i && M > y ? 1 : -1), a = w + e * Math.cos(M), h = $ + n * Math.sin(M), I = yt(a, h, e, n, r, 0, i, N, D, [M, E, w, $]);
}
k = M - y;
var F = Math.cos(y), z = Math.sin(y), q = Math.cos(M), W = Math.sin(M), X = Math.tan(k / 4), P = 4 / 3 * e * X, V = 4 / 3 * n * X, A = [t, s], C = [t + P * z, s - V * F], st = [a + P * W, h - V * q], nt = [a, h];
if (C[0] = 2 * A[0] - C[0], C[1] = 2 * A[1] - C[1], l)
return [C, st, nt].concat(I);
I = [C, st, nt].concat(I).join().split(",");
for (var T = [], S = 0, j = I.length; S < j; S++)
T[S] = S % 2 ? f(I[S - 1], I[S], m).y : f(I[S], I[S + 1], m).x;
return T;
}, Bt = /,?([a-z]),?/gi;
function Mt(t) {
return t.join(",").replace(Bt, "$1");
}
function K(t) {
if (!t || !Array.isArray(t) || t.length === 0)
return tt(0, 0, 0, 0);
let s = 0, e = 0;
const n = [], r = [];
let o;
for (let u = 0, m = t.length; u < m; u++)
if (o = t[u], o[0] == "M")
s = isFinite(o[1]) ? o[1] : 0, e = isFinite(o[2]) ? o[2] : 0, n.push(s), r.push(e);
else {
const I = s, c = e, f = isFinite(o[1]) ? o[1] : 0, _ = isFinite(o[2]) ? o[2] : 0, b = isFinite(o[3]) ? o[3] : 0, d = isFinite(o[4]) ? o[4] : 0, g = isFinite(o[5]) ? o[5] : 0, v = isFinite(o[6]) ? o[6] : 0, p = Ot(I, c, f, _, b, d, g, v);
isFinite(p.min.x) && isFinite(p.max.x) && isFinite(p.min.y) && isFinite(p.max.y) && (n.push(p.min.x, p.max.x), r.push(p.min.y, p.max.y)), s = g, e = v;
}
if (n.length === 0 || r.length === 0)
return tt(0, 0, 0, 0);
const i = Math.min(...n), a = Math.min(...r), h = Math.max(...n), l = Math.max(...r);
return !isFinite(i) || !isFinite(a) || !isFinite(h) || !isFinite(l) ? tt(0, 0, 0, 0) : tt(i, a, h - i, l - a);
}
const tt = function(t, s, e, n) {
return t = isFinite(t) ? t : 0, s = isFinite(s) ? s : 0, e = isFinite(e) ? e : 0, n = isFinite(n) ? n : 0, {
x: t,
y: s,
w: e,
h: n,
cx: t + e / 2,
cy: s + n / 2
};
}, Ot = function(t, s, e, n, r, o, i, a) {
for (var h = [], l = [[], []], u, m, I, c, f, _, b, d, g = 0; g < 2; ++g) {
if (g == 0 ? (m = 6 * t - 12 * e + 6 * r, u = -3 * t + 9 * e - 9 * r + 3 * i, I = 3 * e - 3 * t) : (m = 6 * s - 12 * n + 6 * o, u = -3 * s + 9 * n - 9 * o + 3 * a, I = 3 * n - 3 * s), Math.abs(u) < 1e-12) {
if (Math.abs(m) < 1e-12)
continue;
c = -I / m, 0 < c && c < 1 && h.push(c);
continue;
}
b = m * m - 4 * I * u, d = Math.sqrt(b), !(b < 0) && (f = (-m + d) / (2 * u), 0 < f && f < 1 && h.push(f), _ = (-m - d) / (2 * u), 0 < _ && _ < 1 && h.push(_));
}
for (var v = h.length, p = v, w; v--; )
c = h[v], w = 1 - c, l[0][v] = w * w * w * t + 3 * w * w * c * e + 3 * w * c * c * r + c * c * c * i, l[1][v] = w * w * w * s + 3 * w * w * c * n + 3 * w * c * c * o + c * c * c * a;
return l[0][p] = t, l[1][p] = s, l[0][p + 1] = i, l[1][p + 1] = a, l[0].length = l[1].length = p + 2, {
min: { x: Math.min.apply(0, l[0]), y: Math.min.apply(0, l[1]) },
max: { x: Math.max.apply(0, l[0]), y: Math.max.apply(0, l[1]) }
};
};
function pt(t, s) {
const [e, n, r, o] = t.values, [i, a, h, l] = s.values, u = h / r, m = l / o, I = i - e * u, c = a - n * m;
return {
scaleX: u,
scaleY: m,
translateX: I,
translateY: c
};
}
function G(t, s, e) {
return [
t * e.scaleX + e.translateX,
s * e.scaleY + e.translateY
];
}
function Yt(t, s) {
if (!t || !t.trim())
return t;
try {
const e = wt(t), r = lt(e).map((o) => {
const i = o[0], a = o.slice(1), h = [i];
switch (i) {
case "M":
case "L":
if (a.length >= 2) {
const [l, u] = G(a[0], a[1], s);
h.push(l, u);
for (let m = 2; m < a.length; m += 2)
if (m + 1 < a.length) {
const [I, c] = G(a[m], a[m + 1], s);
h.push(I, c);
}
}
break;
case "C":
if (a.length >= 6) {
for (let l = 0; l < a.length; l += 2)
if (l + 1 < a.length) {
const [u, m] = G(a[l], a[l + 1], s);
h.push(u, m);
}
}
break;
case "Q":
if (a.length >= 4) {
for (let l = 0; l < a.length; l += 2)
if (l + 1 < a.length) {
const [u, m] = G(a[l], a[l + 1], s);
h.push(u, m);
}
}
break;
case "A":
if (a.length >= 7) {
const l = a[0] * s.scaleX, u = a[1] * s.scaleY, [m, I] = G(a[5], a[6], s);
h.push(l, u, a[2], a[3], a[4], m, I);
}
break;
case "H":
if (a.length >= 1) {
const [l] = G(a[0], 0, s);
h.push(l);
}
break;
case "V":
if (a.length >= 1) {
const [, l] = G(0, a[0], s);
h.push(l);
}
break;
case "Z":
case "z":
break;
default:
for (let l = 0; l < a.length; l += 2)
if (l + 1 < a.length) {
const [u, m] = G(a[l], a[l + 1], s);
h.push(u, m);
} else
h.push(a[l]);
}
return h;
});
return Mt(r);
} catch (e) {
return console.warn("Path transformation failed:", e), t;
}
}
function It(t, s = "", e) {
const n = {
gradients: {},
patterns: {},
others: {}
};
for (const [r, o] of Object.entries(t.gradients)) {
const i = s + r;
let a = o;
a = a.replace(new RegExp(`id="${r}"`, "g"), `id="${i}"`), a = a.replace(new RegExp(`id='${r}'`, "g"), `id='${i}'`), e && (a = Lt(a, e)), n.gradients[i] = a;
}
for (const [r, o] of Object.entries(t.patterns)) {
const i = s + r;
let a = o;
a = a.replace(new RegExp(`id="${r}"`, "g"), `id="${i}"`), a = a.replace(new RegExp(`id='${r}'`, "g"), `id='${i}'`), e && (a = Xt(a, e)), n.patterns[i] = a;
}
for (const [r, o] of Object.entries(t.others)) {
const i = s + r;
let a = o;
a = a.replace(new RegExp(`id="${r}"`, "g"), `id="${i}"`), a = a.replace(new RegExp(`id='${r}'`, "g"), `id='${i}'`), n.others[i] = a;
}
return n;
}
function Lt(t, s) {
let e = t;
return t.includes("linearGradient") && (e = e.replace(
/\b(x1|y1|x2|y2)=["']([^"']+)["']/g,
(n, r, o) => {
const i = ut(r, o, s);
return `${r}="${i}"`;
}
)), t.includes("radialGradient") && (e = e.replace(
/\b(cx|cy|fx|fy|r)=["']([^"']+)["']/g,
(n, r, o) => {
const i = ut(r, o, s);
return `${r}="${i}"`;
}
)), e;
}
function Xt(t, s) {
let e = t;
return e = e.replace(
/\b(x|y|width|height)=["']([^"']+)["']/g,
(n, r, o) => {
const i = ut(r, o, s);
return `${r}="${i}"`;
}
), e;
}
function ut(t, s, e) {
if (s.endsWith("%"))
return s;
const n = parseFloat(s);
if (isNaN(n))
return s;
let r;
switch (t) {
case "x1":
case "x2":
case "cx":
case "fx":
case "x":
r = n * e.scaleX + e.translateX;
break;
case "y1":
case "y2":
case "cy":
case "fy":
case "y":
r = n * e.scaleY + e.translateY;
break;
case "r":
r = n * Math.sqrt(e.scaleX * e.scaleY);
break;
case "width":
r = n * e.scaleX;
break;
case "height":
r = n * e.scaleY;
break;
default:
r = n;
}
return r.toFixed(3);
}
function et(t, s, e) {
let n = { ...s };
for (const [r, o] of Object.entries(n))
if (typeof o == "string" && o.startsWith("url(#")) {
const i = o.match(/url\(#([^)]+)\)/);
i && e[i[1]] && (n[r] = `url(#${e[i[1]]})`);
}
return {
pathData: t,
attrs: n
};
}
class zt {
/**
* SVGMorpheus Constructor | SVGMorpheus 构造器
* Creates a new SVGMorpheus instance for morphing SVG icons | 创建一个新的 SVGMorpheus 实例用于变形 SVG 图标
*
* @param element Target SVG element or CSS selector | 目标 SVG 元素或 CSS 选择器
* - string: CSS selector to find the SVG element | 字符串:用于查找 SVG 元素的 CSS 选择器
* - HTMLElement: Direct reference to HTML element containing SVG | HTML 元素:直接引用包含 SVG 的 HTML 元素
* - SVGSVGElement: Direct reference to SVG element | SVG 元素:直接引用 SVG 元素
*
* @param options Configuration options for default behavior | 默认行为的配置选项
* - iconId: Initial icon to display | 初始显示的图标
* - duration: Default animation duration (ms) | 默认动画持续时间(毫秒)
* - easing: Default easing function name | 默认缓动函数名称
* - rotation: Default rotation direction | 默认旋转方向
*
* @param callback Default callback function executed after animations complete | 动画完成后执行的默认回调函数
* Called when any morphing animation finishes | 当任何变形动画完成时被调用
* Can be overridden by individual to() method calls | 可以被单独的 to() 方法调用覆盖
*/
constructor(s, e, n) {
if (this._icons = {}, this._curIconId = "", this._toIconId = "", this._curIconItems = [], this._fromIconItems = [], this._toIconItems = [], this._morphNodes = [], this._morphG = null, this._svgDoc = null, !s)
throw new Error('SVGMorpheus > "element" is required');
let r;
if (typeof s == "string") {
const i = document.querySelector(s);
if (!i)
throw new Error('SVGMorpheus > "element" query is not related to an existing DOM node');
r = i;
} else
r = s;
if (e && typeof e != "object")
throw new Error('SVGMorpheus > "options" parameter must be an object');
if (e = e || {}, n && typeof n != "function")
throw new Error('SVGMorpheus > "callback" parameter must be a function');
const o = this;
this._icons = {}, this._curIconId = e.iconId || "", this._toIconId = "", this._curIconItems = [], this._fromIconItems = [], this._toIconItems = [], this._morphNodes = [], this._morphG = null, this._startTime = void 0, this._defDuration = e.duration || 750, this._defEasing = e.easing || "quad-in-out", this._defRotation = e.rotation || "clock", this._defCallback = n || function() {
}, this._duration = this._defDuration, this._easing = this._defEasing, this._rotation = this._defRotation, this._callback = this._defCallback, this._rafid = void 0, this._fnTick = function(i) {
o._startTime || (o._startTime = i);
const a = Math.min((i - o._startTime) / o._duration, 1);
o._updateAnimationProgress(a), a < 1 ? o._rafid = ht(o._fnTick) : o._toIconId !== "" && o._animationEnd();
}, r.nodeName.toUpperCase() === "SVG" ? this._svgDoc = r : this._svgDoc = r.getSVGDocument(), this._svgDoc ? o._init() : r.addEventListener("load", function() {
o._svgDoc = r.getSVGDocument(), o._init();
}, !1);
}
_init() {
if (this._svgDoc) {
if (this._svgDoc.nodeName.toUpperCase() !== "SVG") {
const s = this._svgDoc.getElementsByTagName("svg");
this._svgDoc = s[0];
}
if (this._svgDoc) {
let s = "";
const e = this._svgDoc.outerHTML, n = vt(e), r = at(e), o = ct(e);
for (let a = this._svgDoc.childNodes.length - 1; a >= 0; a--) {
const h = this._svgDoc.childNodes[a];
if (h.nodeName.toUpperCase() === "G") {
const l = h, u = l.getAttribute("id");
if (u) {
const m = [];
let I = n || void 0, c = r, f = o;
const _ = l.getAttribute("data-original-viewbox");
if (_) {
const g = _.trim().split(/\s+/).map(Number);
g.length === 4 && (I = {
values: [g[0], g[1], g[2], g[3]],
original: _
});
}
const b = l.outerHTML, d = at(b);
c = {
gradients: { ...r.gradients, ...d.gradients },
patterns: { ...r.patterns, ...d.patterns },
others: { ...r.others, ...d.others },
raw: d.raw || r.raw
}, f = { ...o, ...ct(b) };
for (let g = 0, v = l.childNodes.length; g < v; g++) {
const p = l.childNodes[g], w = {
path: "",
attrs: {},
style: {}
};
switch (p.nodeName.toUpperCase()) {
case "PATH":
w.path = p.getAttribute("d") || "";
break;
case "CIRCLE":
const $ = p, y = parseFloat($.getAttribute("cx") || "0"), M = parseFloat($.getAttribute("cy") || "0"), k = parseFloat($.getAttribute("r") || "0");
w.path = `M${y - k},${M}a${k},${k} 0 1,0 ${k * 2},0a${k},${k} 0 1,0 -${k * 2},0z`;
break;
case "ELLIPSE":
const E = p, N = parseFloat(E.getAttribute("cx") || "0"), D = parseFloat(E.getAttribute("cy") || "0"), F = parseFloat(E.getAttribute("rx") || "0"), z = parseFloat(E.getAttribute("ry") || "0");
w.path = `M${N - F},${D}a${F},${z} 0 1,0 ${F * 2},0a${F},${z} 0 1,0 -${F * 2},0z`;
break;
case "RECT":
const q = p, W = parseFloat(q.getAttribute("x") || "0"), X = parseFloat(q.getAttribute("y") || "0"), P = parseFloat(q.getAttribute("width") || "0"), V = parseFloat(q.getAttribute("height") || "0"), A = parseFloat(q.getAttribute("rx") || "0"), C = parseFloat(q.getAttribute("ry") || "0");
!A && !C ? w.path = `M${W},${X}l${P},0l0,${V}l-${P},0z` : w.path = `M${W + A},${X}l${P - A * 2},0a${A},${C} 0 0,1 ${A},${C}l0,${V - C * 2}a${A},${C} 0 0,1 -${A},${C}l${A * 2 - P},0a${A},${C} 0 0,1 -${A},-${C}l0,${C * 2 - V}a${A},${C} 0 0,1 ${A},-${C}z`;
break;
case "POLYGON":
const T = (p.getAttribute("points") || "").split(/\s+/);
let S = "";
for (let O = 0, xt = T.length; O < xt; O++)
S += (O && "L" || "M") + T[O];
w.path = S + "z";
break;
case "LINE":
const j = p, U = parseFloat(j.getAttribute("x1") || "0"), Q = parseFloat(j.getAttribute("y1") || "0"), B = parseFloat(j.getAttribute("x2") || "0"), ot = parseFloat(j.getAttribute("y2") || "0");
w.path = `M${U},${Q}L${B},${ot}z`;
break;
}
if (w.path !== "") {
for (let y = 0, M = p.attributes.length; y < M; y++) {
const k = p.attributes[y];
if (k.specified) {
const E = k.name.toLowerCase();
switch (E) {
case "fill":
case "fill-opacity":
case "opacity":
case "stroke":
case "stroke-opacity":
case "stroke-width":
w.attrs[E] = k.value;
}
}
}
const $ = p.style;
for (let y = 0, M = $.length; y < M; y++) {
const k = $[y];
switch (k) {
case "fill":
case "fill-opacity":
case "opacity":
case "stroke":
case "stroke-opacity":
case "stroke-width":
w.style[k] = $[k];
}
}
m.push(w);
}
}
if (m.length > 0) {
const g = {
id: u,
items: m,
viewBox: I,
defs: c,
rootAttrs: f
};
this._icons[u] = g;
}
this._morphG ? this._svgDoc.removeChild(h) : (s = u, this._morphG = document.createElementNS("http://www.w3.org/2000/svg", "g"), this._svgDoc.replaceChild(this._morphG, h));
}
}
}
const i = this._curIconId || s;
i !== "" && (this._setupAnimation(i), this._updateAnimationProgress(1), this._animationEnd());
}
}
}
_setupAnimation(s) {
var e, n, r, o, i, a, h, l;
if (s && this._icons[s]) {
this._toIconId = s, this._startTime = void 0;
let u, m;
this._fromIconItems = L(this._curIconItems), this._toIconItems = L(this._icons[s].items);
const I = this._icons[this._curIconId], c = this._icons[s], f = c.viewBox || (I == null ? void 0 : I.viewBox) || { values: [0, 0, 24, 24], original: "0 0 24 24" };
if (this._svgDoc && this._svgDoc.setAttribute("viewBox", f.original), I && I.viewBox && c.viewBox) {
const d = pt(I.viewBox, f), g = `from_${this._curIconId}_`, v = {};
I.defs && (Object.keys(I.defs.gradients).forEach((p) => {
v[p] = g + p;
}), Object.keys(I.defs.patterns).forEach((p) => {
v[p] = g + p;
}), Object.keys(I.defs.others).forEach((p) => {
v[p] = g + p;
})), this._fromIconItems = this._fromIconItems.map((p) => {
const w = Yt(p.path, d), $ = et(w, p.attrs, v), y = et(w, p.style, v);
return {
...p,
path: w,
attrs: $.attrs,
style: y.attrs
};
});
}
if (c.defs) {
const d = `to_${s}_`, g = {};
Object.keys(c.defs.gradients).forEach((v) => {
g[v] = d + v;
}), Object.keys(c.defs.patterns).forEach((v) => {
g[v] = d + v;
}), Object.keys(c.defs.others).forEach((v) => {
g[v] = d + v;
}), this._toIconItems = this._toIconItems.map((v) => {
const p = et(v.path, v.attrs, g), w = et(v.path, v.style, g);
return {
...v,
attrs: p.attrs,
style: w.attrs
};
}), this._injectTransformedDefs(I, c);
}
for (u = 0, m = this._morphNodes.length; u < m; u++) {
const d = this._morphNodes[u];
d.fromIconItemIdx = u, d.toIconItemIdx = u;
}
const _ = Math.max(this._fromIconItems.length, this._toIconItems.length);
let b;
for (u = 0; u < _; u++)
if (this._fromIconItems[u] || (this._toIconItems[u] ? (b = K(it(this._toIconItems[u].path)), this._fromIconItems.push({
path: "M" + b.cx + "," + b.cy + "l0,0",
attrs: {},
style: {},
trans: {
rotate: [0, b.cx, b.cy]
}
})) : this._fromIconItems.push({
path: "M0,0l0,0",
attrs: {},
style: {},
trans: {
rotate: [0, 0, 0]
}
})), this._toIconItems[u] || (this._fromIconItems[u] ? (b = K(it(this._fromIconItems[u].path)), this._toIconItems.push({
path: "M" + b.cx + "," + b.cy + "l0,0",
attrs: {},
style: {},
trans: {
rotate: [0, b.cx, b.cy]
}
})) : this._toIconItems.push({
path: "M0,0l0,0",
attrs: {},
style: {},
trans: {
rotate: [0, 0, 0]
}
})), !this._morphNodes[u] && this._morphG) {
const d = document.createElementNS("http://www.w3.org/2000/svg", "path");
this._morphG.appendChild(d), this._morphNodes.push({
node: d,
fromIconItemIdx: u,
toIconItemIdx: u
});
}
for (u = 0; u < _; u++) {
const d = this._fromIconItems[u], g = this._toIconItems[u], v = it(this._fromIconItems[u].path, this._toIconItems[u].path);
d.curve = v[0], g.curve = v[1];
const p = mt(this._fromIconItems[u].attrs, this._toIconItems[u].attrs);
d.attrsNorm = p[0], g.attrsNorm = p[1], d.attrs = Y(d.attrsNorm), g.attrs = Y(g.attrsNorm);
const w = mt(this._fromIconItems[u].style, this._toIconItems[u].style);
d.styleNorm = w[0], g.styleNorm = w[1], d.style = Y(d.styleNorm), g.style = Y(g.styleNorm), b = K(g.curve);
let $ = 0, y = 0, M = 0;
for (let D = 0; D < this._toIconItems.length; D++)
if (this._toIconItems[D].curve) {
const F = K(this._toIconItems[D].curve);
F && !isNaN(F.cx) && !isNaN(F.cy) && ($ += F.cx, y += F.cy, M++);
}
const k = M > 0 ? { x: $ / M, y: y / M } : { x: 12, y: 12 };
g.trans = {
rotate: [0, k.x, k.y]
}, d.trans ? d.trans.rotate && (d.trans.rotate[0] = 0, d.trans.rotate[1] = k.x, d.trans.rotate[2] = k.y) : d.trans = {
rotate: [0, k.x, k.y]
};
let E = this._rotation, N;
switch (E === "random" && (E = Math.random() < 0.5 ? "counterclock" : "clock"), E) {
case "none":
(e = d.trans) != null && e.rotate && ((n = g.trans) != null && n.rotate) && (g.trans.rotate[0] = d.trans.rotate[0]);
break;
case "counterclock":
(r = d.trans) != null && r.rotate && ((o = g.trans) != null && o.rotate) ? (g.trans.rotate[0] = d.trans.rotate[0] - 360, N = -d.trans.rotate[0] % 360, g.trans.rotate[0] += N < 180 ? N : N - 360) : (i = g.trans) != null && i.rotate && (g.trans.rotate[0] = -360);
break;
default:
(a = d.trans) != null && a.rotate && ((h = g.trans) != null && h.rotate) ? (g.trans.rotate[0] = d.trans.rotate[0] + 360, N = d.trans.rotate[0] % 360, g.trans.rotate[0] += N < 180 ? -N : 360 - N) : (l = g.trans) != null && l.rotate && (g.trans.rotate[0] = 360);
break;
}
}
this._curIconItems = L(this._fromIconItems);
}
}
_updateAnimationProgress(s) {
s = x[this._easing](s);
let e, n, r, o;
for (e = 0, o = this._curIconItems.length; e < o; e++)
this._fromIconItems[e].curve && this._toIconItems[e].curve && (this._curIconItems[e].curve = At(this._fromIconItems[e].curve, this._toIconItems[e].curve, s), this._curIconItems[e].path = Mt(this._curIconItems[e].curve)), this._fromIconItems[e].attrsNorm && this._toIconItems[e].attrsNorm && (this._curIconItems[e].attrsNorm = ft(this._fromIconItems[e].attrsNorm, this._toIconItems[e].attrsNorm, s), this._curIconItems[e].attrs = Y(this._curIconItems[e].attrsNorm)), this._fromIconItems[e].styleNorm && this._toIconItems[e].styleNorm && (this._curIconItems[e].styleNorm = ft(this._fromIconItems[e].styleNorm, this._toIconItems[e].styleNorm, s), this._curIconItems[e].style = Y(this._curIconItems[e].styleNorm)), this._fromIconItems[e].trans && this._toIconItems[e].trans && (this._curIconItems[e].trans = $t(this._fromIconItems[e].trans, this._toIconItems[e].trans, s), this._curIconItems[e].transStr = Ct(this._curIconItems[e].trans));
for (e = 0, o = this._morphNodes.length; e < o; e++) {
const i = this._morphNodes[e];
i.node.setAttribute("d", this._curIconItems[e].path);
const a = this._curIconItems[e].attrs;
for (n in a)
i.node.setAttribute(n, a[n]);
const h = this._curIconItems[e].style;
for (r in h)
i.node.style[r] = h[r];
i.node.setAttribute("transform", this._curIconItems[e].transStr || "");
}
}
_animationEnd() {
for (let s = this._morphNodes.length - 1; s >= 0; s--) {
const e = this._morphNodes[s];
if (this._toIconItems[s]) {
e.node.setAttribute("d", this._toIconItems[s].path);
const n = this._toIconItems[s].attrs;
for (const i in n)
e.node.setAttribute(i, n[i]);
const r = this._toIconItems[s].style;
for (const i in r)
e.node.style[i] = r[i];
const o = this._toIconItems[s].transStr || "";
e.node.setAttribute("transform", o);
} else
e.node.parentNode && e.node.parentNode.removeChild(e.node), this._morphNodes.splice(s, 1);
}
this._curIconId = this._toIconId, this._toIconId = "", this._callback();
}
// Public methods | 公共方法
/**
* Morph to target icon | 变形到目标图标
* Triggers morphing animation from current icon to specified target icon | 触发从当前图标到指定目标图标的变形动画
*
* @param iconId Target icon ID to morph to | 要变形到的目标图标ID
* Must match an ID of a <g> element in the SVG | 必须匹配 SVG 中某个 <g> 元素的ID
*
* @param options Animation options for this specific morph | 此次特定变形的动画选项
* Overrides constructor defaults for this animation only | 仅为此次动画覆盖构造器默认值
* - duration: Animation duration (ms) | 动画持续时间(毫秒)
* - easing: Easing function name | 缓动函数名称
* - rotation: Rotation direction | 旋转方向
*
* @param callback Callback function for this specific morph | 此次特定变形的回调函数
* Overrides constructor default callback for this animation only | 仅为此次动画覆盖构造器默认回调
* Called when this specific morphing animation completes | 当此次特定变形动画完成时被调用
*/
to(s, e, n) {
if (s !== this._toIconId) {
if (e && typeof e != "object")
throw new Error('SVGMorpheus.to() > "options" parameter must be an object');
if (e = e || {}, n && typeof n != "function")
throw new Error('SVGMorpheus.to() > "callback" parameter must be a function');
this._rafid && kt(this._rafid), this._duration = e.duration || this._defDuration, this._easing = e.easing || this._defEasing, this._rotation = e.rotation || this._defRotation, this._callback = n || this._defCallback, this._setupAnimation(s), this._rafid = ht(this._fnTick);
}
}
/**
* Register custom easing function | 注册自定义缓动函数
* Adds a custom easing function that can be used in animations | 添加可在动画中使用的自定义缓动函数
*
* @param name Unique name for the easing function | 缓动函数的唯一名称
* This name will be used to reference the function in options | 此名称将用于在选项中引用该函数
*
* @param fn Custom easing function | 自定义缓动函数
* Takes progress (0-1) and returns eased progress (typically 0-1) | 接受进度值(0-1)并返回缓动后的进度值(通常为0-1)
* @param progress Animation progress from 0 to 1 | 从0到1的动画进度
* @returns Eased progress value | 缓动后的进度值
*
* @example
* // Register a custom bounce easing | 注册自定义弹跳缓动
* morpheus.registerEasing('my-bounce', (t) => {
* return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
* });
*/
registerEasing(s, e) {
x[s] = e;
}
/**
* 动态插入转换后的defs到SVG文档中
*/
_injectTransformedDefs(s, e) {
if (!this._svgDoc) return;
let n = this._svgDoc.querySelector("defs");
if (n || (n = document.createElementNS("http://www.w3.org/2000/svg", "defs"), this._svgDoc.insertBefore(n, this._svgDoc.firstChild)), s && s.defs && s.viewBox) {
const r = `from_${this._curIconId}_`, o = e.viewBox || { values: [0, 0, 24, 24] }, i = pt(s.viewBox, o), a = It(s.defs, r, i);
this._insertDefsContent(n, a);
}
if (e.defs) {
const r = `to_${e.id}_`, o = It(e.defs, r);
this._insertDefsContent(n, o);
}
}
/**
* 插入defs内容到defs元素中
*/
_insertDefsContent(s, e) {
const n = new DOMParser();
Object.values(e.gradients).forEach((r) => {
try {
const i = n.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${r}</svg>`, "image/svg+xml").documentElement.firstElementChild;
if (i) {
const a = document.importNode(i, !0);
s.appendChild(a);
}
} catch (o) {
console.warn("Failed to parse gradient:", r, o);
}
}), Object.values(e.patterns).forEach((r) => {
try {
const i = n.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${r}</svg>`, "image/svg+xml").documentElement.firstElementChild;
if (i) {
const a = document.importNode(i, !0);
s.appendChild(a);
}
} catch (o) {
console.warn("Failed to parse pattern:", r, o);
}
}), Object.values(e.others).forEach((r) => {
try {
const i = n.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${r}</svg>`, "image/svg+xml").documentElement.firstElementChild;
if (i) {
const a = document.importNode(i, !0);
s.appendChild(a);
}
} catch (o) {
console.warn("Failed to parse other def:", r, o);
}
});
}
}
export {
zt as SVGMorpheus,
Tt as bundleSvgs,
Ht as bundleSvgsString,
L as clone,
At as curveCalc,
K as curvePathBBox,
zt as default,
x as easings,
wt as parsePathString,
it as path2curve,
Mt as path2string,
lt as pathToAbsolute,
ft as styleNormCalc,
Y as styleNormToString,
mt as styleToNorm,
Ct as trans2string,
$t as transCalc
};