Hotgeart
Hotgeart

Reputation: 384

Format the legend of my donut chart

I try to make this chart with D3js:

donut chart

I've no idea how to make my "%" small like a <sup> tag (image). I tried to remove the suffix from the format()... it's give me a float.

How can I do that? Do I need to substring from my current text and add a new text? What's the better way?

Code :

makeDonut(1, 45);

  function makeDonut(id, percent) {
    var duration = 2000,
      transition = 200,
      width = 180,
      height = 180;

    var dataset = {
        lower: calcPercent(0),
        upper: calcPercent(percent)
      },
      radius = Math.min(width, height) / 3,
      pie = d3.pie().sort(null),
      format = d3.format(".0%");

    var arc = d3.arc()
      .innerRadius(radius * .8)
      .outerRadius(radius / .7);

    var svg = d3.select("#graph" + id).append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    var path = svg.selectAll("path")
      .data(pie(dataset.lower))
      .enter().append("path")
      .attr("class", function(d, i) {
        return "g" + id + "-color" + i
      })
      .attr("d", arc)
      .each(function(d) {
        this._current = d;
      });

    var text = svg.append("text")
      .attr("class", "g" + id + "-text")
      .attr("text-anchor", "middle")
      .attr("dy", ".3em");

    var progress = 0;

    var timeout = setTimeout(function() {
      clearTimeout(timeout);
      path = path.data(pie(dataset.upper));
      path.transition().duration(duration).attrTween("d", function(a) {
        var i = d3.interpolate(this._current, a);
        var i2 = d3.interpolate(progress, percent)
        this._current = i(0);
        return function(t) {
          text.text(format(i2(t) / 100));
          return arc(i(t));
        };
      });
    }, 200);
  };

function calcPercent(percent) {
  return [percent, 100 - percent];
};
.g1-color0 {
  fill: #5ca747;
}

.g1-color1 {
  fill: #dcdcdc;
}

.g1-text {
  font-family: 'Roboto Condensed', sans-serif;
  fill: #5ca747;
  font-size: 50px;
  font-weight: bold;
}

.graph1 span {
  font-family: 'Roboto Condensed', sans-serif;
  text-transform: uppercase;
  font-size: 26px;
  color: #5ca747;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="graph1 col-sm-4 text-center">
  <div id="graph1"></div>
  <span>3 projecten klaar</span>
</div>

I created a JSFiffle

Upvotes: 1

Views: 261

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

An easy (and lazy) solution is just creating another text selection for the % symbol:

var percentText = svg.append("text")
    .attr("class", "g" + id + "-percent")
    .attr("text-anchor", "middle")
    .attr("dx", "1.2em")
    .attr("dy", "-0.3em")
    .text("%");

Here is the demo:

makeDonut(1, 45);

  function makeDonut(id, percent) {
    var duration = 2000,
      transition = 200,
      width = 180,
      height = 180;

    var dataset = {
        lower: calcPercent(0),
        upper: calcPercent(percent)
      },
      radius = Math.min(width, height) / 3,
      pie = d3.pie().sort(null);

    var arc = d3.arc()
      .innerRadius(radius * .8)
      .outerRadius(radius / .7);

    var svg = d3.select("#graph" + id).append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    var path = svg.selectAll("path")
      .data(pie(dataset.lower))
      .enter().append("path")
      .attr("class", function(d, i) {
        return "g" + id + "-color" + i
      })
      .attr("d", arc)
      .each(function(d) {
        this._current = d;
      });

    var text = svg.append("text")
      .attr("class", "g" + id + "-text")
      .attr("text-anchor", "middle")
      .attr("dy", ".3em");
      
    var percentText = svg.append("text")
      .attr("class", "g" + id + "-percent")
      .attr("text-anchor", "middle")
      .attr("dx", "1.2em")
      .attr("dy", "-0.3em")
      .text("%");

    var progress = 0;

    var timeout = setTimeout(function() {
      clearTimeout(timeout);
      path = path.data(pie(dataset.upper));
      path.transition().duration(duration).attrTween("d", function(a) {
        var i = d3.interpolate(this._current, a);
        var i2 = d3.interpolate(progress, percent)
        this._current = i(0);
        return function(t) {
        if(~~(i2(t))>=10){percentText.attr("dx", "1.8em")}
          text.text(~~(i2(t)));
          return arc(i(t));
        };
      });
    }, 200);
  };

function calcPercent(percent) {
  return [percent, 100 - percent];
};
.g1-color0 {
  fill: #5ca747;
}

.g1-color1 {
  fill: #dcdcdc;
}

.g1-text {
  font-family: 'Roboto Condensed', sans-serif;
  fill: #5ca747;
  font-size: 50px;
  font-weight: bold;
}

.g1-percent {
  font-family: 'Roboto Condensed', sans-serif;
  fill: #5ca747;
  font-size: 20px;
  font-weight: bold;
}

.graph1 span {
  font-family: 'Roboto Condensed', sans-serif;
  text-transform: uppercase;
  font-size: 26px;
  color: #5ca747;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="graph1 col-sm-4 text-center">
  <div id="graph1"></div>
  <span>3 projecten klaar</span>
</div>

Upvotes: 1

Related Questions