简体   繁体   English

如何使用更新的数据集更新d3.js饼图

[英]How to update d3.js pie chart with updated dataset

I've mixed and matched a lot of code from other sources. 我已经混合并匹配了许多其他来源的代码。

Currently, the pie chart displays fine, but when I select a different server in the drop-down menu, it fails to update the picture. 目前,饼状图显示正常,但是当我在下拉菜单中选择其他服务器时,它无法更新图片。 The console logs show that dataset is indeed being changed. 控制台日志显示确实已更改数据集。 I checked online and it seems like my elements are not being removed correctly? 我在线检查了一下,看来我的元素没有被正确删除? However, whenever I try to use path.exit().remove() it fails to display anything. 但是,每当我尝试使用path.exit()。remove()时,它都无法显示任何内容。

Here is my code and jsfiddle: http://jsfiddle.net/36q95k1c/2/ 这是我的代码和jsfiddle: http : //jsfiddle.net/36q95k1c/2/

var ds1 = [1,1,1,1,1,1,1,3,0,0];
var ds2 = [0,0,0,1,1,1,1,1,1,1];
var ds3 = [0,0,1,1,0,0,0,0,0,0];
var ds4 = [0,0,2,0,5,3,0,0,0,0];
var ds5 = [0,0,0,0,0,0,0,0,0,0];
var ds6 = [0,0,0,0,0,0,0,0,0,0];
var ds7 = [0,0,0,0,0,0,0,0,0,0];
var ds8 = [0,0,0,0,0,0,0,0,0,0];
var ds9 = [0,0,0,0,0,0,0,0,0,0];
var ds10 = [0,0,0,0,0,0,0,0,0,0];
var ds11 = [0,0,0,0,0,0,0,0,0,0];
var ds12 = [0,0,0,0,0,0,0,0,0,0];
var ds13 = [0,0,0,0,0,0,0,0,0,0];
var ds14 = [0,0,0,0,0,0,0,0,0,0];



var dataset = {inner: [4,1,31,28,13,65,6,6,4,3],
    middle: ds1,
    outer: [1175,1802,8126,11926,37264,4267,2961,2909,850,12432]};

var victim_total = 4+1+31+28+13+65+6+6+4+3;
var killer_total = 22+4+37+72+2+20+2+11+3+3;
var general_total = 1175+1802+8126+11926+37264+4267+2961+2909+850+12432;
var legendRectSize = 25;
var legendSpacing = 6;



//Width and height
var w = 750;
var h = 750;
var r = 100;
var donutWidth = 225


var outerRadius = w / 2;
var innerRadius = donutWidth;
var arc = d3.svg.arc()
    .innerRadius(innerRadius)
    .outerRadius(outerRadius);

var pie = d3.layout.pie()
    .sort(null);

// Easy colors accessible via a 10-step ordinal scale
var color = d3.scale.category20();

// Create SVG element
var svg = d3.select("body")
    .append("svg")
    .attr("width", 2*w)
    .attr("height", h)
    .append('g')
    .attr('transform', 'translate(' + (w / 2) + 
    ',' + (h / 2) + ')');

// Define the div for the tooltip
var div = d3.select("body").append("div")   
    .attr("class", "tooltip")               
    .style("opacity", 0);


function updateLegend(newData) {
    //https://dl.dropboxusercontent.com/s/hfho50s0xd2dcpn/craftinggeneralstats1.csv?dl=1"
    //https://dl.dropboxusercontent.com/s/i152v8ccetr5gj0/craftinggeneralstats.csv?dl=1
    //Import CSV file
d3.csv("https://dl.dropboxusercontent.com/s/i152v8ccetr5gj0/craftinggeneralstats.csv?dl=1", function(data) {
  data.forEach(function(d) {
    d.outer = +d.count;
    d.middle = +d.countkiller;
    d.inner = +d.countvictim;
    d.label = d.label;
  });
 // function updateLegend(newData) {
  /*var step;
  for (step = 0; step < 10; step++) {
  // Runs 5 times, with values of step 0 through 4.
  data[step].countkiller = 1;
}*/
//data[i].countkiller = 0;
console.log(dataset.middle);
// Set up groups
var arcs = svg.selectAll("g.arc")
    .data(d3.values(dataset));
    arcs.enter()
    .append("g")    
    .attr("class", "arc")
    .attr("transform", "translate(" +0+ "," +0+ ")");



var path = arcs.selectAll("path")
    .data(function(d) { return pie(d); });
  path.enter().append("path")
  .on("mouseover", function(d, i, j) { 
 // console.log(d);
  //console.log(dataset.middle[3]);
     div.transition()       
                .duration(200)      
                .style("opacity", .9)
                .style("left", (d3.event.pageX) + "px")     
                .style("top", (d3.event.pageY - 28) + "px");
            if (j ==0)
                div.html("Victim" + "<br/>" + Math.round(1000 * d.value / victim_total) / 10 +"%")
            if (j ==1)
                div.html("Killer" + "<br/>" + Math.round(1000 * d.value / killer_total) / 10 +"%")
            if (j ==2)
            {
                div.html("Overall" + "<br/>" + Math.round(1000 * d.value / general_total) / 10 +"%")
                }

            })                  
        .on("mouseout", function(d) {       
            div.transition()        
                .duration(500)      
                .style("opacity", 0);   
        })
    .attr("fill", function(d, i) { return color(i); })
    .attr("d", function(d, i, j) { return arc.innerRadius(10+r*j).outerRadius(r*(j+1))(d); });


   // .attr("text-anchor", "middle")
   /* .text(function (d, i) {
    return data[i].label;
});*/


// Setup legend
 var legend = svg.selectAll('.legend')                     
          .data(color.domain())                                   
          .enter()                                                
          .append('g')                                            
          .attr('class', 'legend')                                
          .attr('transform', function(d, i) {                     
            var height = legendRectSize + legendSpacing;          
            var offset =  height * color.domain().length / 2;     
            var horz = -2 * legendRectSize;                       
            var vert = i * height - offset;                       
            return 'translate(' + (horz +(w/2)) +  ',' + vert + ')';        
          });                                                     

        legend.append('rect')                                     
          .attr('width', legendRectSize)                          
          .attr('height', legendRectSize)                         
          .style('fill', color)                                   
          .style('stroke', color)                                   
            .on('click', function(label) {                            
              var rect = d3.select(this);                             
              var enabled = true;                                     


              if (rect.attr('class') === 'disabled') {                
                rect.attr('class', '');                               
              } else {                                                
                if (totalEnabled < 2) return;                         
                rect.attr('class', 'disabled');                       
                enabled = false;                                      
              }                                                       

              pie.value(function(d) {                                 
                if (d.label === label) d.enabled = enabled;           
                return (d.enabled) ? d.count : 0;                     
              });                                                    
              arcs = arcs.data(d3.values(dataset))                                 
            });                                                       
        legend.append('text')                                     
          .attr('x', legendRectSize + legendSpacing)              
          .attr('y', legendRectSize - legendSpacing)              
          .text(function (d, i) {
      return data[i].label;
});     
    path.exit().remove(); 
d3.select('#opts')  
  .on('change', function(d) {
    var server = eval(d3.select(this).property('value'));
    dataset.middle = server;
    updateLegend(dataset);
});

});
}

     updateLegend(dataset);

In the current version, you just add declarations for the enter selection, which affects only arcs that are inserted . 在当前版本中,您只需为enter选择添加声明,这仅影响插入的圆弧。 You need to guide D3 how to treat the update selection, which affects arcs that are updated and the exit selection, which affects arcs that are removed . 您需要指导D3如何处理update选择,这会影响已更新的弧,而exit选择会影响会移除的弧。 You can add these lines of code before the path.enter() statement. 您可以在path.enter()语句之前添加这些代码行。

path.attr("d", function(d, i, j) {
  return arc.innerRadius(10 + r * j).outerRadius(r * (j + 1))(d);
});

path.exit().remove();

The updated fiddle: http://jsfiddle.net/36q95k1c/5/ 更新的小提琴: http : //jsfiddle.net/36q95k1c/5/

To add to Hieu Le's nice answer, for your query about animations, it can be a bit tricky to figure out the right point at which to add the transition() call. 要添加到Hieu Le的一个很好的答案中,对于有关动画的查询,要弄清楚添加transition()调用的正确点可能有些棘手。 Try putting it on line 100 of Hieu Le's jsfiddle to see if it's what you're after: 尝试将其放在Hieu Le的jsfiddle的第100行中,看看它是否是您所追求的:

path.transition().attr("d", function(d, i, j) {
  return arc.innerRadius(10 + r * j).outerRadius(r * (j + 1))(d);
});

Once you've got it animating, check out the docs for information on different interpolations and tweens. 完成动画设置后,请查看文档以获取有关不同插值和补间的信息。

Cheers! 干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM