User12_24_4004
User12_24_4004

Reputation: 31

How to wrap the text inside the SVG polygon without cutting the text

I have used SVG polygon in the sunburst which I got from GitHub. The text that is rendered on the breadcrumb is not fitting the polygon. I have changed the width of the polygon but it isn't working. How do I wrap the text inside that svg:polygon?

This is the code:

var entering = g.enter().append("svg:g");

entering.append("svg:polygon")
    .attr("width",100)//I have changed the width but it is not working
    .attr("height",100)
    .attr("points", breadcrumbPoints)
    .style("fill", function(d) {
        return color((d.children ? d : d.parent).name);
    })
//  .style("fill", function(d) { return colors[d.name]; });

entering.append("svg:text")
    .attr("x", (b.w + b.t)/2)
    .attr("y", b.h / 2)
    .attr("dy", "0.35em")
    .attr("text-anchor", "middle")
    .text(function(d) {
        return d.name;
    });

The sunburst looks like this. The text is not fitting into the polygon breadcrumb and is not displayed correctly. Some part of the text has been cut.

Upvotes: 1

Views: 1904

Answers (3)

user9807750
user9807750

Reputation:

To have the breadcrumbs update while moving mouse from left to right within a level(siblings) change var breadcrumbs to this:

var breadcrumbs = d3.select('#sequence').selectAll('.breadcrumb-custom')
    .data(sequenceArray, function(d) { return d.name + d.depth; }); 

Upvotes: 1

User12_24_4004
User12_24_4004

Reputation: 31

Thanks everyone for your response. For increasing the size and for getting equal width of the breadcrumbs , I have changed the polygon points and my code now looks like this.

function breadcrumbPoints(d, i) {
    	  var points = [];
    	  points.push("0,0");
    	  points.push(b.w*2 + ",0");
    	  points.push(b.w*2 + b.t + "," + (b.h / 2));
    	  points.push(b.w*2 + "," + b.h);
    	  points.push("0," + b.h);
    	  if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
    	    points.push(b.t + "," + (b.h / 2));
    	  }
    	  return points.join(" ");
    	}

    	// Update the breadcrumb trail to show the current sequence and percentage.
    	function updateBreadcrumbs(nodeArray, percentageString) {

    	  // Data join; key function combines name and depth (= position in sequence).
    	  var g = d3.select("#trail")
    	      .selectAll("g")
    	      .data(nodeArray, function(d) { return d.name + d.depth; });

    	  // Add breadcrumb and label for entering nodes.
    	  var entering = g.enter().append("svg:g");

    	  entering.append("svg:polygon")
    	      .attr("points", breadcrumbPoints)
    	      .style("fill", function(d) { return color((d.children ? d : d.parent).name); })
    	    //  .style("fill", function(d) { return colors[d.name]; });

    	  entering.append("svg:text")
    	      .attr("x", (b.w + b.t/2))
    	      .attr("y", b.h /2)
    	      .attr("dy", "0.36em")
    	      .attr("text-anchor", "middle")
    	      .text(function(d) { return d.name; })
    	      .style("fill", "white");

    	  // Set position for entering and updating nodes.
    	  g.attr("transform", function(d, i) {
    	    return "translate(" + i * (b.w + b.s)*2+ ", 0)";
    	  });

    	  // Remove exiting nodes.
    	  g.exit().remove();

    	  // Now move and update the percentage at the end.
    	  d3.select("#trail").select("#endlabel")
    	      .attr("x", (nodeArray.length + 0.5) * (b.w*2 + b.s))
    	      .attr("y", b.h / 2)
    	      .attr("dy", "0.36em")
    	      .attr("text-anchor", "middle")
    	      .text(percentageString)
    	  .style("fill", "green")

    	  // Make the breadcrumb trail visible, if it's hidden.
    	  d3.select("#trail")
    	      .style("visibility", "");

    	}

Upvotes: 0

torresomar
torresomar

Reputation: 2229

The approach I would take to solve this issue is to use plain html and css. Let css take care of arranging the elements by using a small set of rules.

Instead of a svg lets create a container for the breadcrumbs

<div id="main">    
    <div id="sequence-container">
        <div id="sequence" class="breadcrumbs-container"></div>
    </div>
    <!-- rest of html -->
</div>

Lets update a little your mouseover function:

function mouseover(d) {
    // ...
    var sequenceArray = getAncestors(d);
    // updateBreadcrumbs(sequenceArray, percentageString); remove this!
    var breadcrumbs = d3.select('#sequence').selectAll('.breadcrumb-custom')
        .data(sequenceArray); // join data
    // usual update pattern 
    breadcrumbs.exit().remove();
    breadcrumbs.attr('class', 'breadcrumb-custom')
    breadcrumbs.enter()
        .append('li')
        .attr('class', 'breadcrumb-custom')
        .append('a')
        .style('background', function (d) {
            return color((d.children ? d : d.parent).name);
        })
        .style('border-left-color', function (d) {
            return color((d.children ? d : d.parent).name);
        })
        .html(function (d) {
            return d.name
        });
    // ...
}

And we will also need to update the mouseleave function:

function mouseleave(d) {
    // ...
    // Remove breadcrumbs
    var breadcrumbs = d3.select('#sequence').selectAll('.breadcrumb-custom')
        .data([]);
    breadcrumbs.exit().remove();
    // ...
}

You had a function in charge of breadcrumb initialization, we will also need to remove the call to the function:

function createVisualization(json) {
    // initializeBreadcrumbTrail(); remove!
}

And now lets declare the css rules (got them from here https://css-tricks.com/triangle-breadcrumbs/) in order to get the visual aspect we want to achieve:

#sequence-container {
  width: auto;
  height: 80px;
}
.breadcrumbs-container {
   list-style: none;
   overflow: hidden;
   font: 18px Helvetica, Arial, Sans-Serif;
}
.breadcrumbs-container li {
   float: left;
}
.breadcrumbs-container li a {
   color: white;
   text-decoration: none;
   font-size: 10px;
   padding: 15px 0 10px 55px;
   position: relative;
   display: block;
   float: left;
}
.breadcrumbs-container li a:after {
   content: " ";
   display: block;
   width: 0;
   height: 0;
   border-top: 50px solid transparent;
   border-bottom: 50px solid transparent;
   border-left: 30px solid;
   border-left-color: inherit;
   position: absolute;
   top: 50%;
   margin-top: -50px;
   left: 100%;
   z-index: 2;
}
.breadcrumbs-container li a:before {
   content: " ";
   display: block;
   width: 0;
   height: 0;
   border-top: 50px solid transparent;
   border-bottom: 50px solid transparent;
   border-left: 30px solid white;
   position: absolute;
   top: 50%;
   margin-top: -50px;
   margin-left: 1px;
   left: 100%;
   z-index: 1;
}
.breadcrumbs-container li:first-child a {
   padding-left: 10px;
}

The end result looks like this: enter image description here

Working fiddle: http://jsfiddle.net/zv3zvur6/1/

Upvotes: 0

Related Questions