Html d3 节点标签

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11102795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 01:08:32  来源:igfitidea点击:

d3 Node Labeling

htmlsvgd3.jslabel

提问by Josh Bradley

I've been using the sample code from this d3 projectto learn how to display d3 graphs and I can't seem to get text to show up in the middle of the circles (similar to this exampleand this example). I've looked at other examples and have tried adding

我一直在使用这个 d3 项目中的示例代码来学习如何显示 d3 图形,但我似乎无法让文本显示在圆圈的中间(类似于这个例子这个例子)。我查看了其他示例并尝试添加

node.append("title").text("Node Name To Display")

and

node.append("text")
    .attr("text-anchor", "middle")
    .attr("dy", ".3em").text("Node Name To Display")

right after node is defined but the only results I see is "Node Name To Display" is showing up when I hover over each node. It's not showing up as text inside the circle. Do I have to write my own svg text object and determine the coordinates of that it needs to be placed at based on the coordinates of radius of the circle? From the other two examples, it would seem like d3 already takes cares of this somehow. I just don't know the right attribute to call/set.

在定义节点之后,但我看到的唯一结果是当我将鼠标悬停在每个节点上时显示“要显示的节点名称”。它没有显示为圆圈内的文本。我是否必须编写自己的 svg 文本对象并根据圆的半径坐标确定需要放置的坐标?从其他两个例子来看,似乎 d3 已经以某种方式解决了这个问题。我只是不知道调用/设置的正确属性。

回答by mbostock

There are lots of examplesshowing how to add labels to graph and tree visualizations, but I'd probably start with this one as the simplest:

很多示例展示了如何向图形和树可视化添加标签,但我可能会从最简单的例子开始:

You haven't posted a link to your code, but I'm guessing that noderefers to a selection of SVG circle elements. You can't add text elements to circle elements because circle elements are not containers; adding a text element to a circle will be ignored.

您还没有发布指向您的代码的链接,但我猜这node指的是一组 SVG 圆元素。您不能向圆元素添加文本元素,因为圆元素不是容器;将文本元素添加到圆圈将被忽略。

Typically you use a G element to group a circle element (or an image element, as above) and a text element for each node. The resulting structure looks like this:

通常,您使用 G 元素为每个节点分组一个圆元素(或图像元素,如上所述)和一个文本元素。生成的结构如下所示:

<g class="node" transform="translate(130,492)">
  <circle r="4.5"/>
  <text dx="12" dy=".35em">Gavroche</text>
</g>

Use a data-jointo create the G elements for each node, and then use selection.appendto add a circle and a text element for each. Something like this:

使用数据连接为每个节点创建 G 元素,然后使用selection.append为每个节点添加一个圆和一个文本元素。像这样的东西:

var node = svg.selectAll(".node")
    .data(nodes)
  .enter().append("g")
    .attr("class", "node")
    .call(force.drag);

node.append("circle")
    .attr("r", 4.5);

node.append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name });

One downside of this approach is that you may want the labels to be drawn on top of the circles. Since SVG does not yet support z-index, elements are drawn in document order; so, the above approach causes a label to be drawn above its circle, but it may be drawn under other circles. You can fix this by using two data-joins and creating separate groups for circles and labels, like so:

这种方法的一个缺点是您可能希望将标签绘制在圆圈的顶部。由于 SVG 尚不支持 z-index,因此元素按文档顺序绘制;因此,上述方法会导致在其圆上方绘制标签,但可能会在其他圆下方绘制标签。您可以通过使用两个数据连接并为圆圈和标签创建单独的组来解决此问题,如下所示:

<g class="nodes">
  <circle transform="translate(130,492)" r="4.5"/>
  <circle transform="translate(110,249)" r="4.5"/>
  …
</g>
<g class="labels">
  <text transform="translate(130,492)" dx="12" dy=".35em">Gavroche</text>
  <text transform="translate(110,249)" dx="12" dy=".35em">Valjean</text>
  …
</g>

And the corresponding JavaScript:

以及相应的 JavaScript:

var circle = svg.append("g")
    .attr("class", "nodes")
  .selectAll("circle")
    .data(nodes)
  .enter().append("circle")
    .attr("r", 4.5)
    .call(force.drag);

var text = svg.append("g")
    .attr("class", "labels")
  .selectAll("text")
    .data(nodes)
  .enter().append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text(function(d) { return d.name });

This technique is used in the Mobile Patent Suitsexample (with an additional text element used to create a white shadow).

该技术用于Mobile Patent Suits示例(带有用于创建白色阴影的附加文本元素)。

回答by Aleks Kissinger

If you want to grow the nodes to fit large labels, you can use the getBBox property of an SVG text node after you've drawn it. Here's how I did it, for a list of nodes with fixed coordinates, and two possible shapes:

如果要扩大节点以适应大标签,可以在绘制 SVG 文本节点后使用它的 getBBox 属性。这是我如何做到的,对于具有固定坐标的节点列表和两种可能的形状:

nodes.forEach(function(v) {
  var nd;
  var cx = v.coord[0];
  var cy = v.coord[1];

  switch (v.shape) {
    case "circle":
      nd = svg.append("circle");
      break;
    case "rectangle":
      nd = svg.append("rect");
      break;
  }

  var w = 10;
  var h = 10;
  if (v.label != "") {
    var lText = svg.append("text");

    lText.attr("x", cx)
         .attr("y", cy + 5)
         .attr("class", "labelText")
         .text(v.label);

    var bbox = lText.node().getBBox();
    w = Math.max(w,bbox.width);
    h = Math.max(h,bbox.height);
  }

  var pad = 4;

  switch (v.shape) {
    case "circle":
      nd.attr("cx", cx)
        .attr("cy", cy)
        .attr("r", Math.sqrt(w*w + h*h)/2 + pad);
      break;
    case "rectangle":
      nd.attr("x", cx - w/2 - pad)
        .attr("y", cy - h/2 - pad)
        .attr("width", w + 2*pad)
        .attr("height", h + 2*pad);
      break;
  }

});

Note that the shape is added, the text is added, thenthe shape is positioned, in order to get the text to show on top.

请注意,添加形状,添加文本,然后定位形状,以使文本显示在顶部。

回答by blue-sky

I found this guide very useful in trying to accomplish something similar :

我发现本指南在尝试完成类似的事情时非常有用:

https://www.dashingd3js.com/svg-text-element

https://www.dashingd3js.com/svg-text-element

Based on above link this code will generate circle labels :

基于上面的链接,此代码将生成圆圈标签:

<!DOCTYPE html>
<html>
  <head>
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
      <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
   </head>
<body style="overflow: hidden;">
<div id="canvas"  style="overflow: hidden;"></div>

<script type="text/javascript">

    var graph = {
        "nodes": [
            {name: "1", "group": 1, x: 100, y: 90, r: 10 , connected : "2"},
            {name: "2", "group": 1, x: 200, y: 50, r: 15, connected : "1"},
            {name: "3", "group": 2, x: 200, y: 130, r: 25, connected : "1"}
        ]
    }

    $( document ).ready(function() {

        var width = 2000;
        var height = 2000;

        var svg = d3.select("#canvas").append("svg")
                .attr("width", width)
                .attr("height", height)
                .append("g");

        var lines = svg.attr("class", "line")
                .selectAll("line").data(graph.nodes)
                .enter().append("line")
                .style("stroke", "gray") // <<<<< Add a color
                .attr("x1", function (d, i) {
                    return d.x
                })
                .attr("y1", function (d) {
                    return d.y
                })
                .attr("x2", function (d) {
                    return findAttribute(d.connected).x
                })
                .attr("y2", function (d) {
                    return findAttribute(d.connected).y
                })

        var circles = svg.selectAll("circle")
                .data(graph.nodes)
                .enter().append("circle")
                .style("stroke", "gray")
                .style("fill", "white")
                .attr("r", function (d, i) {
                    return d.r
                })
                .attr("cx", function (d, i) {
                    return d.x
                })
                .attr("cy", function (d, i) {
                    return d.y
                });

        var text = svg.selectAll("text")
                                .data(graph.nodes)
                                .enter()
                               .append("text");

        var textLabels = text
          .attr("x", function(d) { return d.x; })
          .attr("y", function(d) { return d.y; })
          .text( function (d) { return d.name })
          .attr("font-family", "sans-serif")
          .attr("font-size", "10px")
          .attr("fill", "red");

    });

    function findAttribute(name) {
        for (var i = 0, len = graph.nodes.length; i < len; i++) {
            if (graph.nodes[i].name === name)
                return graph.nodes[i]; // Return as soon as the object is found
        }
        return null; // The object was not found
    }


</script>
</body>
</html>