在 d3.js 中将标签放置在节点的中心 [英] Placing labels at the center of nodes in d3.js

查看:22
本文介绍了在 d3.js 中将标签放置在节点的中心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 d3.js 开始,并尝试创建一行节点,每个节点都包含一个居中的数字标签.

I am starting with d3.js, and am trying to create a row of nodes each of which contains a centered number label.

我能够在视觉上产生所需的结果,但我这样做的方式几乎不是最佳的,因为它涉及对每个文本元素的 x-y 坐标进行硬编码.代码如下:

I am able to produce the desired result visually, but the way I did it is hardly optimal as it involves hard-coding the x-y coordinates for each text element. Below is the code:

var svg_w = 800;
var svg_h = 400;
var svg = d3.select("body")
    .append("svg")
    .attr("width", svg_w)
    .attr("weight", svg_h);

var dataset = [];
for (var i = 0; i < 6; i++) {
    var datum = 10 + Math.round(Math.random() * 20);
    dataset.push(datum);
}

var nodes = svg.append("g")
               .attr("class", "nodes")
               .selectAll("circle")
               .data(dataset)
               .enter()
               .append("circle")
               .attr("class", "node")
               .attr("cx", function(d, i) {
                   return (i * 70) + 50;
               })
               .attr("cy", svg_h / 2)
               .attr("r", 20);

var labels = svg.append("g")
                .attr("class", "labels")
                .selectAll("text")
                .data(dataset)
                .enter()
                .append("text")
                .attr("dx", function(d, i) {
                    return (i * 70) + 42
                })
                .attr("dy", svg_h / 2 + 5)
                .text(function(d) {
                    return d;
                });

node 类是我为 circle 元素单独定义的自定义 CSS 类,而 nodeslabels 没有明确定义,它们是从这个答案借来的.

The node class is custom CSS class I've defined separately for the circle elements, whereas classes nodes and labels are not explicitly defined and they are borrowed from this answer.

正如所见,每个文本标签的位置都是硬编码的,因此它出现在每个节点的中心.显然,这不是正确的解决方案.

As seen, the positioning of each text label is hard-coded so that it appears at the center of the each node. Obviously, this is not the right solution.

我的问题是,我应该如何正确地将每个文本标签与每个节点圆圈动态关联,以便标签的位置与圆圈的位置一起自动更改.非常欢迎使用代码示例进行概念性解释.

My question is that how should I correctly associate each text label with each node circle dynamically so that if the positioning of a label changes along with that of a circle automatically. Conceptual explanation is extremely welcome with code example.

推荐答案

文本锚 属性在 D3 创建的 svg 元素上按预期工作.但是,您需要将 textcircle 附加到公共 g 元素中,以确保 textcircle 彼此居中.

The text-anchor attribute works as expected on an svg element created by D3. However, you need to append the text and the circle into a common g element to ensure that the text and the circle are centered with one another.

为此,您可以将 nodes 变量更改为:

To do this, you can change your nodes variable to:

var nodes = svg.append("g")
           .attr("class", "nodes")
           .selectAll("circle")
           .data(dataset)
           .enter()
           // Add one g element for each data node here.
           .append("g")
           // Position the g element like the circle element used to be.
           .attr("transform", function(d, i) {
             // Set d.x and d.y here so that other elements can use it. d is 
             // expected to be an object here.
             d.x = i * 70 + 50,
             d.y = svg_h / 2;
             return "translate(" + d.x + "," + d.y + ")"; 
           });

请注意,dataset 现在是一个对象列表,因此可以使用 dydx 而不仅仅是字符串列表.

Note that the dataset is now a list of objects so that d.y and d.x can be used instead of just a list of strings.

然后,将您的 circletext 附加代码替换为以下内容:

Then, replace your circle and text append code with the following:

// Add a circle element to the previously added g element.
nodes.append("circle")
      .attr("class", "node")
      .attr("r", 20);

// Add a text element to the previously added g element.
nodes.append("text")
     .attr("text-anchor", "middle")
     .text(function(d) {
       return d.name;
      });

现在,不是更改 circle 的位置,而是更改 g 元素的位置,该元素同时移动 circle 和 <代码>文本.

Now, instead of changing the position of the circle you change the position of the g element which moves both the circle and the text.

这是一个 JSFiddle 在圆圈上显示居中文本.

Here is a JSFiddle showing centered text on circles.

如果您希望文本位于单独的 g 元素中,以便它始终显示在顶部,请使用 dxdy 在第一个 g 元素的创建中设置的值以transform 文本.

If you want to have your text be in a separate g element so that it always appears on top, then use the d.x and d.y values set in the first g element's creation to transform the text.

var text = svg.append("svg:g").selectAll("g")
         .data(force.nodes())
         .enter().append("svg:g");

text.append("svg:text")
    .attr("text-anchor", "middle")
    .text(function(d) { return d.name; });

text.attr("transform",  function(d) {
      return "translate(" + d.x + "," + d.y + ")"; 
    });

这篇关于在 d3.js 中将标签放置在节点的中心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆