show percentage in d3 pie chart

时间:2016-04-04 17:16:33

标签: d3.js pie-chart percentage

currently my pie chart in d3 shows the sum of numbers,i want percentage instead .

for eg: currently i have a pie chart for how many people submitted application who visited our site. our current pie chart shows like this : people submitted 17,000 and people didn't submitted-10,000 but i need this in percentage also. how can i get that. please find the pie code below and let me know what changes do i need to make this work. I am new to JavaScript and D3.

ko.bindingHandlers.pieChart = {
    init: function (element, valueAccessor) {
      var _options = valueAccessor();
      var _data = _options.transformer(_options.data);
      $(element).css("marginLeft", "auto");
      $(element).css("marginRight", "auto");
      if (typeof _options.maxWidth != "undefined") {
        var _max = _options.maxWidth * 1;
        $(element).width(Math.min($(element).parent().width(), _max));
      }

      if ($(element).find("svg").length > 0 && _data.length == 0) {
        $(element).find("svg").empty();
      }

      if (_data.length > 0 && isNaN(_data[0].value)) {
        _data = [];
        $(element).find("svg").empty();
      }

      if ($(element).is(":visible")) {
        nv.addGraph(function () {
          var _chart = nv.models.growingPieChart()
              .x(function (d) {
                return d.label
              })
              .y(function (d) {
                return d.value
              })
              .height($(element).width())
              .showLabels(true).showLegend(false)
              .tooltipContent(function (key, y, e, graph) {
                return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' + y + '</p>'
              });

          var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");

          _d3.datum(_data)
              .transition().duration(150)
              .each("end", _options.onComplete != null ? _options.onComplete : void(0))
              .call(_chart);

          if (_options.fqs) {
            $.each(_options.fqs(), function (cnt, item) {
              if (item.id() == _options.data.widget_id && item.field() == _options.field()) {
                _chart.selectSlices($.map(item.filter(), function (it) {
                  return it.value();
                }));
              }
            });
          }

          $(element).data("chart", _chart);

          var _resizeTimeout = -1;
          nv.utils.windowResize(function () {
            window.clearTimeout(_resizeTimeout);
            _resizeTimeout = window.setTimeout(function () {
              _chart.update();
            }, 200);
          });

          $(element).on("forceUpdate", function () {
            _chart.update();
          });

          $(element).height($(element).width());
          var _parentSelector = typeof _options.parentSelector != "undefined" ? _options.parentSelector : ".card-widget";
          $(element).parents(_parentSelector).on("resize", function () {
            if (typeof _options.maxWidth != "undefined") {
              var _max = _options.maxWidth * 1;
              $(element).width(Math.min($(element).parent().width(), _max));
            }
            $(element).height($(element).width());
            _chart.update();
          });

          return _chart;
        }, function () {
          var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
          _d3.selectAll(".nv-slice").on("click",
              function (d, i) {
                if (typeof _options.onClick != "undefined") {
                  chartsUpdatingState();
                  _options.onClick(d);
                }
              });
        });
      }
    },
    update: function (element, valueAccessor) {
      var _options = valueAccessor();
      var _data = _options.transformer(_options.data);
      var _chart = $(element).data("chart");
      if (_chart) {
        var _d3 = d3.select($(element).find("svg")[0]);
        _d3.datum(_data)
              .transition().duration(150)
              .each("end", _options.onComplete != null ? _options.onComplete : void(0))
              .call(_chart);

        if (_options.fqs) {
            $.each(_options.fqs(), function (cnt, item) {
              if (item.id() == _options.data.widget_id && item.field() == _options.field()) {
                _chart.selectSlices($.map(item.filter(), function (it) {
                  return it.value();
                }));
              }
            });
          }
        chartsNormalState();
      }
      else if (_data.length > 0) {
        ko.bindingHandlers.pieChart.init(element, valueAccessor);
      }
    }
  };

2 个答案:

答案 0 :(得分:0)

A fiddle would be useful to test this against (hint hint), but I'm pretty sure you want to change this line:

.y(function (d) {
  return d.value
})

to this

.y(function (d) {
  return d.value/total
})

You may have to define total. Like I said, without a jsfiddle or at least some indication of the format of your data, it's hard to determine if this is actually what's wrong or how to fix it.

Note: a pie chart of relative percentages will look exactly the same as a pie chart of the original numbers. You might be able to change the label and only the label, as follows:

return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' + y + '</p>'

to this

return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' + (y/total) + '</p>'

Hopefully both of those should work. You will have to define total, if it isn't already defined elsewhere. If not:

var total = 0;
_data.forEach(function(d){total += d.value});

Good luck!

答案 1 :(得分:0)

It would be even more helpful to include information such as the library you are using and a fully reproducible example using a gist, codepen, jsfiddle, etc. I am guessing you are using hue and more specifically growingPieChart. If my guesses are correct, then you can modify your tooltipContent function similar to @Vyross answer that posted while I was typing this.

.tooltipContent(function (key, y, e, graph) {
  return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' +
    (+y) / d3.sum(
      d3.select(graph.container).select('g').datum(),
      function(d){return d.value}
    ) +
    '</p>'
});