0

i read lots of threads and the Mike's blog but i haven't found how to solve my problem. I'm using the donut chart of D3.js and everything works fine. I use that code and change the value for each diagram:

var w = 650;
var h = 400;
var r = 150;
var ir = 75;
var textOffset = 24;
var tweenDuration = 1050;

//OBJECTS TO BE POPULATED WITH DATA LATER
var lines, valueLabels, nameLabels;
var pieData = [];    
var oldPieData = [];
var filteredPieData = [];

//D3 helper function to populate pie slice parameters from array data
var donut = d3.layout.pie().value(function(d){
  return d.itemValue;
});

//D3 helper function to create colors from an ordinal scale
var color = d3.scale.category20c();

//D3 helper function to draw arcs, populates parameter "d" in path object
var arc = d3.svg.arc()
  .startAngle(function(d){ return d.startAngle; })
  .endAngle(function(d){ return d.endAngle; })
  .innerRadius(ir)
  .outerRadius(r);

///////////////////////////////////////////////////////////
// GENERATE FAKE DATA /////////////////////////////////////
///////////////////////////////////////////////////////////

var data;

var dataStructure = [
   {
      "data":[
         {
            "itemLabel":"Social Media",
            "itemValue":90
         },
         {
            "itemLabel":"Blogs",
            "itemValue":30
         },
         {
            "itemLabel":"Text Messaging",
            "itemValue":60
         },
         {
            "itemLabel":"Email",
            "itemValue":90
         },
      ],
      "label":"2007"
   },
   {
      "data":[
         {
            "itemLabel":"Social Media",
            "itemValue":80
         },
         {
            "itemLabel":"Blogs",
            "itemValue":20
         },
         {
            "itemLabel":"Text Messaging",
            "itemValue":70
         },
         {
            "itemLabel":"Email",
            "itemValue":90
         },
      ],
      "label":"2009"
   },   
   {
      "data":[
         {
            "itemLabel":"Social Media",
            "itemValue":70
         },
         {
            "itemLabel":"Blogs",
            "itemValue":20
         },
         {
            "itemLabel":"Text Messaging",
            "itemValue":70
         },
         {
            "itemLabel":"Email",
            "itemValue":90
         },
      ],
      "label":"2011"
   },
   {
      "data":[
         {
            "itemLabel":"Social Media",
            "itemValue":60
         },
         {
            "itemLabel":"Blogs",
            "itemValue":20
         },
         {
            "itemLabel":"Text Messaging",
            "itemValue":70
         },
         {
            "itemLabel":"Email",
            "itemValue":90
         },
      ],
      "label":"2013"
   },   
];

///////////////////////////////////////////////////////////
// CREATE VIS & GROUPS ////////////////////////////////////
///////////////////////////////////////////////////////////

var vis = d3.select("#pie-chart").append("svg:svg")
  .attr("width", w)
  .attr("height", h);

//GROUP FOR ARCS/PATHS
var arc_group = vis.append("svg:g")
  .attr("class", "arc")
  .attr("transform", "translate(" + (w/2) + "," + (h/2) + ")");

//GROUP FOR LABELS
var label_group = vis.append("svg:g")
  .attr("class", "label_group")
  .attr("transform", "translate(" + (w/2) + "," + (h/2) + ")");

//GROUP FOR CENTER TEXT  
var center_group = vis.append("svg:g")
  .attr("class", "center_group")
  .attr("transform", "translate(" + (w/2) + "," + (h/2) + ")");

//PLACEHOLDER GRAY CIRCLE
// var paths = arc_group.append("svg:circle")
//     .attr("fill", "#EFEFEF")
//     .attr("r", r);

///////////////////////////////////////////////////////////
// CENTER TEXT ////////////////////////////////////////////
///////////////////////////////////////////////////////////

//WHITE CIRCLE BEHIND LABELS
var whiteCircle = center_group.append("svg:circle")
  .attr("fill", "white")
  .attr("r", ir);

///////////////////////////////////////////////////////////
// STREAKER CONNECTION ////////////////////////////////////
///////////////////////////////////////////////////////////

// to run each time data is generated
function update(number) {

  data = dataStructure[number].data;

  oldPieData = filteredPieData;
  pieData = donut(data);

  var sliceProportion = 0; //size of this slice
  filteredPieData = pieData.filter(filterData);
  function filterData(element, index, array) {
    element.name = data[index].itemLabel;
    element.value = data[index].itemValue;
    sliceProportion += element.value;
    return (element.value > 0);
  }

    //DRAW ARC PATHS
    paths = arc_group.selectAll("path").data(filteredPieData);
    paths.enter().append("svg:path")
      .attr("stroke", "white")
      .attr("stroke-width", 0.5)
      .attr("fill", function(d, i) { return color(i); })
      .transition()
        .duration(tweenDuration)
        .attrTween("d", pieTween);
    paths
      .transition()
        .duration(tweenDuration)
        .attrTween("d", pieTween);
    paths.exit()
      .transition()
        .duration(tweenDuration)
        .attrTween("d", removePieTween)
      .remove();

    //DRAW TICK MARK LINES FOR LABELS
    lines = label_group.selectAll("line").data(filteredPieData);
    lines.enter().append("svg:line")
      .attr("x1", 0)
      .attr("x2", 0)
      .attr("y1", -r-3)
      .attr("y2", -r-15)
      .attr("stroke", "gray")
      .attr("transform", function(d) {
        return "rotate(" + (d.startAngle+d.endAngle)/2 * (180/Math.PI) + ")";
      });
    lines.transition()
      .duration(tweenDuration)
      .attr("transform", function(d) {
        return "rotate(" + (d.startAngle+d.endAngle)/2 * (180/Math.PI) + ")";
      });
    lines.exit().remove();

    //DRAW LABELS WITH PERCENTAGE VALUES
    valueLabels = label_group.selectAll("text.value").data(filteredPieData)
      .attr("dy", function(d){
        if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) {
          return 5;
        } else {
          return -7;
        }
      })
      .attr("text-anchor", function(d){
        if ( (d.startAngle+d.endAngle)/2 < Math.PI ){
          return "beginning";
        } else {
          return "end";
        }
      })
      .text(function(d){
        var percentage = (d.value/sliceProportion)*100;
        return percentage.toFixed(1) + "%";
      });

    valueLabels.enter().append("svg:text")
      .attr("class", "value")
      .attr("transform", function(d) {
        return "translate(" + Math.cos(((d.startAngle+d.endAngle - Math.PI)/2)) * (r+textOffset) + "," + Math.sin((d.startAngle+d.endAngle - Math.PI)/2) * (r+textOffset) + ")";
      })
      .attr("dy", function(d){
        if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) {
          return 5;
        } else {
          return -7;
        }
      })
      .attr("text-anchor", function(d){
        if ( (d.startAngle+d.endAngle)/2 < Math.PI ){
          return "beginning";
        } else {
          return "end";
        }
      }).text(function(d){
        var percentage = (d.value/sliceProportion)*100;
        return percentage.toFixed(1) + "%";
      });

    valueLabels.transition().duration(tweenDuration).attrTween("transform", textTween);

    valueLabels.exit().remove();


    //DRAW LABELS WITH ENTITY NAMES
    nameLabels = label_group.selectAll("text.units").data(filteredPieData)
      .attr("dy", function(d){
        if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) {
          return 17;
        } else {
          return 5;
        }
      })
      .attr("text-anchor", function(d){
        if ((d.startAngle+d.endAngle)/2 < Math.PI ) {
          return "beginning";
        } else {
          return "end";
        }
      }).text(function(d){
        return d.name;
      });

    nameLabels.enter().append("svg:text")
      .attr("class", "units")
      .attr("transform", function(d) {
        return "translate(" + Math.cos(((d.startAngle+d.endAngle - Math.PI)/2)) * (r+textOffset) + "," + Math.sin((d.startAngle+d.endAngle - Math.PI)/2) * (r+textOffset) + ")";
      })
      .attr("dy", function(d){
        if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) {
          return 17;
        } else {
          return 5;
        }
      })
      .attr("text-anchor", function(d){
        if ((d.startAngle+d.endAngle)/2 < Math.PI ) {
          return "beginning";
        } else {
          return "end";
        }
      }).text(function(d){
        return d.name;
      });

    nameLabels.transition().duration(tweenDuration).attrTween("transform", textTween);

    nameLabels.exit().remove();

}

///////////////////////////////////////////////////////////
// FUNCTIONS //////////////////////////////////////////////
///////////////////////////////////////////////////////////

// Interpolate the arcs in data space.
function pieTween(d, i) {
  var s0;
  var e0;
  if(oldPieData[i]){
    s0 = oldPieData[i].startAngle;
    e0 = oldPieData[i].endAngle;
  } else if (!(oldPieData[i]) && oldPieData[i-1]) {
    s0 = oldPieData[i-1].endAngle;
    e0 = oldPieData[i-1].endAngle;
  } else if(!(oldPieData[i-1]) && oldPieData.length > 0){
    s0 = oldPieData[oldPieData.length-1].endAngle;
    e0 = oldPieData[oldPieData.length-1].endAngle;
  } else {
    s0 = 0;
    e0 = 0;
  }
  var i = d3.interpolate({startAngle: s0, endAngle: e0}, {startAngle: d.startAngle, endAngle: d.endAngle});
  return function(t) {
    var b = i(t);
    return arc(b);
  };
}

function removePieTween(d, i) {
  s0 = 2 * Math.PI;
  e0 = 2 * Math.PI;
  var i = d3.interpolate({startAngle: d.startAngle, endAngle: d.endAngle}, {startAngle: s0, endAngle: e0});
  return function(t) {
    var b = i(t);
    return arc(b);
  };
}

function textTween(d, i) {
  var a;
  if(oldPieData[i]){
    a = (oldPieData[i].startAngle + oldPieData[i].endAngle - Math.PI)/2;
  } else if (!(oldPieData[i]) && oldPieData[i-1]) {
    a = (oldPieData[i-1].startAngle + oldPieData[i-1].endAngle - Math.PI)/2;
  } else if(!(oldPieData[i-1]) && oldPieData.length > 0) {
    a = (oldPieData[oldPieData.length-1].startAngle + oldPieData[oldPieData.length-1].endAngle - Math.PI)/2;
  } else {
    a = 0;
  }
  var b = (d.startAngle + d.endAngle - Math.PI)/2;

  var fn = d3.interpolateNumber(a, b);
  return function(t) {
    var val = fn(t);
    return "translate(" + Math.cos(val) * (r+textOffset) + "," + Math.sin(val) * (r+textOffset) + ")";
  };
}

$( "#slider" ).slider({
    value: 0,
    min: 0,
    max: 3,
    step: 1,
    slide: function( event, ui ) {
        update(ui.value);
        console.log(ui.value);
      }
})
.each(function() {

  //
  // Add labels to slider whose values 
  // are specified by min, max and whose
  // step is set to 1
  //

  // Get the options for this slider
  var opt = $(this).data().uiSlider.options;

  // Get the number of possible values
  var vals = opt.max - opt.min;

  // Space out values
  for (var i = 0; i <= vals; i++) {

    var el = $('<label>'+dataStructure[i].label+'</label>').css('left',(i/vals*100)+'%');

    $( "#slider" ).append(el);

  }

});

update(0);

Here is the Jsfiddle of the diagram i'm using:

jsfiddle.net/brusasu/AqP73/

I created two html page, each for the diagrams with the value i need to show. My question is how to edit the code in a way where i can use the two diagrams in the same html page.

Thanks in advance

Bebbolin
  • 101
  • 1
  • 16
  • 1
    You need to have different DOM elements and different Javascript variables for each. So, as a start, you could simply copy all the code and append something like `_1` to all variables and DOM elements. This wouldn't result in the prettiest code, but should work. – Lars Kotthoff Nov 05 '13 at 15:36
  • Thanks for the reply. I already did that, i add a "2" in each part needed for the diagram but it doesn't work properly when i merge the code. – Bebbolin Nov 05 '13 at 15:43
  • Could you show us the code of your merge attempt? And what do you mean by "work properly"? – Lars Kotthoff Nov 05 '13 at 15:47
  • Here's a demo of a simple example http://bl.ocks.org/d3noob/raw/5987480/ and here http://www.d3noob.org/2013/07/arranging-more-than-one-d3js-graph-on.html if you want to get fancy you could start using bootstrap to arrange things nicely (explained here http://www.d3noob.org/2013/07/arrange-more-than-one-d3js-graph-with.html) – d3noob Nov 05 '13 at 16:52
  • Thanks all for the reply, i edited the code in that way http://jsfiddle.net/AqP73/3/ and i think i'm doing a big mistake. – Bebbolin Nov 06 '13 at 00:28
  • Hi d3noob, thanks for the reply, i read your amazing blog but i'm not using any csv for the data so i'm not able to edit like you suggest in the guide. – Bebbolin Nov 06 '13 at 00:29

1 Answers1

0

Oki Doki. I'm no expert in these things, but looking at the css in your jsfiddle, it appears to be missing the styles that you might want for the divs "slidercontainer2", "pie-chart2 and "slider2". Make sure that you have these properly duplicated and that will at least get you closer.

d3noob
  • 2,133
  • 3
  • 29
  • 36
  • I fixed the CSS problem, but it doesn't solve my issue. Here how i edit the CSS part: http://jsfiddle.net/AqP73/4/ – Bebbolin Nov 06 '13 at 10:53
  • 1
    Hmm... The reason I thought that would be the direction to go is that if you edit the JavaScript for the second graph and tell it to display in the first id it will do so comfortably. Therefore I made the assumption that the second id was not being defined properly. Sorry, it looks like I was sending you down a dead end. If I was in your position I would replace the graphs with something really simple (just a circle for instance) and then try to replicate the problem you're seeing. I still have a feeling that something is missing in how the graphs are being assigned to the divs. – d3noob Nov 06 '13 at 17:28
  • I solved *temporaly* the problem, adding the two diagrams in different html pages. Thanks for your help. – Bebbolin Nov 07 '13 at 22:27