gpt4 book ai didi

javascript - 如何在 SVG 路径数据 (d) 字符串本身中执行旋转?

转载 作者:行者123 更新时间:2023-12-05 04:26:48 26 4
gpt4 key购买 nike

我正在制作一个图形和图表网络应用程序,我想对其中的不同形状执行旋转操作。不使用 CSS 或任何转换属性,我想对路径数据(d 参数)本身应用旋转。那么,我如何在数学上处理“d”属性中的点(包括大写和小写命令),以便它输出一个新的“d”字符串,表示围绕原点(x,y)进行 theta 度旋转后的旋转形状?例如,在此路径字符串 d="M349,228h212v-1331h-212v133"中,我想应用 transform=rotate(24) 和 transform-origin="455px 161.5px"。应用这些转换后,最终的 d 是什么?

最佳答案

另一种方法可能是通过 matrixTransform() 转换路径坐标。

timo22345 的要点中使用了这个概念 flatten.js并且还可以将其他转换(例如 scale()translate() )转换为硬编码路径命令。

简化示例

/**
* getTransformToElement polyfill
*/
SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(toElement) {
let matrix = toElement.getScreenCTM().inverse().multiply(this.getScreenCTM())
return matrix;
};

function convertTransform(decimals = 3) {
let svg = document.querySelector('svg');
let transformed = svg.querySelectorAll('*[transform]');
let transformedTotal = transformed.length;

if (transformedTotal) {
transformed.forEach(function(el, i) {
let type = el.nodeName.toLowerCase();
let shapes = ['path', 'circle', 'rect', 'polygon', 'polyline', 'line', 'ellipse'];

if (shapes.indexOf(type) !== -1) {
// normalize pathdata to get absolute coordinates
let pathData = el.getPathData({
normalize: true
})

// get transform matrix
let matrix = el.getTransformToElement(el.parentNode);
el.removeAttribute('transform');

pathData.forEach(function(command, d) {
let values = command.values;
// loop through coordinates:
for (let v = 0; v < values.length - 1; v += 2) {
let [x, y] = [values[v], values[v + 1]];
let pt = svg.createSVGPoint();
pt.x = x;
pt.y = y;
// change coordinates by matrix transform
let pTrans = pt.matrixTransform(matrix);
// save coordinates to pathdata array
pathData[d]['values'][v] = +pTrans.x.toFixed(decimals);
pathData[d]['values'][v + 1] = +pTrans.y.toFixed(decimals);
}
})

//check if conversion is needed for primitives (rect, circle, polygons etc.)
if (type !== 'path') {
let newPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
let atts = [...el.attributes];
let excludedAtts = ['d', 'x', 'y', 'x1', 'y1', 'x2', 'y2', 'cx', 'cy', 'r', 'rx', 'ry', 'points', 'height', 'width'];
for (let a = 0; a < atts.length; a++) {
let att = atts[a];
if (excludedAtts.indexOf(att.nodeName) === -1) {
var attrName = att.nodeName;
var attrValue = att.nodeValue;
newPath.setAttribute(attrName, attrValue + '');
}
}
el.replaceWith(newPath);
el = newPath;
}
el.setPathData(pathData)
}
})
}
}
<script src="https://cdn.jsdelivr.net/npm/path-data-polyfill@1.0.3/path-data-polyfill.min.js"></script>
<p><button type="button" onclick="convertTransform()"> Convert transforms </button></p>
<svg viewBox="0 0 100 100" overflow="visible">
<path class="" d="M25 25 h25 v25 h-25 z" fill="green" />
<rect x="0" y="0" width="33%" height="20" transform="rotate(27 20 50) translate(20 10)" fill="orange" />
<path data-att="random" transform="rotate(45 50 50) scale(1.2) translate(10 -20)" class="transform" d="M25 25 h25 v25 h-25 z" fill="red" />
</svg>

工作原理

  1. 我们需要通过 getTransformToElement() 获取每个元素的转换矩阵(包括 polyfill)
  2. 我们需要将路径数据转换为绝对命令(使用 Jarek Foksa's path-data-polyfill )
  3. 可以使用 point.matrixTransform(matrix)
  4. 将每个命令的点 (x/y) 转换为新的 x/y 值

上面的脚本被简化了:它不能转换嵌套转换(比如嵌套转换组)——timo22345 flatten.js 可以通过应用多个转换来完成这个技巧(并且它不需要辅助库/polyfills)。

基于flatten.js的例子(多次嵌套转换)

let svg = document.querySelector('svg');


SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(e) {
return e.getScreenCTM().inverse().multiply(this.getScreenCTM())
},
function() {
var e = /,?([achlmqrstvxz]),?/gi,
t = function(t) {
return t.join(",").replace(e, "$1")
};

function r(e, t, r, a, n, u, i, c) {
function o(e) {
return Math.abs(e) < 1e-16
}
var l, s, h, f, x, y, p, g, b, v, m, M = [];
if (l = e, s = t, h = r *= Math.PI / 180, f = parseFloat(Math.sin(h)), x = parseFloat(Math.cos(h)), M[0] = i.a * +l * x + i.c * l * f, M[1] = i.b * +l * x + i.d * l * f, M[2] = i.a * -s * f + i.c * s * x, M[3] = i.b * -s * f + i.d * s * x, b = (y = M[0] * M[0] + M[2] * M[2]) - (g = M[1] * M[1] + M[3] * M[3]), o(p = 2 * (M[0] * M[1] + M[2] * M[3]))) r = 0, v = y, m = g;
else if (o(b)) v = y + .5 * p, m = y - .5 * p, r = Math.PI / 4;
else {
var d = 1 + p * p / (b * b);
v = .5 * (y + g + (d = d < 0 ? 0 : Math.sqrt(d)) * b), m = .5 * (y + g - d * b), r = .5 * Math.atan2(p, b)
}
return v = v < 0 ? 0 : Math.sqrt(v), m = m < 0 ? 0 : Math.sqrt(m), b <= 0 ? (t = v, e = m) : (t = m, e = v), i.a * i.d - i.b * i.c < 0 && (n = n ? 0 : 1), u = u.matrixTransform(i), ["A", e, t, r = 180 * r / Math.PI, a, n, u.x, u.y]
}
var a = {},
n = "hasOwnProperty",
u = String,
i = "array",
c = {
NaN: 1,
Infinity: 1,
"-Infinity": 1
},
o = u.prototype.toLowerCase,
l = u.prototype.toUpperCase,
s = Object.prototype.toString,
h = Math,
f = h.max,
x = (h.min, h.abs, h.pow, h.PI),
y = (h.round, parseFloat),
p = (parseInt, e = /,?([achlmqrstvxz]),?/gi, /([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/gi),
g = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/gi;

function b(e) {
if (Object(e) !== e) return e;
var t = new e.constructor;
for (var r in e) e[n](r) && (t[r] = b(e[r]));
return t
}
a.is = function(e, t) {
return "finite" == (t = o.call(t)) ? !c[n](+e) : "array" == t ? e instanceof Array : "null" == t && null === e || t == typeof e && null !== e || "object" == t && e === Object(e) || "array" == t && Array.isArray && Array.isArray(e) || s.call(e).slice(8, -1).toLowerCase() == t
}, a._path2string = function() {
return this.join(",").replace(e, "$1")
};
var v = function(e) {
var t = b(e);
return t.toString = a._path2string, t
},
m = function(e) {
var t = m.ps = m.ps || {};
return t[e] ? t[e].sleep = 100 : t[e] = {
sleep: 100
}, setTimeout((function() {
for (var r in t) t[n](r) && r != e && (t[r].sleep--, !t[r].sleep && delete t[r])
})), t[e]
},
M = function(e) {
if (!e) return null;
var t = m(e);
if (t.arr) return v(t.arr);
var r = {
a: 7,
c: 6,
h: 1,
l: 2,
m: 2,
r: 4,
q: 4,
s: 4,
t: 2,
v: 1,
z: 0
},
n = [];
return a.is(e, i) && a.is(e[0], i) && (n = v(e)), n.length || u(e).replace(p, (function(e, t, a) {
var u = [],
i = t.toLowerCase();
if (a.replace(g, (function(e, t) {
t && u.push(+t)
})), "m" == i && u.length > 2 && (n.push([t].concat(u.splice(0, 2))), i = "l", t = "m" == t ? "l" : "L"), "r" == i) n.push([t].concat(u));
else
for (; u.length >= r[i] && (n.push([t].concat(u.splice(0, r[i]))), r[i]););
})), n.toString = a._path2string, t.arr = v(n), n
};
var d = A((function(e) {
if (a.is(e, i) && a.is(e && e[0], i) || (e = M(e)), !e || !e.length) return [
["M", 0, 0]
];
var t = [],
r = 0,
n = 0,
u = 0,
c = 0,
o = 0;
"M" == e[0][0] && (u = r = +e[0][1], c = n = +e[0][2], o++, t[0] = ["M", r, n]);
for (var s, h, f = 3 == e.length && "M" == e[0][0] && "R" == e[1][0].toUpperCase() && "Z" == e[2][0].toUpperCase(), x = o, y = e.length; x < y; x++) {
if (t.push(s = []), (h = e[x])[0] != l.call(h[0])) switch (s[0] = l.call(h[0]), s[0]) {
case "A":
s[1] = h[1], s[2] = h[2], s[3] = h[3], s[4] = h[4], s[5] = h[5], s[6] = +(h[6] + r), s[7] = +(h[7] + n);
break;
case "V":
s[1] = +h[1] + n;
break;
case "H":
s[1] = +h[1] + r;
break;
case "R":
for (var p = [r, n].concat(h.slice(1)), g = 2, b = p.length; g < b; g++) p[g] = +p[g] + r, p[++g] = +p[g] + n;
t.pop(), t = t.concat(catmullRom2bezier(p, f));
break;
case "M":
u = +h[1] + r, c = +h[2] + n;
default:
for (g = 1, b = h.length; g < b; g++) s[g] = +h[g] + (g % 2 ? r : n)
} else if ("R" == h[0]) p = [r, n].concat(h.slice(1)), t.pop(), t = t.concat(catmullRom2bezier(p, f)), s = ["R"].concat(h.slice(-2));
else
for (var v = 0, m = h.length; v < m; v++) s[v] = h[v];
switch (s[0]) {
case "Z":
r = u, n = c;
break;
case "H":
r = s[1];
break;
case "V":
n = s[1];
break;
case "M":
u = s[s.length - 2], c = s[s.length - 1];
default:
r = s[s.length - 2], n = s[s.length - 1]
}
}
return t.toString = a._path2string, t
}));

function A(e, t, r) {
return function a() {
var n = Array.prototype.slice.call(arguments, 0),
u = n.join("␀"),
i = a.cache = a.cache || {},
c = a.count = a.count || [];
if (i.hasOwnProperty(u)) {
for (var o = 0, l = c.length; o < l; o++) c[o] === u && c.push(c.splice(o, 1)[0]);
return r ? r(i[u]) : i[u]
}
return c.length >= 1e3 && delete i[c.shift()], c.push(u), i[u] = e.apply(t, n), r ? r(i[u]) : i[u]
}
}
var C = function(e, t, r, a) {
return [e, t, r, a, r, a]
},
q = function(e, t, r, a, n, u) {
var i = 1 / 3,
c = 2 / 3;
return [i * e + c * r, i * t + c * a, i * n + c * r, i * u + c * a, n, u]
},
S = A((function(e, t, r, a, n, u, i, c, o, l) {
var s, h = 120 * x / 180,
f = x / 180 * (+n || 0),
y = [],
p = A((function(e, t, r) {
return {
x: e * Math.cos(r) - t * Math.sin(r),
y: e * Math.sin(r) + t * Math.cos(r)
}
}));
if (l) w = l[0], V = l[1], C = l[2], q = l[3];
else {
e = (s = p(e, t, -f)).x, t = s.y, c = (s = p(c, o, -f)).x, o = s.y;
Math.cos(x / 180 * n), Math.sin(x / 180 * n);
var g = (e - c) / 2,
b = (t - o) / 2,
v = g * g / (r * r) + b * b / (a * a);
v > 1 && (r *= v = Math.sqrt(v), a *= v);
var m = r * r,
M = a * a,
d = (u == i ? -1 : 1) * Math.sqrt(Math.abs((m * M - m * b * b - M * g * g) / (m * b * b + M * g * g))),
C = d * r * b / a + (e + c) / 2,
q = d * -a * g / r + (t + o) / 2,
w = Math.asin(((t - q) / a).toFixed(9)),
V = Math.asin(((o - q) / a).toFixed(9));
(w = e < C ? x - w : w) < 0 && (w = 2 * x + w), (V = c < C ? x - V : V) < 0 && (V = 2 * x + V), i && w > V && (w -= 2 * x), !i && V > w && (V -= 2 * x)
}
var k = V - w;
if (Math.abs(k) > h) {
var L = V,
E = c,
T = o;
V = w + h * (i && V > w ? 1 : -1), c = C + r * Math.cos(V), o = q + a * Math.sin(V), y = S(c, o, r, a, n, 0, i, E, T, [V, L, C, q])
}
k = V - w;
var G = Math.cos(w),
P = Math.sin(w),
Z = Math.cos(V),
_ = Math.sin(V),
j = Math.tan(k / 4),
z = 4 / 3 * r * j,
H = 4 / 3 * a * j,
I = [e, t],
R = [e + z * P, t - H * G],
F = [c + z * _, o - H * Z],
N = [c, o];
if (R[0] = 2 * I[0] - R[0], R[1] = 2 * I[1] - R[1], l) return [R, F, N].concat(y);
for (var O = [], U = 0, Q = (y = [R, F, N].concat(y).join().split(",")).length; U < Q; U++) O[U] = U % 2 ? p(y[U - 1], y[U], f).y : p(y[U], y[U + 1], f).x;
return O
})),
w = A((function(e, t) {
var r = !t && m(e);
if (!t && r.curve) return v(r.curve);
for (var a = d(e), n = t && d(t), u = {
x: 0,
y: 0,
bx: 0,
by: 0,
X: 0,
Y: 0,
qx: null,
qy: null
}, i = {
x: 0,
y: 0,
bx: 0,
by: 0,
X: 0,
Y: 0,
qx: null,
qy: null
}, c = function(e, t, r) {
var a, n;
if (!e) return ["C", t.x, t.y, t.x, t.y, t.x, t.y];
switch (!(e[0] in {
T: 1,
Q: 1
}) && (t.qx = t.qy = null), e[0]) {
case "M":
t.X = e[1], t.Y = e[2];
break;
case "A":
e = ["C"].concat(S.apply(0, [t.x, t.y].concat(e.slice(1))));
break;
case "S":
"C" == r || "S" == r ? (a = 2 * t.x - t.bx, n = 2 * t.y - t.by) : (a = t.x, n = t.y), e = ["C", a, n].concat(e.slice(1));
break;
case "T":
"Q" == r || "T" == r ? (t.qx = 2 * t.x - t.qx, t.qy = 2 * t.y - t.qy) : (t.qx = t.x, t.qy = t.y), e = ["C"].concat(q(t.x, t.y, t.qx, t.qy, e[1], e[2]));
break;
case "Q":
t.qx = e[1], t.qy = e[2], e = ["C"].concat(q(t.x, t.y, e[1], e[2], e[3], e[4]));
break;
case "L":
e = ["C"].concat(C(t.x, t.y, e[1], e[2]));
break;
case "H":
e = ["C"].concat(C(t.x, t.y, e[1], t.y));
break;
case "V":
e = ["C"].concat(C(t.x, t.y, t.x, e[1]));
break;
case "Z":
e = ["C"].concat(C(t.x, t.y, t.X, t.Y))
}
return e
}, o = function(e, t) {
if (e[t].length > 7) {
e[t].shift();
for (var r = e[t]; r.length;) s[t] = "A", n && (h[t] = "A"), e.splice(t++, 0, ["C"].concat(r.splice(0, 6)));
e.splice(t, 1), b = f(a.length, n && n.length || 0)
}
}, l = function(e, t, r, u, i) {
e && t && "M" == e[i][0] && "M" != t[i][0] && (t.splice(i, 0, ["M", u.x, u.y]), r.bx = 0, r.by = 0, r.x = e[i][1], r.y = e[i][2], b = f(a.length, n && n.length || 0))
}, s = [], h = [], x = "", p = "", g = 0, b = f(a.length, n && n.length || 0); g < b; g++) {
a[g] && (x = a[g][0]), "C" != x && (s[g] = x, g && (p = s[g - 1])), a[g] = c(a[g], u, p), "A" != s[g] && "C" == x && (s[g] = "C"), o(a, g), n && (n[g] && (x = n[g][0]), "C" != x && (h[g] = x, g && (p = h[g - 1])), n[g] = c(n[g], i, p), "A" != h[g] && "C" == x && (h[g] = "C"), o(n, g)), l(a, n, u, i, g), l(n, a, i, u, g);
var M = a[g],
A = n && n[g],
w = M.length,
V = n && A.length;
u.x = M[w - 2], u.y = M[w - 1], u.bx = y(M[w - 4]) || u.x, u.by = y(M[w - 3]) || u.y, i.bx = n && (y(A[V - 4]) || i.x), i.by = n && (y(A[V - 3]) || i.y), i.x = n && A[V - 2], i.y = n && A[V - 1]
}
return n || (r.curve = v(a)), n ? [a, n] : a
}), null, v);
window.flatten = function e(a, n = !1, u = !1, i = !1, c = 3) {
if (a)
if (void 0 === i && (i = !1), void 0 === n && (n = !1), void 0 === u && (u = !1), void 0 === c && (c = !1), a && a.children && a.children.length) {
for (var o = 0, l = a.children.length; o < l; o++) e(a.children[o], n, u, i, c);
a.removeAttribute("transform")
} else if (a instanceof SVGCircleElement || a instanceof SVGRectElement || a instanceof SVGEllipseElement || a instanceof SVGLineElement || a instanceof SVGPolygonElement || a instanceof SVGPolylineElement || a instanceof SVGPathElement) {
if (path_elem = function(e, r) {
if (!e) return;
var a = document.createElementNS(e.ownerSVGElement.namespaceURI, "path");
let n = [...e.attributes],
u = ["d", "x", "y", "x1", "y1", "x2", "y2", "cx", "cy", "r", "rx", "ry", "points", "height", "width"];
for (let e = 0; e < n.length; e++) {
let t = n[e];
if (-1 === u.indexOf(t.nodeName)) {
var i = t.nodeName,
c = t.nodeValue;
a.setAttribute(i, c + "")
}
}
var o = "",
l = function(e) {
return !("number" != typeof e || e == 1 / 0 || e < 0)
},
s = 1.81,
h = e.tagName;
switch (h) {
case "ellipse":
case "circle":
var f = +e.getAttribute("rx"),
x = +e.getAttribute("ry"),
y = +e.getAttribute("cx"),
p = +e.getAttribute("cy");
"circle" == h && (f = x = +e.getAttribute("r")), o += t([
["M", y - f, p],
["C", y - f, p - x / s, y - f / s, p - x, y, p - x],
["C", y + f / s, p - x, y + f, p - x / s, y + f, p],
["C", y + f, p + x / s, y + f / s, p + x, y, p + x],
["C", y - f / s, p + x, y - f, p + x / s, y - f, p],
["Z"]
]);
break;
case "path":
o = e.getAttribute("d");
break;
case "line":
var g = e.getAttribute("x1"),
b = e.getAttribute("y1");
x2 = e.getAttribute("x2"), y2 = e.getAttribute("y2"), o = "M" + g + "," + b + "L" + x2 + "," + y2;
break;
case "polyline":
o = "M" + e.getAttribute("points");
break;
case "polygon":
o = "M" + e.getAttribute("points") + "Z";
break;
case "rect":
f = +e.getAttribute("rx"), x = +e.getAttribute("ry");
var v = e.getBBox(),
m = v.x,
M = v.y,
d = v.width,
A = v.height;
if (l(f) || l(x) ? l(f) && !l(x) ? x = f : l(x) && !l(f) ? f = x : (f > d / 2 && (f = d / 2), x > A / 2 && (x = A / 2)) : f = x = 0, f || x)
if (r) o += t([
["M", m + f, M],
["H", m + d - f],
["A", f, x, 0, 0, 1, m + d, M + x],
["V", M + A - x],
["A", f, x, 0, 0, 1, m + d - f, M + A],
["H", m + f],
["A", f, x, 0, 0, 1, m, M + A - x],
["V", M + x],
["A", f, x, 0, 0, 1, m + f, M]
]);
else {
x || (x = f), o += t([
["M", m, M + x],
["C", m, M + x / (s = 2.19), m + f / s, M, m + f, M],
["L", m + d - f, M],
["C", m + d - f / s, M, m + d, M + x / s, m + d, M + x],
["L", m + d, M + A - x],
["C", m + d, M + A - x / s, m + d - f / s, M + A, m + d - f, M + A],
["L", m + f, M + A],
["C", m + f / s, M + A, m, M + A - x / s, m, M + A - x],
["L", m, M + x],
["Z"]
])
}
else o += t([
["M", m, M],
["L", m + d, M],
["L", m + d, M + A],
["L", m, M + A],
["L", m, M],
["Z"]
])
}
o && a.setAttribute("d", o);
return e.parentNode.replaceChild(a, e), a
}(a, i), !path_elem || "" == path_elem.getAttribute(f)) return "M 0 0";
var s;
c || 0 === c ? c > 15 ? c = 15 : c < 0 && (c = 0) : c = !1;
var h = path_elem,
f = h.getAttribute("d").trim();
if (n) x = s = w(f);
else {
var x = s = M(f);
s = d(s)
}
var y, p, g = h.ownerSVGElement,
b = h.getTransformToElement(g),
v = (o = 0, s.length),
m = "",
A = "",
C = 0,
q = 0,
S = [],
V = g.createSVGPoint(),
k = {},
L = 0,
E = 0;
for (k.x = null, k.y = null; o < v; o++) {
if (m = s[o][0].toUpperCase(), A = x[o][0], S[o] = [], S[o][0] = s[o][0], "A" == m) C = s[o][6], q = s[o][7], V.x = s[o][6], V.y = s[o][7], S[o] = r(s[o][1], s[o][2], s[o][3], s[o][4], s[o][5], V, b), S[o][1] = S[o][1], S[o][2] = S[o][2], S[o][3] = S[o][3], S[o][6] = S[o][6], S[o][7] = S[o][7];
else if ("Z" != m)
for (y = 1; y < s[o].length; y += 2) "V" == m ? q = s[o][y] : "H" == m ? C = s[o][y] : (C = s[o][y], q = s[o][y + 1]), V.x = C, V.y = q, p = V.matrixTransform(b), "V" == m || "H" == m ? (S[o][0] = "L", S[o][y] = p.x, S[o][y + 1] = p.y) : (S[o][y] = p.x, S[o][y + 1] = p.y);
("Z" != m && null === k.x || "M" == m) && (k.x = C, k.y = q), "Z" == m && (C = k.x, q = k.y)
}
var T = 0,
G = 0;
for (k.x = "", o = 0; o < S.length; o++) {
if ("A" == (A = x[o][0]) || "M" == A || "L" == A || "C" == A || "S" == A || "Q" == A || "T" == A || "H" == A || "V" == A) {
var P = Z = S[o].length;
if ("A" == A) S[o][6] = _(S[o][6]), S[o][7] = _(S[o][7]);
else
for (P--; --P;) S[o][P] = _(S[o][P]);
L = S[o][Z - 2], E = S[o][Z - 1]
} else if ("a" == A) T = S[o][6], G = S[o][7], S[o][0] = A, S[o][6] = _(S[o][6] - L), S[o][7] = _(S[o][7] - E), L = T, E = G;
else if ("m" == A || "l" == A || "c" == A || "s" == A || "q" == A || "t" == A || "h" == A || "v" == A) {
var Z = S[o].length;
for (T = S[o][Z - 2], G = S[o][Z - 1], y = 1; y < Z; y += 2) S[o][0] = "h" == A || "v" == A ? "l" : A, S[o][y] = _(S[o][y] - L), S[o][y + 1] = _(S[o][y + 1] - E);
L = T, E = G
}("z" != A.toLowerCase() && "" == k.x || "m" == A.toLowerCase()) && (k.x = L, k.y = E), "z" == A.toLowerCase() && (L = k.x, E = k.y)
}
S[0][1] = +S[0][1].toFixed(c), S[0][2] = +S[0][2].toFixed(c), u && (S = d(S)), path_elem.setAttribute("d", t(S)), path_elem.removeAttribute("transform")
}

function _(e) {
return !1 !== c ? Math.round(e * Math.pow(10, c)) / Math.pow(10, c) : e
}
}
}();
<p><button type="button" onclick="flatten(svg)"> Convert transforms flatten.js</button></p>


<svg viewBox="0 0 100 100" overflow="visible">
<g transform="rotate(-33 50 50) translate(-10 -10) scale(1.5)">
<g transform="rotate(-33 50 50) translate(-10 -10) scale(1.5)">
<path class="" d="M25 25 h25 v25 h-25 z" fill="green" />
<rect x="0" y="0" width="33%" height="20" transform="rotate(27 20 50) translate(20 10)" fill="orange" />
<path data-att="random" transform="rotate(45 50 50)" class="transform" d="M25 25 h25 v25 h-25 z" fill="red" />
</g>
</g>
</svg>

转换(扁平化)转换可能不是一个好主意

至少当您的用户经常更改转换时。
使用像 fabric.js 这样的 Canvas 驱动(具有 svg 导出功能)库可能是更好的解决方案。

上述路径数据操作由于坐标/数字舍入而有损。如果仅完成一次(例如,在编辑之后或将转换后的图形导出为 svg 文件之前),则可以忽略不计。

转换(扁平化)转换在以下情况下会很有用

  • 您正在为 太多转换 的 svg 文件而苦苦挣扎(有时相互否定......有时完全疯狂)
  • 您需要针对外部应用程序或具有有限 svg 功能支持的生成器(例如 pdf 生成器或办公应用程序)优化您的 svg

关于javascript - 如何在 SVG 路径数据 (d) 字符串本身中执行旋转?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72943080/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com