Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3.js - How can I add a new line to the text in this Collapsible Tree?

Tags:

svg

d3.js

I have a Collapsible Tree built by D3. Here is the JSFIDDLE:http://jsfiddle.net/mEyQW/57/

As you can see, when the nodes fully expended, the text were all overlapped. I want to add the new line to replace the space (May have 1 or 2). For example: SDS 123 will become

SDS
123

I have tried several similar answers found in stack overflow, but still cannot solve my problem. Could you please help on this? Presented by a JSFIDDLE will be appreciated!!

  nodeEnter.append("text")
      .attr("x", function(d) { return d.children1 || d._children1 ? -10 : 10; })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) { return d.children1 || d._children1 ? "end" : "start"; })
      .text(function(d) { return d.NickName ; })
      .style("fill-opacity", 1e-6);

Thanks!!

like image 430
Evian Avatar asked Jan 05 '15 12:01

Evian


2 Answers

I had a similar problem so I had to do a little manual work. First, you need a function that will actually 'wrap' the text:

function wordwrap(text, max) {
  var regex = new RegExp(".{0,"+max+"}(?:\\s|$)","g");
  var lines = [];
  var line; 
  while ((line = regex.exec(text))!="") {lines.push(line);} 
  return lines
}   

Then, you need to appy this function to each text element. In your code I would write it like this:

nodeEnter.append("text")
  .attr("x", function(d) { return d.children1 || d._children1 ? -10 : 10; })
  .attr("dy", ".35em")
  .attr("text-anchor", function(d) { return d.children1 || d._children1 ? "end" : "start"; })
   .style("fill-opacity", 1e-6)
   .each(function (d) {
       if (d.NickName!=undefined) {
          var lines = wordwrap(d.NickName, 15)
          for (var i = 0; i < lines.length; i++) {
             d3.select(this).append("tspan")
                 .attr("dy",13)
                 .attr("x",function(d) { 
                      return d.children1 || d._children1 ? -10 : 10; })
                  .text(lines[i])
           }
        }
}); 

The end result is this:

enter image description here

Of course you should spend some time adjusting the x position of each text element.

EDIT A simpler way would be to have a wordwrap method as:

function wordwrap2(text) {
   var lines=text.split(" ")
   return lines
}

and apply it like the following:

nodeEnter.append("text")
  .attr("x", function(d) { return d.children1 || d._children1 ? -10 : 10; })
  .attr("dy", ".35em")
  .attr("text-anchor", function(d) { return d.children1 || d._children1 ? "end" : "start"; })
   .style("fill-opacity", 1e-6)
   .each(function (d) {
       if (d.NickName!=undefined) {
          var lines = wordwrap2(d.NickName)
          for (var i = 0; i < lines.length; i++) {
             d3.select(this).append("tspan")
                 .attr("dy",13)
                 .attr("x",function(d) { 
                      return d.children1 || d._children1 ? -10 : 10; })
                  .text(lines[i])
           }
        }
});    

Here is a fiddle for this last approach: http://jsfiddle.net/mEyQW/59/

Hope this helps.

like image 113
Nikos Avatar answered Nov 18 '22 05:11

Nikos


I had a hard time to split a line on comma and place the text pieces in a list format. The following adaptation worked.

 function splitoncomma(text) {
   var lines=text.split(",") //splits text on comma
   return lines
}

   label.append("div")
          .attr("class", "class_name")
          .each(function (d) {
            if (textValue(d)!==undefined) {
              var lines = splitoncomma(textValue(d))
              for (var i = 0; i < lines.length; i++) {
                d3.select(this)
                .append("text")
                .append("tspan")
                .style("float","left")// the float:left avoids default inline positioning
                .text(lines[i])
       }
    }

The style float left is required to avoid default inline placement.

like image 43
Ed Die Avatar answered Nov 18 '22 05:11

Ed Die