如何获取 SVG 图像中出现在屏幕上的元素的 Y 坐标?
How to get Y-coordinate of elements in SVG image as they appear on the screen?
我想从 SVG 图像中解析出文本值,并按照它们在屏幕上出现的垂直顺序对它们进行排序。
我设法从 SVG 中找到并解析出文本元素,但我无法计算这些文本相对于根视口的 y 坐标。
这是一种简单的方法吗?
您需要投入的工作量取决于 SVG 的复杂程度以及垂直位置的具体含义。除了应用于 <text>
元素的各种转换之外,<tspan>
子元素或单个字形可以使用 dx
、dy
和 rotate
属性移动。
以下纯 JS 解决方案按第一个字形开始的点排序,使用 getStartPositionOfChar()
, and getScreenCTM()
将该值转换为屏幕坐标。红色箭头说明评估的点。
如果在 <use>
个元素中引用文本,解决方案将失败。
var texts = Array.from(document.querySelectorAll('text'));
var list = document.querySelector('ol');
var ordered = texts.map(function (t) {
var pos = t.getStartPositionOfChar(0), // start of first glyph at baseline {x, y}
ctm = t.getScreenCTM(); // transformation matrix to screen {a, b, c, d, e, f}
return {
text: t.textContent,
y: ctm.b*pos.x + ctm.d*pos.y + ctm.f
};
}).sort(function (a, b) {
return a.y - b.y;
}).forEach(function (o) {
var li = document.createElement('li');
li.textContent = o.text + ': ' + o.y.toFixed(2);
list.append(li);
});
#arrow {
fill: none;
stroke: red;
}
text {
font-family: sans-serif;
font-size: 15px;
}
ol {
position:absolute;
top:20px;
left:300px;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="300" height="150" viewBox="0 50 200 100">
<defs>
<path id="arrow" d="M 0 0 -10 0 M -4 -4 0 0 -4 4" />
</defs>
<text x="10" y="100" dy="-2 10 -5">red</text>
<text x="150" y="60" transform="rotate(30)"><tspan y="10">green</tspan></text>
<g transform="matrix(0.6,-0.3,-0.2,-0.6,60,340)">
<text x="100" y="300">blue</text>
</g>
<use xlink:href="#arrow" x="10" y="98" />
<use xlink:href="#arrow" x="124.904" y="83.6603" />
<use xlink:href="#arrow" x="60" y="130" />
</svg>
<ol></ol>
我想从 SVG 图像中解析出文本值,并按照它们在屏幕上出现的垂直顺序对它们进行排序。 我设法从 SVG 中找到并解析出文本元素,但我无法计算这些文本相对于根视口的 y 坐标。
这是一种简单的方法吗?
您需要投入的工作量取决于 SVG 的复杂程度以及垂直位置的具体含义。除了应用于 <text>
元素的各种转换之外,<tspan>
子元素或单个字形可以使用 dx
、dy
和 rotate
属性移动。
以下纯 JS 解决方案按第一个字形开始的点排序,使用 getStartPositionOfChar()
, and getScreenCTM()
将该值转换为屏幕坐标。红色箭头说明评估的点。
如果在 <use>
个元素中引用文本,解决方案将失败。
var texts = Array.from(document.querySelectorAll('text'));
var list = document.querySelector('ol');
var ordered = texts.map(function (t) {
var pos = t.getStartPositionOfChar(0), // start of first glyph at baseline {x, y}
ctm = t.getScreenCTM(); // transformation matrix to screen {a, b, c, d, e, f}
return {
text: t.textContent,
y: ctm.b*pos.x + ctm.d*pos.y + ctm.f
};
}).sort(function (a, b) {
return a.y - b.y;
}).forEach(function (o) {
var li = document.createElement('li');
li.textContent = o.text + ': ' + o.y.toFixed(2);
list.append(li);
});
#arrow {
fill: none;
stroke: red;
}
text {
font-family: sans-serif;
font-size: 15px;
}
ol {
position:absolute;
top:20px;
left:300px;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="300" height="150" viewBox="0 50 200 100">
<defs>
<path id="arrow" d="M 0 0 -10 0 M -4 -4 0 0 -4 4" />
</defs>
<text x="10" y="100" dy="-2 10 -5">red</text>
<text x="150" y="60" transform="rotate(30)"><tspan y="10">green</tspan></text>
<g transform="matrix(0.6,-0.3,-0.2,-0.6,60,340)">
<text x="100" y="300">blue</text>
</g>
<use xlink:href="#arrow" x="10" y="98" />
<use xlink:href="#arrow" x="124.904" y="83.6603" />
<use xlink:href="#arrow" x="60" y="130" />
</svg>
<ol></ol>