javascript - D3.js 中的协调饼图和条形图

标签 javascript d3.js charts

我有一个与条形图协调的画笔。当画笔移动并调整大小时,条形图仅显示过滤后的条形。在同一页面中,我有一个饼图,它与条形图和画笔不协调,但我希望它如此。我还希望饼图根据过滤后的值更新其内容。我怎样才能做到这一点?

这是我的代码,后面是 plnkr 链接,您可以在其中查看我到目前为止所做的事情:

<script type="text/javascript">
  var margin = {
      top: 20,
      right: 20,
      bottom: 70,
      left: 40,
      mid: 20
    },
    w = 750 - margin.left - margin.right,
    h = 300 - margin.top - margin.bottom;
  var barPadding = 1;
  var padding = 20;
  var miniHeight = 60;

  var selected;

  var svg = d3.select(".outer-wrapper .chart").append("svg")
    .attr("width", w + margin.left + margin.right)
    .attr("height", h + margin.top + margin.mid + miniHeight + margin.bottom)
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var barsGroup = svg.append('g')
                    .attr("class","barsGroup");

  var miniGroup = svg.append('g')
                    .attr("class","miniGroup")
                    .attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");

  var brushGroup = svg.append('g')
                    .attr("class","brushGroup")
                    .attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");

    var w2 = 400;
    var h2 = 400;

    var outerRadius = w2 / 2;
    var innerRadius = w2 / 3;
    var arc = d3.svg.arc()
                    .innerRadius(innerRadius)
                    .outerRadius(outerRadius);

    var pie = d3.layout.pie()
        .sort(null)
      .value(function(d) { return d.values; });

    var color = d3.scale.category20c();

    var svg2 = d3.select("body")
                .append("svg")
                .attr("width", w2)
                .attr("height", h2);


  d3.csv("data.csv", function(data) {

    var dataset = d3.nest()
      .key(function(d) {
        return d.Year;
      })
      .sortKeys(d3.ascending)
      .rollup(function(values) {
        return values.length;
      })
      .entries(data)
      .filter(function(d) {
        return d.key != "UNK" && d.key != "VAR" && d.key != 199 && d.key != 211 && d.key != 2017;
      });

    //SCALES

    var xScale = d3.scale.ordinal()
      .domain(dataset.map(function(d) {
        return d.key
      }))
      .rangeRoundBands([0, w], 0.05);

    var xScaleBrush = d3.scale.ordinal()
      .domain(d3.range(dataset.length))
        .rangeRoundBands([0, w], 0.05);


    var yScale = d3.scale.linear()
      .domain([0, d3.max(dataset, function(d) {
        return d.values;
      })])
      .range([h, 0]);

    //AXIS

    var xAxis = d3.svg.axis()
      .scale(xScale)
      .orient("bottom")
      .tickValues([1900,1920,1930,1940,1950,1960,1970,1980,1990,2000, 2010]);

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .ticks(6)
        .orient("left");

    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + h + ")")
      .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", "-.55em")
      .attr("transform", "rotate(-90)");

    svg.append("g")
        .attr("class","x2 axis")
        .attr("transform", "translate(" + 0 + "," + (margin.top + h + margin.mid + miniHeight) + ")" )
      .call(xAxis)
      .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", "-.55em")
      .attr("transform", "rotate(-90)");

    svg.append("g")
        .attr("class", "y axis")
      .append("g")
        .attr("class", "axisLabel")
      .append("text")
        .attr("transform", "translate(" + -(margin.left * 0.8) + "," + (h/2) + "), rotate(-90)")
        .style("text-anchor", "middle")
        .text("Score");

    var brush = d3.svg.brush()
      .x(xScaleBrush)
      .extent([0, w])
      .on("brush", display);

    brushGroup.append("g")
      .attr("class", "brush")
      .call(brush)
      .selectAll("rect")
      .attr("opacity", 0.5)
      .attr("height", miniHeight);

    function display() {

        selected =  xScaleBrush.domain()
                                .filter(function(d){
                                    return (brush.extent()[0] <= xScaleBrush(d)) && (xScaleBrush(d) <= brush.extent()[1]);
                                });

        var start;
        var end;

      /* Keep a minimum amount of bars on there to avoid any jank */
      if (selected.length > 2) {
        start = selected[0];
        end = selected[selected.length - 1] + 1;
      } else {
        start = 0;
        end = dataset.length;
      }

      var updatedData = dataset.slice(start, end);

      updateBars(updatedData);

    }

    function update(grp, data, main) {

      grp.selectAll("rect").data(data, function(d) {
          return d.key;
        })
        .attr("x", function(d) {
          return xScale(d.key);
        })
        .attr("y", function(d) {
          return main ? yScale(d.values) : 0;
        })
        .attr("width", function (d) {
                return xScale.rangeBand();
            })
        .attr("height", function(d) {
          return main ? h - yScale(d.values) : miniHeight;
        });
    }

    function enter(grp, data, main) {

      grp.selectAll("rect").data(data, function(d) {
          return d.key;
        })
        .enter()
        .append("rect")
        .attr("x", function(d, i) {
          return xScale(d.key);
        })
        .attr("y", function(d) {
          return main ? yScale( d.values) : 0;
        })
        .attr("width", function(d) {
                return xScale.rangeBand();
            })
        .attr("height", function(d) {
          return main ? h - yScale(d.values) : miniHeight;
        })
        .attr("fill", function(d) {
          var color = d3.scale.linear()
            .domain([0, d3.max(dataset, function(d) {
              return d.values;
            })])
            .range([200, 244]);
            var deg = color(d.values);
                return "hsl(" + deg + ", 100%, 50%)";
        })
        .on("mouseover", function(d) {

          if(main){

          d3.select(this)
            .attr("fill", "orange");

          var xPosition = parseFloat(d3.select(this).attr("x"));
          var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + 100;

          d3.select("#tooltip")
            .style("left", xPosition + "px")
            .style("top", yPosition + "px")
            .style("z-index", "10")
            .select("#value")
            .text(d.values);

          d3.select("#tooltip")
            .select("#key")
            .text("Film del " + d.key + " rilasciati su DVD");

          d3.select("#tooltip").classed("hidden", false);

          }

        })
        .on("mouseout", function(d) {
          d3.select(this)
            .transition()
            .duration(250)
            .attr("fill", function(d) {
              var color = d3.scale.linear()
                .domain([0, d3.max(dataset, function(d) {
                  return d.values;
                })])
                .range([200, 244]);
                var deg = color(d.values);
                    return "hsl(" + deg + ", 100%, 50%)";
            });

          d3.select("#tooltip").classed("hidden", true);
        });

    }


    function exit(grp, data) {

      grp.selectAll("rect").data(data, function(d) {
          return d.key;
        }).exit()
        .remove();

    }

    function updateBars(data) {

      xScale.domain(data.map(function(d) {
        return d.key
      }));
      yScale.domain([0, d3.max(data, function(d) {
        return d.values;
      })]);

      /* Update */
      update(barsGroup, data, true);

      /* Enter… */
      enter(barsGroup, data, true);

      /* Exit */
      exit(barsGroup, data);


        svg.select(".outer-wrapper .chart .y")
            .transition()
            .duration(10)
            .call(yAxis);

        svg.select(".outer-wrapper .chart .x")
            .transition()
            .duration(50)
            .call(xAxis);
    }


    enter(miniGroup, dataset, false);
    updateBars(dataset);


  var dataset2 = d3.nest()
          .key(function(d) { return d.Genre; })
          .sortKeys(d3.ascending)
          .rollup(function(values) {  return values.length; })
          .entries(data);




  var text = svg2.append("text")
            .attr("dx", 200)
            .attr("dy", 200)
            .attr("font-size", 30)
            .style("text-anchor", "middle")
            .attr("fill", "#36454f");

  var text2 = svg2.append("text")
            .attr("dx", 200)
            .attr("dy", 230)
            .attr("font-size", 20)
            .style("text-anchor", "middle")
            .attr("fill", "#36454f");

  var text3 = svg2.append("text")
            .attr("dx", 200)
            .attr("dy", 260)
            .attr("font-size", 20)
            .style("text-anchor", "middle")
            .attr("fill", "#36454f");

    //Set up groups
    var arcs = svg2.selectAll("g.arc")
                  .data(pie(dataset2))
                  .enter()
                  .append("g")
                  .attr("class", "arc")
                  .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
                  .on("mouseover", function(d) {

                     var total = data.length;
             var percent = Math.round(1000 * d.value / total) / 10;

                   text.text(d.data.key).attr("class", "inner-circle");
                   text2.text(d.value + " DVD");
                   text3.text(percent +"%");

                })
                .on("mouseout", function(d) {

                  text.text(function(d) { return ""; });
                  text2.text(function(d) { return ""; });
                  text3.text(function(d) { return ""; });

                });

    //Draw arc paths
    arcs.append("path")
        .attr("fill", function(d, i) {
            return color(i);
        })
        .attr("d", arc);

  });
</script>

http://plnkr.co/edit/cwNl6zUSOM4yPmUtSRr4?p=preview

最佳答案

您可以通过将构建饼图的部分转换为接收新数据的函数来实现这一点。

唯一的调整是我要做的第一件事是删除以前的饼图,用新数据重新绘制它:

function updatePie(data){    
    svg2.selectAll("g.arc").remove();

完整代码如下:

<script type="text/javascript">
var margin = {
    top: 20,
    right: 20,
    bottom: 70,
    left: 40,
    mid: 20
  },
  w = 750 - margin.left - margin.right,
  h = 300 - margin.top - margin.bottom;
var barPadding = 1;
var padding = 20;
var miniHeight = 60;

var selected;

var svg = d3.select(".outer-wrapper .chart").append("svg")
  .attr("width", w + margin.left + margin.right)
  .attr("height", h + margin.top + margin.mid + miniHeight + margin.bottom)
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var barsGroup = svg.append('g')
                    .attr("class","barsGroup");

var miniGroup = svg.append('g')
                    .attr("class","miniGroup")
                    .attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");

var brushGroup = svg.append('g')
                    .attr("class","brushGroup")
                    .attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");

    var w2 = 400;
    var h2 = 400;

    var outerRadius = w2 / 2;
    var innerRadius = w2 / 3;
    var arc = d3.svg.arc()
                    .innerRadius(innerRadius)
                    .outerRadius(outerRadius);

    var pie = d3.layout.pie()
        .sort(null)
    .value(function(d) { return d.values; });

    var color = d3.scale.category20c();

    var svg2 = d3.select("body")
                .append("svg")
                .attr("width", w2)
                .attr("height", h2);


d3.csv("data.csv", function(data) {

  var dataset = d3.nest()
    .key(function(d) {
      return d.Year;
    })
    .sortKeys(d3.ascending)
    .rollup(function(values) {
      return values.length;
    })
    .entries(data)
    .filter(function(d) {
      return d.key != "UNK" && d.key != "VAR" && d.key != 199 && d.key != 211 && d.key != 2017;
    });

  //SCALES

  var xScale = d3.scale.ordinal()
    .domain(dataset.map(function(d) {
      return d.key
    }))
    .rangeRoundBands([0, w], 0.05);

  var xScaleBrush = d3.scale.ordinal()
    .domain(d3.range(dataset.length))
    .rangeRoundBands([0, w], 0.05);


  var yScale = d3.scale.linear()
    .domain([0, d3.max(dataset, function(d) {
      return d.values;
    })])
    .range([h, 0]);

  //AXIS

  var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    .tickValues([1900,1920,1930,1940,1950,1960,1970,1980,1990,2000, 2010,2020,2030,2040,2050,2060]);

  var yAxis = d3.svg.axis()
    .scale(yScale)
    .ticks(6)
    .orient("left");

  //Appendi asse x
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + h + ")")
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");

  //Asse x per brush
  svg.append("g")
    .attr("class","x2 axis")
    .attr("transform", "translate(" + 0 + "," + (margin.top + h + margin.mid + miniHeight) + ")" )
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");

  svg.append("g")
    .attr("class", "y axis")
    .append("g")
    .attr("class", "axisLabel")
    .append("text")
    .attr("transform", "translate(" + -(margin.left * 0.8) + "," + (h/2) + "), rotate(-90)")
    .style("text-anchor", "middle")
    .text("Score");

  var brush = d3.svg.brush()
    .x(xScaleBrush)
    .extent([0, w])
    .on("brush", display);

  brushGroup.append("g")
    .attr("class", "brush")
    .call(brush)
    .selectAll("rect")
    .attr("opacity", 0.5)
    .attr("height", miniHeight);

  function display() {

    selected =  xScaleBrush.domain()
                            .filter(function(d){
                                return (brush.extent()[0] <= xScaleBrush(d)) && (xScaleBrush(d) <= brush.extent()[1]);
                            });

    var start;
    var end;

    /* Keep a minimum amount of bars on there to avoid any jank */
    if (selected.length > 2) {
      start = selected[0];
      end = selected[selected.length - 1] + 1;
    } else {
      start = 0;
      end = dataset.length;
    }

    var updatedData = dataset.slice(start, end);

    updateBars(updatedData);
    updatePie(updatedData);

  }

  function update(grp, data, main) {

    grp.selectAll("rect").data(data, function(d) {
        return d.key;
      })
      .attr("x", function(d) {
        return xScale(d.key);
      })
      .attr("y", function(d) {
        return main ? yScale(d.values) : 0;
      })
      .attr("width", function (d) {
            return xScale.rangeBand();
        })
      .attr("height", function(d) {
        return main ? h - yScale(d.values) : miniHeight;
      });
  }

  function enter(grp, data, main) {

    grp.selectAll("rect").data(data, function(d) {
        return d.key;
      })
      .enter()
      .append("rect")
      .attr("x", function(d, i) {
        return xScale(d.key);
      })
      .attr("y", function(d) {
        return main ? yScale( d.values) : 0;
      })
      .attr("width", function(d) {
            return xScale.rangeBand();
        })
      .attr("height", function(d) {
        return main ? h - yScale(d.values) : miniHeight;
      })
      .attr("fill", function(d) {
        var color = d3.scale.linear()
          .domain([0, d3.max(dataset, function(d) {
            return d.values;
          })])
          .range([200, 244]);
          var deg = color(d.values);
                return "hsl(" + deg + ", 100%, 50%)";
      })
      .on("mouseover", function(d) {

        if(main){

        d3.select(this)
          .attr("fill", "orange");

        var xPosition = parseFloat(d3.select(this).attr("x"));
        var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + 100;

        d3.select("#tooltip")
          .style("left", xPosition + "px")
          .style("top", yPosition + "px")
          .style("z-index", "10")
          .select("#value")
          .text(d.values);

        d3.select("#tooltip")
          .select("#key")
          .text("Film del " + d.key + " rilasciati su DVD");

        d3.select("#tooltip").classed("hidden", false);

        }

      })
      .on("mouseout", function(d) {
        d3.select(this)
          .transition()
          .duration(250)
          .attr("fill", function(d) {
            var color = d3.scale.linear()
              .domain([0, d3.max(dataset, function(d) {
                return d.values;
              })])
              .range([200, 244]);
              var deg = color(d.values);
                    return "hsl(" + deg + ", 100%, 50%)";
          });

        d3.select("#tooltip").classed("hidden", true);
      });

  }


  function exit(grp, data) {

    grp.selectAll("rect").data(data, function(d) {
        return d.key;
      }).exit()
      .remove();

  }

  function updateBars(data) {

    xScale.domain(data.map(function(d) {
      return d.key
    }));
    yScale.domain([0, d3.max(data, function(d) {
      return d.values;
    })]);

    /* Update */
    update(barsGroup, data, true);

    /* Enter… */
    enter(barsGroup, data, true);

    /* Exit */
    exit(barsGroup, data);


    svg.select(".outer-wrapper .chart .y")
        .transition()
        .duration(10)
        .call(yAxis);

        svg.select(".outer-wrapper .chart .x")
        .transition()
        .duration(50)
        .call(xAxis);
  }


  enter(miniGroup, dataset, false);
  updateBars(dataset);

var dataset2 = d3.nest()
        .key(function(d) { return d.Genre; })
        .sortKeys(d3.ascending)
        .rollup(function(values) {  return values.length; })
        .entries(data);


var text = svg2.append("text")
          .attr("dx", 200)
          .attr("dy", 200)
          .attr("font-size", 30)
          .style("text-anchor", "middle")
          .attr("fill", "#36454f");

var text2 = svg2.append("text")
          .attr("dx", 200)
          .attr("dy", 230)
          .attr("font-size", 20)
          .style("text-anchor", "middle")
          .attr("fill", "#36454f");

var text3 = svg2.append("text")
          .attr("dx", 200)
          .attr("dy", 260)
          .attr("font-size", 20)
          .style("text-anchor", "middle")
          .attr("fill", "#36454f");

function updatePie(data){
  svg2.selectAll("g.arc").remove();
  var arcs = svg2.selectAll("g.arc")
        .data(pie(data))
        .enter()
        .append("g")
        .attr("class", "arc")
        .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
        .on("mouseover", function(d) {

           var total = data.length;
           var percent = Math.round(1000 * d.value / total) / 10;

           text.text(d.data.key).attr("class", "inner-circle");
           text2.text(d.value + " DVD");
           text3.text(percent +"%");

        })
        .on("mouseout", function(d) {

          text.text(function(d) { return ""; });
          text2.text(function(d) { return ""; });
          text3.text(function(d) { return ""; });

        });
  arcs.append("path")
    .attr("fill", function(d, i) {
      return color(i);
    })
    .attr("d", arc);

}
updatePie(dataset2);

});

关于javascript - D3.js 中的协调饼图和条形图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35228059/

相关文章:

typescript - D3 鼠标悬停和鼠标移出

javascript - jQuery ajax 成功页面中的搜索框 - 循环中的问题

javascript - 单击导航箭头时如何停止 Owl Carousel

HTML SVG : show element on top of all elements

javascript - 如何禁用 amCharts 跳过我的数据?

java - 如何向图表添加趋势线?

javascript - highchart x 轴未显示正确的日期标签

javascript - 向每个列表项添加当前状态

javascript - 是否可以使用类向 React 组件添加内联样式?

css - 在创建的 :, 中,我的方法无法正常工作