Search code examples
javascriptd3.jspie-chart

Add <id> + <data> to an ARC of a D3-PIE-chart


I happened to play around with the D3js-Library to visualize some SQL-JSON_LD data and want to do the following:

  • attach individual id-TAG as well as data-set (Matrix with various elements) to each slice

My Code right now looks like this

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  path {
    fill: #ccc;
    stroke: #333;
    stroke-width: 1.5px;
    transition: fill 250ms linear;
    transition-delay: 150ms;
  }
  
  path:hover {
    fill: #999;
    stroke: #000;
    transition-delay: 0;
  }
</style>

<body>
  <script src="//d3js.org/d3.v3.min.js"></script>
  <script>
    var data = {
  {"year":"2017-07-01","value":"1"},
  {"year":"2017-07-02","value":"1"},
  {"year":"2017-07-03","value":"2"},
  {"year":"2017-07-04","value":"3"},
  {"year":"2017-07-05","value":"5"},
  {"year":"2017-07-06","value":"8"},
  {"year":"2017-07-07","value":"13"},
  {"year":"2017-07-08","value":"21"},
  {"year":"2017-07-09","value":"24"},
  {"year":"2017-07-10","value":"55"},
  {"year":"2017-07-11","value":"89"},};

    var width = 960,
      height = 500;
      arc_ids = d3.range(data.length); // for naming the arcs

    var outerRadius = height / 2 - 20,
      innerRadius = outerRadius / 3,
      cornerRadius = 10;

    var pie = d3.layout.pie()
      .padAngle(.02);

    var arc = d3.svg.arc()
      .padRadius(outerRadius)
      .innerRadius(innerRadius);

    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height)
      .attr("id","viz_pieChart") // adds an ID to the whole chart
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    svg.selectAll("path")
      .data(pie(data.map(function(d) { return parseInt(d.value); })))
      .attr("id", function(d, i) { console.log('CP1'); return "arc-" + arc_ids[i]; }) // This was intended to add an individual id to each arc, but it doesn't
      .attr("data", function(d) { return d.data; }) // attach data to arc according to value, as e.g.: {"year":"2017-07-01","value":"1"}
      .enter().append("path")
      .each(function(d) {
        d.outerRadius = outerRadius - 20;
      })
      .attr("d", arc)
      .on("mouseover", arcTween(outerRadius, 0))
      on("click", function(d){console.log(d.id);console.log(d.data.toString())}); //print id of the clicked arc as well as saved data
      .on("mouseout", arcTween(outerRadius - 20, 150));

    function arcTween(outerRadius, delay) {
      return function() {
        d3.select(this).transition().delay(delay).attrTween("d", function(d) {
          var i = d3.interpolate(d.outerRadius, outerRadius);
          return function(t) {
            d.outerRadius = i(t);
            return arc(d);
          };
        });
      };
    }
 //test whether an arc can be reached, e.g. the 2nd Element
 console.log(document.getElementById('slice-1')); // gives an error
  </script>

I also checked this1, this2 and this3 as they seemed promising, but it still does not work for me.

Afterwards I want to use the attached data of an arc to print it into another svg-graphic. But first adressing has to work.

And I'm sorry for the post with more than one specific question!

Thank you for your help!


Solution

  • you must append the path before give it an id or data

    <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
      path {
        fill: #ccc;
        stroke: #333;
        stroke-width: 1.5px;
        transition: fill 250ms linear;
        transition-delay: 150ms;
      }
      
      path:hover {
        fill: #999;
        stroke: #000;
        transition-delay: 0;
      }
    </style>
    
    <body>
      <script src="//d3js.org/d3.v3.min.js"></script>
      <script>
        var data = [
      {"year":"2017-07-01","value":"1"},
      {"year":"2017-07-02","value":"1"},
      {"year":"2017-07-03","value":"2"},
      {"year":"2017-07-04","value":"3"},
      {"year":"2017-07-05","value":"5"},
      {"year":"2017-07-06","value":"8"},
      {"year":"2017-07-07","value":"13"},
      {"year":"2017-07-08","value":"21"},
      {"year":"2017-07-09","value":"24"},
      {"year":"2017-07-10","value":"55"},
      {"year":"2017-07-11","value":"89"}];
    
        var width = 960,
          height = 500;
          arc_ids = d3.range(data.length); // for naming the arcs
    
        var outerRadius = height / 2 - 20,
          innerRadius = outerRadius / 3,
          cornerRadius = 10;
    
        var pie = d3.layout.pie()
          .padAngle(.02);
    
        var arc = d3.svg.arc()
          .padRadius(outerRadius)
          .innerRadius(innerRadius);
    
        var svg = d3.select("body").append("svg")
          .attr("width", width)
          .attr("height", height)
          .attr("id","viz_pieChart") // adds an ID to the whole chart
          .append("g")
          .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
        svg.selectAll("path")
          .data(pie(data.map(function(d) { 
          return parseInt(d.value); 
          })))
                .enter().append("path")
          .each(function(d) {
            d.outerRadius = outerRadius - 20;
          })
          .attr("id", function(d, i) {  return "arc-" + arc_ids[i]; }) 
          
          // This was intended to add an individual id to each arc, but it doesn't
          .attr("data", function(d) { return d.data; }) // attach data to arc according to value, as e.g.: {"year":"2017-07-01","value":"1"}
    
          .attr("d", arc)
          .on("mouseover", arcTween(outerRadius, 0))
          .on("click", function(d){
          console.log(this.id);
          console.log(d.data.toString())
          }) //print id of the clicked arc as well as saved data
          .on("mouseout", arcTween(outerRadius - 20, 150));
    
        function arcTween(outerRadius, delay) {
          return function() {
            d3.select(this).transition().delay(delay).attrTween("d", function(d) {
              var i = d3.interpolate(d.outerRadius, outerRadius);
              return function(t) {
                d.outerRadius = i(t);
                return arc(d);
              };
            });
          };
        }
     //test whether an arc can be reached, e.g. the 2nd Element
     console.log(document.getElementById('slice-1')); // gives an error
      </script>