56

私は d3.js から始めて、中央に番号ラベルを含むノードの行を作成しようとしています。

目的の結果を視覚的に生成することはできますが、各テキスト要素の xy 座標をハードコーディングする必要があるため、最適な方法とは言えません。以下はコードです:

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;
                });

クラスは要素用に個別に定義したカスタム CSS クラスですが、クラスとnodeは明示的に定義されておらず、この回答から借用されています。circlenodeslabels

ご覧のとおり、各テキスト ラベルの配置は、各ノードの中央に表示されるようにハードコードされています。明らかに、これは正しい解決策ではありません。

私の質問は、ラベルの位置が円の位置とともに自動的に変化するように、各テキスト ラベルを各ノード サークルに動的に正しく関連付けるにはどうすればよいかということです。コード例を使用した概念的な説明は大歓迎です。

4

3 に答える 3

69

text-anchor属性は、D3 によって作成された svg 要素で期待どおりに機能します。ただし、とが互いに中央に配置されるように、textとをcircle共通のg要素に追加する必要があります。textcircle

これを行うには、nodes変数を次のように変更できます。

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はオブジェクトのリストになっているため、単なる文字列のリストの代わりにd.yandを使用できることに注意してください。d.x

次に、コードを次のように置き換えてcircle追加します。text

// 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の位置を変更します。gcircletext

これは、円の中央にテキストを表示するJSFiddleです。

テキストがg常に一番上に表示されるように別の要素に配置する場合は、最初の要素の作成でテキストに設定されたd.xd.yの値を使用します。gtransform

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 + ")"; 
    });
于 2012-08-08T13:40:58.743 に答える
38

最良の答えは、質問者自身からのものでした。

さらなる観察: 各テキスト要素に対して .attr("text-anchor", "middle") のみを使用すると、ラベルは水平方向の中央にありますが、垂直方向にはわずかにずれています。attr("y", ".3em") (d3.js Web サイトの例から借用) を追加してこれを修正しました。これは、任意のサイズのノード サークルでもうまく機能するようです。ただし、この追加の属性が正確に何をするのかは、私の理解を逃れています。確かに、各テキスト要素の y 座標に対して何らかの処理を行いますが、特に .3em を指定するのはなぜでしょうか? 私にはほとんど魔法のように思えます...

.attr("text-anchor", "middle")各テキスト要素に追加するだけです。

例:

node.append("text")
    .attr("x", 0)
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .text(function(d) { return d.name; });
于 2014-06-30T02:00:26.093 に答える
4

このページでは、テキスト要素に関して、svg フードの下で何が起こっているかを説明します。基礎となる機構とデータ構造を理解することで、コードを機能させるためにどのように変更する必要があるかをよりよく理解することができました。

于 2013-07-06T01:48:36.003 に答える