如何防止SVG文本流出其圆圈?

Vin*_*ent 2 javascript svg d3.js

这就是文本现在在圆圈内的显示方式:

在此处输入图片说明

这就是我想在圆圈内显示文本的方式:

在此处输入图片说明

我正在寻找一种方法来切断/隐藏/或?文本中不适合圆圈的部分,并在这些过长文本的末尾显示三个点。我找到了许多解释如何将多个单词包裹在一个圆圈中的答案,但我找不到一种方法以这种方式将一个太长的单词放入一个圆圈中。

这些是输入时添加到圆圈和文本的样式:

enterNode = (selection) => {
        selection.select('circle')
            .attr("r", 30)
            .style("fill", function (d) {
                return color(d.label)
            })
            .style("stroke", "#4D5061")

        selection.select('text')
            .style("fill", "#3D3B30")
            .style("font-weight", "600")
            .style("text-transform", "uppercase")
            .style("text-anchor", "middle")
            .style("alignment-baseline", "middle")
    }
Run Code Online (Sandbox Code Playgroud)

圆圈是以这种方式显示的 d3 力布局的一部分

<svg>
  <g class="node-group">
    <g class="node>
      <circle class="circle"></circle>
      <text class="text"></text>
    </g>
  </g>
  <g class="link-group">...</g>
</svg>
Run Code Online (Sandbox Code Playgroud)

如果您对如何解决这个问题有想法,我真的会很高兴!

Ger*_*ado 5

这是一个基于 D3 的 SVG 元素解决方案,因为您有一个带有 D3 力有向图的 SVG。

它涉及获取圆的宽度(您可以将其attr("r")用作 getter,但这里我使用的是getBBox())和文本的长度(这里我使用的是getComputedTextLength())并将这些值传递给自定义函数。

首先,让我们看看没有任何功能的圆圈和文字。这是我的演示中的文本:

最重要的是:对你自己来说是真实的,它必须随之而来,就像黑夜一样,你不能对任何人做假。

如您所见,它不仅比圆长,而且实际上比 SVG 还要大:

var svg = d3.select("svg");
var circle = svg.append("circle")
  .attr("cx", 200)
  .attr("cy", 110)
  .attr("r", 100)
  .style("fill", "powderblue")
  .style("stroke", "darkslategray");

var text = svg.append("text")
  .style("text-anchor", "middle")
  .style("dominant-baseline", "central")
  .attr("x", 200)
  .attr("y", 110)
  .text("This above all: to thine own self be true, And it must follow, as the night the day, Thou canst not then be false to any man.");
Run Code Online (Sandbox Code Playgroud)
svg {
  border: 1px solid gray;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="400" height="220"></svg>
Run Code Online (Sandbox Code Playgroud)

现在让我们调用我们的函数,这里命名为crop(). 必须在文本选择上调用它,使用圆形选择作为第二个参数,如下所示:

text.call(crop, circle);
Run Code Online (Sandbox Code Playgroud)

这是功能:

function crop(text, circle) {
    var circleRadius = circle.node().getBBox().width;
    while (text.node().getComputedTextLength() > circleRadius) {
        text.text(text.text().slice(0, -4) + "...");
    }
};
Run Code Online (Sandbox Code Playgroud)

如您所见,它基本上采用值,并在while循环中裁剪文本(使用"..."),直到它适合空间。我实际上在每个循环中再次打印文本,以获取节点的计算长度……但是,那些现代浏览器的速度非常快,以至于人们无法注意到。

这是演示:

text.call(crop, circle);
Run Code Online (Sandbox Code Playgroud)
function crop(text, circle) {
    var circleRadius = circle.node().getBBox().width;
    while (text.node().getComputedTextLength() > circleRadius) {
        text.text(text.text().slice(0, -4) + "...");
    }
};
Run Code Online (Sandbox Code Playgroud)
var svg = d3.select("svg");
var circle = svg.append("circle")
  .attr("cx", 200)
  .attr("cy", 110)
  .attr("r", 100)
  .style("fill", "powderblue")
  .style("stroke", "darkslategray");

var text = svg.append("text")
  .style("text-anchor", "middle")
  .style("dominant-baseline", "central")
  .attr("x", 200)
  .attr("y", 110)
  .text("This above all: to thine own self be true, And it must follow, as the night the day, Thou canst not then be false to any man.");

text.call(crop, circle);

function crop(text, circle) {
  var circleRadius = circle.node().getBBox().width;
  while (text.node().getComputedTextLength() > circleRadius) {
    text.text(text.text().slice(0, -4) + "...");
  }
}
Run Code Online (Sandbox Code Playgroud)