yAnTar
yAnTar

Reputation: 4610

Vertical legend in pieChart in one column in nvd3

I need vertical legend in PieChart. Now library provide only 2 options: top/right. If use right - legend is in several columns. I need legend in one column.

I found one hack - correct transform value and put legend in one column.

  var positionX = 30;
  var positionY = 30;
  var verticalOffset = 25;

  d3.selectAll('.nv-legend .nv-series')[0].forEach(function(d) {
    positionY += verticalOffset;
    d3.select(d).attr('transform', 'translate(' + positionX + ',' + positionY + ')');
  });

Example

It works, but If I click to legend to update it - legend return to start position (several columns). enter image description here

JSFiddle example

Upvotes: 3

Views: 3690

Answers (3)

user1190045
user1190045

Reputation: 11

I know this is an old question, but I had the same one and ended up here. None of the answers worked for me, but I was able to modfiy Ranijth's answer and get it working (and looking nice).

else if (legendPosition === "vertical") {       
                var pad=50;
                var legendWidth=150; //might need to change this
                legend.height(availableHeight).key(pie.x());
                legend.width(legendWidth);                  

                wrap.select('.nv-legendWrap')
                    .datum(data)
                    .call(legend)
                    .attr('transform', 'translate('+ ((availableWidth / 2)+legendWidth+pad)+','+pad+')');
 }

Pie Chart with Vertical Legend

Upvotes: 0

Ranjith Siji
Ranjith Siji

Reputation: 1135

A Quick Hack.

Modify the nv.d3.js Line 11149 (May differ on other versions )

// Legend
            if (showLegend) {
                if (legendPosition === "top") {

Add another option vertical

} else if (legendPosition === "vertical") {

                    var legendWidth = nv.models.legend().width();
                    var positionY = 10;
                    var positionX = availableWidth - 200;
                    var verticalOffset = 20;

                    if ( margin.top != legend.height()) {
                        margin.top = legend.height();
                        availableHeight = nv.utils.availableHeight(height, container, margin);
                    }

                    legend.width(200);
                  //  legend.height(availableHeight).key(pie.x());
                    positionY += verticalOffset;

                    wrap.select('.nv-legendWrap')
                        .datum(data)
                        .call(legend)
                        .attr('transform', 'translate(' + positionX + ',' + positionY + ')');
                }

Also can play with variables. Works very nice with Legends. For a very long list of legends. More logic want to apply.

Upvotes: 0

Bettimms
Bettimms

Reputation: 671

A workaround for this is to update the legend for every click and double click of .nv-legend.

(function() {
  var h = 600;
  var r = h / 2;
  var arc = d3.svg.arc().outerRadius(r);

  var data = [{
    "label": "Test 1",
    "value": 74
  }, {
    "label": "Test 2",
    "value": 7
  }, {
    "label": "Test 3",
    "value": 7
  }, {
    "label": "Test 4",
    "value": 12
  }];


  var colors = [
    'rgb(178, 55, 56)',
    'rgb(213, 69, 70)',
    'rgb(230, 125, 126)',
    'rgb(239, 183, 182)'
  ]


  nv.addGraph(function() {
    var chart = nv.models.pieChart()
      .x(function(d) {
        return d.label
      })
      .y(function(d) {
        return d.value
      })
      .color(colors)
      .showLabels(true)
      .labelType("percent");

    d3.select("#chart svg")
      .datum(data)
      .transition().duration(1200)
      .call(chart);

    var svg = d3.select("#chart svg");

    function updateLegendPosition() {
      svg.selectAll(".nv-series")[0].forEach(function(d, i) {
        d3.select(d).attr("transform", "translate(0," + i * 15 + ")");
      })
    }
    svg.select('.nv-legend').on("click", function() {
      updateLegendPosition();
    });

    svg.select('.nv-legend').on("dblclick", function() {
      updateLegendPosition();
    });

    updateLegendPosition();

    return chart;
  });


}())
@import url(http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans+Mono);

#chart svg {
  height: 600px;
}

.nv-label text{
    font-family: Droid Sans;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.js"></script>


<div id="chart">
  <svg></svg>
</div>

Upvotes: 8

Related Questions