UNPKG

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
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 };