我有一个项目,我将一些数据可视化为包含rect元素的SVG元素。所以我想要做的是在SVG的一个特定的rect元素上添加一个标签,为了做到这一点,我必须得到rect元素的位置,以便将标签放置在这个确切的位置。
因此,为了实现这一点,我首先使用getBoundingClientRect() javascrip方法获得SVG位置,然后使用相同的方法得到rect元素位置。
在此之后,我得到svg和rect元素的位置之间的差异,得到的值是标签将要放置的位置。
这是代码,以便获取每个元素的位置,然后计算标签的新位置。
parentId参数是svg元素的id,childId参数是rect元素的id。
function getElemementRelativePosition(parentId, childId) {
var parentPos = document.getElementById(parentId).getBoundingClientRect();
var childPos = document.getElementById(childId).getBoundingClientRect();
var relativePos = {};
relativePos.top = childPos.top - parentPos.top;
relativePos.right = childPos.right - parentPos.right;
relativePos.bottom = childPos.bottom - parentPos.bottom;
relativePos.left = childPos.left - parentPos.left;
return relativePos;
}
getElemementRelativePosition函数返回标签的正确值,但问题是标签的占位符在其初始位置仍然很粘稠,所以即使我改变了它的位置,标签的高度也会将svg元素向下推。
包含标签的div元素具有以下属性
<div style="position:relative;z-index:10;top:@ relativePos.top; left:@ relativePos.left;">
MyLabel
</div>
对于如何在不使用svg的情况下实现这一点,有任何建议吗?
提前感谢!
发布于 2022-11-29 17:17:44
正如@maciek所指出的:您可以使用position:relative
将svg和label包装在div中,并将position:absolute
应用于您的svg和label。
选择: svg <text>
标签
如果您只需要简单的单行标签- 有一些优点:您只需要得到<rect>
元素的中心x和y坐标。
通过应用text-anchor:middle
和dominant-baseline:middle
,文本将垂直和水平中心相对于rect的中心。
您可以使用getBBox()
方法获得中心坐标(类似于getBoundingClientRect()
,但专门用于svg元素)。
简单的标签助手看起来可能如下所示:
function setSvgLabelPos(rect, label){
let bb = rect.getBBox();
let [x, y, width, height] = [bb.x, bb.y, bb.width, bb.height];
label.setAttribute('x', (x+width/2) )
label.setAttribute('y', (y+height/2) )
}
同样整洁:字体大小将与父svg元素一起缩放。
弊端
<text>
元素不像块元素:
没有自动line-wrapping
的
示例
// 1. svg text approach
setSvgLabelPos(rect2, labelSvg);
function setSvgLabelPos(rect, label) {
let bb = rect.getBBox();
let [x, y, width, height] = [bb.x, bb.y, bb.width, bb.height];
label.setAttribute('x', (x + width / 2))
label.setAttribute('y', (y + height / 2))
}
// 2. HTML relative/absolute layout
let posLabel = getElemementRelativePosition('svg', 'rect', 'label')
label.setAttribute('style', `top: ${posLabel.top}px; left: ${posLabel.left}px`);
function getElemementRelativePosition(parentId, childId, labelId) {
var parentPos = document.getElementById(parentId).getBoundingClientRect();
var childPos = document.getElementById(childId).getBoundingClientRect();
var labelPos = document.getElementById(labelId).getBoundingClientRect();
var relativePos = {};
relativePos.top = childPos.top - parentPos.top;
relativePos.right = childPos.right - parentPos.right;
relativePos.bottom = childPos.bottom - parentPos.bottom;
relativePos.left = childPos.left - parentPos.left;
return relativePos;
}
svg {
width: 20em;
border: 1px solid #ccc;
background: #eee;
}
.svgWrap {
position: relative;
}
.svgWrap>* {
position: absolute;
}
.label {
padding: 0.3em;
display: inline-block;
background: rgba(0, 0, 0, 0.5);
color: #fff;
}
<div class="svgWrap">
<svg id="svg" viewBox="0 0 100 100">
<rect id="rect" x="25%" y="50%" width="20" height="20" fill="red" />
<rect id="rect2" x="50%" y="25%" width="20" height="20" fill="green" />
<text id="labelSvg" class="label" x="50%" y="50%" style="font-size:4.5px; font-family:sans-serif;fill:currentColor " text-anchor="middle" dominant-baseline="middle">Svg label</text>
</svg>
<div id="label" class="label" style="">MyLabel</div>
</div>
https://stackoverflow.com/questions/74615924
复制相似问题