您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
UMD version of path-data-parser
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/490146/1344867/path-data-parser-umd.js
(function (global, factory) { global = typeof globalThis !== 'undefined' ? globalThis : global || self; factory(global.pathDataParser = {}); })(this, (function (exports) { 'use strict'; const COMMAND = 0; const NUMBER = 1; const EOD = 2; const PARAMS = {A: 7, a: 7, C: 6, c: 6, H: 1, h: 1, L: 2, l: 2, M: 2, m: 2, Q: 4, q: 4, S: 4, s: 4, T: 2, t: 2, V: 1, v: 1, Z: 0, z: 0}; function tokenize(d) { const tokens = new Array(); while (d !== "") { if (d.match(/^([ \t\r\n,]+)/)) { d = d.substr(RegExp.$1.length); } else if (d.match(/^([aAcChHlLmMqQsStTvVzZ])/)) { tokens[tokens.length] = {type: COMMAND, text: RegExp.$1}; d = d.substr(RegExp.$1.length); } else if (d.match(/^(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)/)) { tokens[tokens.length] = {type: NUMBER, text: `${parseFloat(RegExp.$1)}`}; d = d.substr(RegExp.$1.length); } else { return []; } } tokens[tokens.length] = {type: EOD, text: ""}; return tokens; } function isType(token, type) { return token.type === type; } function parsePath(d) { const segments = []; const tokens = tokenize(d); let mode = "BOD"; let index = 0; let token = tokens[index]; while (!isType(token, EOD)) { let paramsCount = 0; const params = []; if (mode === "BOD") { if (token.text === "M" || token.text === "m") { index++; paramsCount = PARAMS[token.text]; mode = token.text; } else { return parsePath("M0,0" + d); } } else if (isType(token, NUMBER)) { paramsCount = PARAMS[mode]; } else { index++; paramsCount = PARAMS[token.text]; mode = token.text; } if (index + paramsCount < tokens.length) { for (let i = index; i < index + paramsCount; i++) { const numbeToken = tokens[i]; if (isType(numbeToken, NUMBER)) { params[params.length] = +numbeToken.text; } else { throw new Error("Param not a number: " + mode + "," + numbeToken.text); } } if (typeof PARAMS[mode] === "number") { const segment = {key: mode, data: params}; segments.push(segment); index += paramsCount; token = tokens[index]; if (mode === "M") mode = "L"; if (mode === "m") mode = "l"; } else { throw new Error("Bad segment: " + mode); } } else { throw new Error("Path data ended short"); } } return segments; } function serialize(segments) { const tokens = []; for (const {key, data} of segments) { tokens.push(key); switch (key) { case "C": case "c": tokens.push(data[0], `${data[1]},`, data[2], `${data[3]},`, data[4], data[5]); break; case "S": case "s": case "Q": case "q": tokens.push(data[0], `${data[1]},`, data[2], data[3]); break; default: tokens.push(...data); break; } } return tokens.join(" "); } function absolutize(segments) { let cx = 0, cy = 0; let subx = 0, suby = 0; const out = []; for (const {key, data} of segments) { switch (key) { case "M": out.push({key: "M", data: [...data]}); [cx, cy] = data; [subx, suby] = data; break; case "m": cx += data[0]; cy += data[1]; out.push({key: "M", data: [cx, cy]}); subx = cx; suby = cy; break; case "L": out.push({key: "L", data: [...data]}); [cx, cy] = data; break; case "l": cx += data[0]; cy += data[1]; out.push({key: "L", data: [cx, cy]}); break; case "C": out.push({key: "C", data: [...data]}); cx = data[4]; cy = data[5]; break; case "c": { const newdata = data.map((d, i) => i % 2 ? d + cy : d + cx); out.push({key: "C", data: newdata}); cx = newdata[4]; cy = newdata[5]; break; } case "Q": out.push({key: "Q", data: [...data]}); cx = data[2]; cy = data[3]; break; case "q": { const newdata = data.map((d, i) => i % 2 ? d + cy : d + cx); out.push({key: "Q", data: newdata}); cx = newdata[2]; cy = newdata[3]; break; } case "A": out.push({key: "A", data: [...data]}); cx = data[5]; cy = data[6]; break; case "a": cx += data[5]; cy += data[6]; out.push({key: "A", data: [data[0], data[1], data[2], data[3], data[4], cx, cy]}); break; case "H": out.push({key: "H", data: [...data]}); cx = data[0]; break; case "h": cx += data[0]; out.push({key: "H", data: [cx]}); break; case "V": out.push({key: "V", data: [...data]}); cy = data[0]; break; case "v": cy += data[0]; out.push({key: "V", data: [cy]}); break; case "S": out.push({key: "S", data: [...data]}); cx = data[2]; cy = data[3]; break; case "s": { const newdata = data.map((d, i) => i % 2 ? d + cy : d + cx); out.push({key: "S", data: newdata}); cx = newdata[2]; cy = newdata[3]; break; } case "T": out.push({key: "T", data: [...data]}); cx = data[0]; cy = data[1]; break; case "t": cx += data[0]; cy += data[1]; out.push({key: "T", data: [cx, cy]}); break; case "Z": case "z": out.push({key: "Z", data: []}); cx = subx; cy = suby; break; } } return out; } function normalize(segments) { const out = []; let lastType = ""; let cx = 0, cy = 0; let subx = 0, suby = 0; let lcx = 0, lcy = 0; for (const {key, data} of segments) { switch (key) { case "M": out.push({key: "M", data: [...data]}); [cx, cy] = data; [subx, suby] = data; break; case "C": out.push({key: "C", data: [...data]}); cx = data[4]; cy = data[5]; lcx = data[2]; lcy = data[3]; break; case "L": out.push({key: "L", data: [...data]}); [cx, cy] = data; break; case "H": cx = data[0]; out.push({key: "L", data: [cx, cy]}); break; case "V": cy = data[0]; out.push({key: "L", data: [cx, cy]}); break; case "S": { let cx1 = 0, cy1 = 0; if (lastType === "C" || lastType === "S") { cx1 = cx + (cx - lcx); cy1 = cy + (cy - lcy); } else { cx1 = cx; cy1 = cy; } out.push({key: "C", data: [cx1, cy1, ...data]}); lcx = data[0]; lcy = data[1]; cx = data[2]; cy = data[3]; break; } case "T": { const [x, y] = data; let x1 = 0, y1 = 0; if (lastType === "Q" || lastType === "T") { x1 = cx + (cx - lcx); y1 = cy + (cy - lcy); } else { x1 = cx; y1 = cy; } const cx1 = cx + 2 * (x1 - cx) / 3; const cy1 = cy + 2 * (y1 - cy) / 3; const cx2 = x + 2 * (x1 - x) / 3; const cy2 = y + 2 * (y1 - y) / 3; out.push({key: "C", data: [cx1, cy1, cx2, cy2, x, y]}); lcx = x1; lcy = y1; cx = x; cy = y; break; } case "Q": { const [x1, y1, x, y] = data; const cx1 = cx + 2 * (x1 - cx) / 3; const cy1 = cy + 2 * (y1 - cy) / 3; const cx2 = x + 2 * (x1 - x) / 3; const cy2 = y + 2 * (y1 - y) / 3; out.push({key: "C", data: [cx1, cy1, cx2, cy2, x, y]}); lcx = x1; lcy = y1; cx = x; cy = y; break; } case "A": { const r1 = Math.abs(data[0]); const r2 = Math.abs(data[1]); const angle = data[2]; const largeArcFlag = data[3]; const sweepFlag = data[4]; const x = data[5]; const y = data[6]; if (r1 === 0 || r2 === 0) { out.push({key: "C", data: [cx, cy, x, y, x, y]}); cx = x; cy = y; } else { if (cx !== x || cy !== y) { const curves = arcToCubicCurves(cx, cy, x, y, r1, r2, angle, largeArcFlag, sweepFlag); curves.forEach(function(curve) { out.push({key: "C", data: curve}); }); cx = x; cy = y; } } break; } case "Z": out.push({key: "Z", data: []}); cx = subx; cy = suby; break; } lastType = key; } return out; } function degToRad(degrees) { return Math.PI * degrees / 180; } function rotate(x, y, angleRad) { const X = x * Math.cos(angleRad) - y * Math.sin(angleRad); const Y = x * Math.sin(angleRad) + y * Math.cos(angleRad); return [X, Y]; } function arcToCubicCurves(x1, y1, x2, y2, r1, r2, angle, largeArcFlag, sweepFlag, recursive) { const angleRad = degToRad(angle); let params = []; let f1 = 0, f2 = 0, cx = 0, cy = 0; if (recursive) { [f1, f2, cx, cy] = recursive; } else { [x1, y1] = rotate(x1, y1, -angleRad); [x2, y2] = rotate(x2, y2, -angleRad); const x = (x1 - x2) / 2; const y = (y1 - y2) / 2; let h = x * x / (r1 * r1) + y * y / (r2 * r2); if (h > 1) { h = Math.sqrt(h); r1 = h * r1; r2 = h * r2; } const sign = largeArcFlag === sweepFlag ? -1 : 1; const r1Pow = r1 * r1; const r2Pow = r2 * r2; const left = r1Pow * r2Pow - r1Pow * y * y - r2Pow * x * x; const right = r1Pow * y * y + r2Pow * x * x; const k = sign * Math.sqrt(Math.abs(left / right)); cx = k * r1 * y / r2 + (x1 + x2) / 2; cy = k * -r2 * x / r1 + (y1 + y2) / 2; f1 = Math.asin(parseFloat(((y1 - cy) / r2).toFixed(9))); f2 = Math.asin(parseFloat(((y2 - cy) / r2).toFixed(9))); if (x1 < cx) { f1 = Math.PI - f1; } if (x2 < cx) { f2 = Math.PI - f2; } if (f1 < 0) { f1 = Math.PI * 2 + f1; } if (f2 < 0) { f2 = Math.PI * 2 + f2; } if (sweepFlag && f1 > f2) { f1 = f1 - Math.PI * 2; } if (!sweepFlag && f2 > f1) { f2 = f2 - Math.PI * 2; } } let df = f2 - f1; if (Math.abs(df) > Math.PI * 120 / 180) { const f2old = f2; const x2old = x2; const y2old = y2; if (sweepFlag && f2 > f1) { f2 = f1 + Math.PI * 120 / 180 * 1; } else { f2 = f1 + Math.PI * 120 / 180 * -1; } x2 = cx + r1 * Math.cos(f2); y2 = cy + r2 * Math.sin(f2); params = arcToCubicCurves(x2, y2, x2old, y2old, r1, r2, angle, 0, sweepFlag, [f2, f2old, cx, cy]); } df = f2 - f1; const c1 = Math.cos(f1); const s1 = Math.sin(f1); const c2 = Math.cos(f2); const s2 = Math.sin(f2); const t = Math.tan(df / 4); const hx = 4 / 3 * r1 * t; const hy = 4 / 3 * r2 * t; const m1 = [x1, y1]; const m2 = [x1 + hx * s1, y1 - hy * c1]; const m3 = [x2 + hx * s2, y2 - hy * c2]; const m4 = [x2, y2]; m2[0] = 2 * m1[0] - m2[0]; m2[1] = 2 * m1[1] - m2[1]; if (recursive) { return [m2, m3, m4].concat(params); } else { params = [m2, m3, m4].concat(params); const curves = []; for (let i = 0; i < params.length; i += 3) { const r12 = rotate(params[i][0], params[i][1], angleRad); const r22 = rotate(params[i + 1][0], params[i + 1][1], angleRad); const r3 = rotate(params[i + 2][0], params[i + 2][1], angleRad); curves.push([r12[0], r12[1], r22[0], r22[1], r3[0], r3[1]]); } return curves; } } exports.absolutize = absolutize; exports.normalize = normalize; exports.parsePath = parsePath; exports.serialize = serialize; }));
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址