D3从下拉菜单中选择值以更新图表

时间:2018-07-24 01:01:45

标签: javascript arrays json d3.js donut-chart

我试图通过下拉菜单更新我的甜甜圈图,但是,执行函数时收到两个错误。我要创建的是一张表示特定医院以及多个类别(例如疾病,受伤等)的甜甜圈图。我使用d3.nest()将我的数据集放入嵌套的数据数组中。

方法:

 d3.json("hospitals.json", function (error, dataset) {

 if(error) throw error;

 var categoryByHospitals = d3.nest()
 .key(function(d) {return d.hospitalName;})
 .entries(dataset);

 categoryByHospitals.forEach(function(object) {
    object.values.forEach(function(d) {
        d.count = +d.count;
        d.enabled = true;
    });

我正在使用d3 v4,并在该网站上查看我的甜甜圈图:https://bl.ocks.org/tezzutezzu/c2653d42ffb4ecc01ffe2d6c97b2ee5e

下面包含屏幕截图和代码

  1. 屏幕截图

enter image description here

  1. JavaScript代码

     var timeDuration = 600;
     var firstTime = true;
    
    
     var width = 800;
     var height = 800;
    
    
     var radius = Math.min(width, height) / 2;
     var donutWidth = 100; 
    
    
     var legendRectSize = 25;
     var legendSpacing = 6; 
    
     var color = d3.scaleOrdinal(d3.schemeCategory20b);
    
     var svg = d3.select('#chart') 
    .append('svg') 
    .attr('width', width) 
    .attr('height', height)
    .append('g') 
    .attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')'); 
    
     var arc = d3.arc()
    .innerRadius(radius - donutWidth)
    .outerRadius(radius); 
    
     var pie = d3.pie() 
    .value(function(d) { return d.count; }) 
    .sort(null); 
    
     var total = d3.sum(dataset, d => d.count);
    
    
     var newTotal = d3.select('.new-total-holder')
    .append('span')
    .attr('class', 'newTotal').text(total);
    
    
     var tooltip = d3.select('#chart') 
    .append('div')                                     
    .attr('class', 'tooltip'); 
    
     tooltip.append('div') 
    .attr('class', 'label'); 
     tooltip.append('div') 
    .attr('class', 'count');                   
     tooltip.append('div')   
    .attr('class', 'percent'); 
    
    
     var path = svg.selectAll('path') 
    .data(pie(categoryByHospitals[17].values)) //.data(pie(dataset)) 
    .enter() 
    .append('path') 
    .attr('d', arc) 
    .attr('fill', function(d) { return color(d.data.category); }) 
    .each(function(d) { this._current - d; });
    
    
    path.on('mouseover', function(d) { 
    //doesn't work
    var total = d3.sum(d3.values(categoryByHospitals).map(function(d) { 
        return (d.enabled) ? d.count : 0;                 
    }));
    var percent = Math.round(1000 * d.data.count / total) / 10; 
    tooltip.select('.label').html(d.data.label);           
    tooltip.select('.count').html('Count: ' + d.data.count); 
    tooltip.select('.percent').html(percent + '%') 
    tooltip.style('display', 'block');                   
    });
    
    path.on('mouseout', function() {                        
    tooltip.style('display', 'none'); 
    });
    
    path.on('mousemove', function(d) {                 
    tooltip.style('top', (d3.event.layerY + 10) + 'px') 
        .style('left', (d3.event.layerX + 10) + 'px');
    });
    
    
     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 + ',' + 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; 
        var totalEnabled =   d3.sum(d3.values(categoryByHospitals).map(function(d) { 
            return (d.value.enabled) ? 1 : 0;
        }));
        if (rect.attr('class') === 'disabled') { 
            rect.attr('class', ''); 
        } else { // else
            if (totalEnabled < 2) return; 
            rect.attr('class', 'disabled'); 
            enabled = false; 
        }
    
        pie.value(function(d) {
            if (d.category === label) d.value.enabled = enabled; 
            return (d.value.enabled) ? d.value.count : 0;
        });
    
        path = path.data(pie(categoryByHospitals[17].values)); 
    
        path.transition() 
            .duration(750) 
            .attrTween('d', function(d) { 
                var interpolate = d3.interpolate(this._current, d); // this = current path element
                this._current = interpolate(0); 
                return function(t) {
                    return arc(interpolate(t));
                };
            });
    
    
        var newTotalCalc = d3.sum(categoryByHospitals.filter(function(d) { return d.enabled; }), d => d.count)
            // console.log(newTotalCalc);
    
    
        newTotal.text(newTotalCalc);
    });
    
    legend.append('text')
    .attr('x', legendRectSize + legendSpacing)
    .attr('y', legendRectSize - legendSpacing)
    .text(function(d) { return d; }); // return label
    
    
    
    //Filter by hospital
    var menu = d3.select(".dropDownMenu").selectAll("option")
    .data(categoryByHospitals)
    .enter()
    .append("option");
    
    menu.attr("value", function(d) { return d.key; })
    .on("change", change)
    .each(change)
    .property("checked", true);
    
    
    function change(category) {
    
    var path = svg.selectAll("path");
    var data0 = path.data(),
        data1 = pie(category.values);
    
    path = path.data(data1, key);
    
    path
        .transition()
        .duration(timeDuration)
        .attrTween("d", arcTween)
    
    path
        .enter()
        .append("path")
        .each(function(d, i) {
    
            var narc = findNeighborArc(i, data0, data1, key);
    
            if (narc) {
                this._current = narc;
                this._previous = narc;
    
            } else {
                this._current = d;
            }
        })
    
    .attr("fill", function(d, i) {
    
            return color(d.data.category)
        })
        .transition()
        .duration(timeDuration)
        .attrTween("d", arcTween)
    
    path
        .exit()
        .transition()
        .duration(timeDuration)
        .attrTween("d", function(d, index) {
            var currentIndex = this._previous.data.category;
            var i = d3.interpolateObject(d, this._previous);
    
            return function(t) {
                return arc(i(t))
            }
    
        })
    
       .remove()
    
       firstTime = false;
    
     }
    
    
     function key(d) {
      return d.data.category;
     }
    
     function type(d) {
       d.count = +d.count;
       return d;
     }
    
     function findNeighborArc(i, data0, data1, key) {
       var d;
    
        if (d = findPreceding(i, data0, data1, key)) {
        var obj = cloneObj(d)
        obj.startAngle = d.endAngle;
        return obj;
    } else if (d = findFollowing(i, data0, data1, key)) {
        var obj = cloneObj(d)
        obj.startAngle = d.endAngle;
        return obj;
    
    }
    
     return null
    }
    
     function findPreceding(i, data0, data1, key) {
        var m = data0.length;
        while (--i >= 0) {
        var k = key(data1[i]);
    
        for (var j = 0; j < m; j++) {
            if (key(data0[j]) === k) return data0[j];
        }
       }
      }
    
    function findFollowing(i, data0, data1, key) {
    var n = data1.length,
        m = data0.length;
    
    while (++i < n) {
        var k = key(data1[i]);
    
        for (var j = 0; j < m; j++) {
            if (key(data0[j]) === k) return data0[j];
        }
      }
    }
    
    function arcTween(d) {
    var i = d3.interpolate(this._current, d);
    
      this._current = i(0);
    
      return function(t) {
         return arc(i(t))
      }
    }
    
    function cloneObj(obj) {
    var o = {};
    
    for (var i in obj) {
        o[i] = obj[i];
    }
    
      return o;
    }
    
  2. JSON文件

     [{"hospitalName": "hospital1", "label":"100", "category": "Sickness", "females":"11", "males":"0", "unknown":"0", "count": "11"},
      {"hospitalName": "hospital1", "label": "321.0", "category": "Injury", "females":"0", "males":"1", "unknown":"2", "count": "3"},
      {"hospitalName": "hospital1" "label": "211","category": "Mental Disorders", "females":"2", "males":"0", "unknown":"3", "count": "5"},
      {"hospitalName": "hospital1","label": "254", "category": "Diseases","females":"1", "males":"0", "unknown":"0", "count": "1"},
      {"hospitalName": "hospital2","label": "000", "category": "None", "females":"2", "males":"0", "unknown":"0", "count": "2"},
      {"hospitalName": "hospital2", "label": "892.3", "category": "Symptoms","females":"9", "males":"2", "unknown":"0", "count": "11"}, 
      {"hospitalName": "hospital3","label": "000", "category": "None", "females":"1", "males":"0", "unknown":"0", "count": "1"},
      {"hospitalName": "hospital3", "label": "100", "category": "Sickness","females":"2", "males":"2", "unknown":"0", "count": "4"}]
    
  3. HTML

      <!doctype html>
      <html lang="en">
      <head>
      <meta charset="utf-8">
      <title>D3 Visualization-Donut Chart (V2)</title>
      <link href="style(v2).css" rel="stylesheet">
      <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
      <link href="https://fonts.googleapis.com/css?family=Oswald" rel="stylesheet">
      </head>
    
      <body>
    
      <div class="dropDownMenu">
        <select id="selection">
        <option id="mtf1" value="hospital1">hospital 1</option>
        <option id="mtf2" value="hospital2">hospital 2</option>
        <option id="mtf3" value="hospital3">hospital 3</option>
        </select>
     </div>
    
    
     <div id="chart"></div>
    
     </body>
    
     <script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.js'>.    </script>
     <script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js'></script>
     <script src="scriptsv2.js"></script>
    
     </html>
    

0 个答案:

没有答案