css - 在 SVG 元素上方添加标签而不使 SVG 元素移动

标签 css svg blazor blazor-server-side

我有一个元素,我将一些数据可视化为包含矩形元素的 SVG 元素。 所以我想做的是在 SVG 的特定矩形元素上添加标签,为了做到这一点,我必须获取矩形元素的位置,以便将标签放置在这个确切的位置。

因此,为了首先实现这一点,我使用 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 不移动到下面的情况下实现这一点有什么建议吗?

提前致谢!

最佳答案

正如 @maciek 所指出的:您可以使用 position:relative 将 svg 和 label 包装在 div 中并申请position:absolute到您的 svg 和标签。

替代:svg <text>标签

如果您只需要简单的单行标签 – <text> 有一些优点: 您只需要获取 <rect> 的中心 x 和 y 坐标元素。
通过申请text-anchor:middledominant-baseline:middle文本将相对于矩形的中心垂直和水平居中。

您可以使用 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>元素的行为与 block 元素不同:

  • 没有自动换行
  • 分别不支持背景颜色和盒状外观

示例

// 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>

关于css - 在 SVG 元素上方添加标签而不使 SVG 元素移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74615924/

相关文章:

overflow - CSS 最大高度属性

Blazor 3.1 嵌套的鼠标悬停事件

javascript - SVG 路径上的 bool 运算

javascript - 如何处理 svg 中的 <path> 笔划宽度变为零

javascript - 如何将德国 map 放在 HTML 中的 svg 上? D3js

Blazor 可选路由参数

C# Blazor客户端从url中读取hash参数

具有单个容器和不同大小元素的 CSS flexbox

html - html/css id 和类的标准命名约定是什么?

javascript - 暂时绕过 CSS 转换