webentwicklung-frage-antwort-db.com.de

Einbetten von Text in D3

Ich möchte, dass der Text in den folgenden D3-Baum eingefügt wird, so dass statt 

Foo is not a long Word

jede Zeile wird umbrochen 

Foo is
not a
long Word

Ich habe versucht, den Text zu einem "foreignObject" und nicht zu einem Textobjekt zu machen. Der Text wird zwar umbrochen, aber er bewegt sich nicht in der Baumanimation und wird in der oberen linken Ecke gruppiert.

Code befindet sich bei

http://jsfiddle.net/mikeyai/X43X5/1/

Javascript:

var width = 960,
    height = 500;

var tree = d3.layout.tree()
    .size([width - 20, height - 20]);

var root = {},
    nodes = tree(root);

root.parent = root;
root.px = root.x;
root.py = root.y;

var diagonal = d3.svg.diagonal();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(10,10)");

var node = svg.selectAll(".node"),
    link = svg.selectAll(".link");

var duration = 750,
    timer = setInterval(update, duration);

function update() {
  if (nodes.length >= 500) return clearInterval(timer);

  // Add a new node to a random parent.
  var n = {id: nodes.length},
      p = nodes[Math.random() * nodes.length | 0];
  if (p.children) p.children.Push(n); else p.children = [n];
  nodes.Push(n);

  // Recompute the layout and data join.
  node = node.data(tree.nodes(root), function(d) { return d.id; });
  link = link.data(tree.links(nodes), function(d) { return d.source.id + "-" + d.target.id; });

  // Add entering nodes in the parent’s old position.
  node.enter().append("text")
      .attr("class", "node")
      .attr("x", function(d) { return d.parent.px; })
      .attr("y", function(d) { return d.parent.py; })
        .text('Foo is not a long Word');

  // Add entering links in the parent’s old position.
  link.enter().insert("path", ".node")
      .attr("class", "link")
      .attr("d", function(d) {
        var o = {x: d.source.px, y: d.source.py};
        return diagonal({source: o, target: o});
      });

  // Transition nodes and links to their new positions.
  var t = svg.transition()
      .duration(duration);

  t.selectAll(".link")
      .attr("d", diagonal);

  t.selectAll(".node")
      .attr("x", function(d) { return d.px = d.x; })
      .attr("y", function(d) { return d.py = d.y; });
}
15
user235236

Sie können Mike Bostocks Beispiel "[Wrapping Long Labels"] ändern, um den <tspan>-Knoten <text>-Elemente hinzuzufügen. Es sind zwei wichtige Änderungen erforderlich, um umhüllten Text zu Ihren Knoten hinzuzufügen. Ich habe mich nicht damit beschäftigt, die Position des Textes während der Übergänge zu aktualisieren, aber es sollte nicht zu schwer sein, ihn hinzuzufügen.

Die erste besteht darin, eine Funktion wrap hinzuzufügen, die auf der Funktion im obigen Beispiel basiert. wrap sorgt dafür, dass <tspan>-Elemente hinzugefügt werden, damit Ihr Text in eine bestimmte Breite passt:

function wrap(text, width) {
    text.each(function () {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            Word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            x = text.attr("x"),
            y = text.attr("y"),
            dy = 0, //parseFloat(text.attr("dy")),
            tspan = text.text(null)
                        .append("tspan")
                        .attr("x", x)
                        .attr("y", y)
                        .attr("dy", dy + "em");
        while (Word = words.pop()) {
            line.Push(Word);
            tspan.text(line.join(" "));
            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(" "));
                line = [Word];
                tspan = text.append("tspan")
                            .attr("x", x)
                            .attr("y", y)
                            .attr("dy", ++lineNumber * lineHeight + dy + "em")
                            .text(Word);
            }
        }
    });
}

Die zweite Änderung besteht darin, dass Sie nicht den Text jedes Knotens festlegen müssen, sondern wrap für jeden Knoten aufrufen müssen:

// Add entering nodes in the parent’s old position.
node.enter().append("text")
    .attr("class", "node")
    .attr("x", function (d) { return d.parent.px; })
    .attr("y", function (d) { return d.parent.py; })
    .text("Foo is not a long Word")
    .call(wrap, 30); // wrap the text in <= 30 pixels
24
mdml

Wenn Sie eine weitere JS-Bibliothek hinzufügen möchten, können Sie auch D3plus , ein D3-Addon, verwenden. Es verfügt über eine integrierte Textumbruch Funktionalität. Es unterstützt sogar das Auffüllen und Ändern der Größe von Text, um den verfügbaren Platz zu füllen.

d3plus.textwrap()
  .container(d3.select("#rectWrap"))
  .draw();

Ich habe es benutzt. Es ist sicher besser als die Verpackung selbst zu berechnen.

Es gibt ein weiteres d3-Plugin für das Text-Wrapping, aber ich habe es noch nie verwendet.

2
user879121

Dies ist eine Möglichkeit zum Textumbruch mit d3 plus. Es ist wirklich einfach für mich und funktioniert ab sofort in allen Browsern

d3plus.textwrap()
    .container(d3.select("#intellectual"))
    .shape('square')
    .width(370)
    .height(55)
    .resize(true)
    .draw();      

0