正如@Maciek所指出的:您可以将SVG和Label都包装在一个带有position:relative
的div中,然后将position:absolute
应用于您的SVG和Label.
Alternative: svg <text>
labels
If you need only simple single-line labels – <text>
has some advantages:
You just need to get the center x and y coordinates of the <rect>
element.
By applying text-anchor:middle
and dominant-baseline:middle
the text will be vertically and horizontally centered relative to the rect's center.
You get the center coordinates using getBBox()
method (similar to getBoundingClientRect()
- but specifically for svg elements).
A simple label helper might look like this:
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元素的font-size will scale.
缺点
<text>
个元素的行为不像块元素:
示例
// 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>