我有一个带有一堆不同路径的 svg。一个看起来的例子如下:
<path d="M2943648.169104896,472020.4539518825L2943637.730875478,472048.6771215173" />
我正在尝试找到一种方法来获取该行的哪一部分已被单击。我可以添加一个返回 d
的 onclick 函数,但这只会给我上面列出的完整字符串,而我只需要相关部分。例如,如果用户单击该行的第一部分,它将返回正确的坐标 (2943648.169104896,472020.4539518825
),或者如果他们单击第二部分,它将显示该行中的其他坐标d 的值。其中一些路径有许多不同的线段。
我在这里找到了一个不推荐使用的方法的答案,我想知道最新的方法是什么。谢谢。
最佳答案
我从另一个 SO 答案获取了 Array segments 代码的路径:
Split a svg path d to array of objects将其包装在创建新 d 路径的代码中,逐步添加每个段
用点击替换
鼠标悬停
删除路径段的特定颜色
因为 N 条路径叠加了一些额外的抗锯齿
<svg-path-extractor colors="orange,green,blue,gold,hotpink,red">
<div id=label></div>
<svg viewBox="0 0 24 24">
<path d="M 0 0 C 15 2 3 18 7 21 A 1 1 0 0 0 14 6 L 0 10 C 0 10 20 30 20 20 q -2 -4 4.13 -1 Z"></path>
<g id=segments></g>
</svg>
</svg-path-extractor>
<script>
customElements.define("svg-path-extractor", class extends HTMLElement {
connectedCallback() {
let addPath = (d, stroke) => {}
setTimeout(() => {
let colors = this.getAttribute("colors").split `,`;
let segments = [...this.querySelectorAll("svg path")].map(p => {
return this.pathToArray(p);
}).flat().map(seg => Object.keys(seg).map(key => seg[key]).join ` `);
segments.map((seg, idx, arr) => {
let d = arr.slice(0, idx + 1).join(" ");
let p = document.createElementNS("http://www.w3.org/2000/svg", "path");
p.setAttribute("d", d);
p.setAttribute("fill", "none");
p.setAttribute("stroke", colors.shift());
p.onmouseover = (evt) => {
let label = `${idx}d=${d}`.replace(seg,`<b>${seg}</b>`);
this.querySelector("#label").innerHTML = label;
}
this.querySelector("svg #segments").prepend(p);
})
});
}
pathToArray(path) {
if (typeof path != "string") path = path.getAttribute("d");
const PATH_COMMANDS = {
M: ["x", "y"],
m: ["dx", "dy"],
H: ["x"],
h: ["dx"],
V: ["y"],
v: ["dy"],
L: ["x", "y"],
l: ["dx", "dy"],
Z: [],
C: ["x1", "y1", "x2", "y2", "x", "y"],
c: ["dx1", "dy1", "dx2", "dy2", "dx", "dy"],
S: ["x2", "y2", "x", "y"],
s: ["dx2", "dy2", "dx", "dy"],
Q: ["x1", "y1", "x", "y"],
q: ["dx1", "dy1", "dx", "dy"],
T: ["x", "y"],
t: ["dx", "dy"],
A: ["rx", "ry", "rotation", "large-arc", "sweep", "x", "y"],
a: ["rx", "ry", "rotation", "large-arc", "sweep", "dx", "dy"]
};
const items = path.replace(/[\n\r]/g, '').
replace(/-/g, ' -').
replace(/(\d*\.)(\d+)(?=\.)/g, '$1$2 ').
trim().
split(/\s*,|\s+/);
const segments = [];
let currentCommand = '';
let currentElement = {};
while (items.length > 0) {
let it = items.shift();
if (PATH_COMMANDS.hasOwnProperty(it))
currentCommand = it;
else
items.unshift(it);
currentElement = {
type: currentCommand
};
PATH_COMMANDS[currentCommand].forEach((prop) => {
it = items.shift(); // TODO sanity check
currentElement[prop] = it;
});
if (currentCommand === 'M') {
currentCommand = 'L';
} else if (currentCommand === 'm') {
currentCommand = 'l';
}
segments.push(currentElement);
}
return segments
}
});
</script>
<style>
body {
font: 12px Arial
}
b{
font-size:1.2em;
color:darkgreen;
}
svg {
width: 180px;
background: pink;
}
svg #segments path{
cursor:pointer;
}
</style>
关于javascript - 使用 Javascript 返回在 SVG 中单击的哪一段线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66661128/