使用 D3 更新多折线图的模式

Update Pattern for Multi-Line Chart with D3

我正在 D3 中创建一个小型仪表板,其中:单击圆环图的一部分时,将更新相邻的折线图。代码大致基于此块 http://bl.ocks.org/diethardsteiner/3287802.

这是我现在所拥有的和问题的 JSFiddle:https://jsfiddle.net/394mLyz9/

如果滚动到 fiddle 的末尾,您会发现 'update' 代码如下:

function updateLineChart(group, colorChosen) {


var basics = dsLineChartBasics();

var margin = basics.margin,
    width = basics.width,
    height = basics.height;

var currentDatasetLineChart = datasetLineChartChosen(group);

var dataNest1 = d3.nest()
    .key(function(d) {return d.group2;})
    .entries(currentDatasetLineChart); 

console.log(dataNest1);

console.log(currentDatasetLineChart);

var xScale = d3.scale.linear()
    .range([0, width])
    .domain(d3.extent(currentDatasetLineChart, function(d) { return d.category; }));

var yScale = d3.scale.linear()
    .range([height, 0])
    .domain([0, d3.max(currentDatasetLineChart, function(d) { return d.measure; })]);       

var line = d3.svg.line()
     .interpolate("basis")  
    .x(function(d, i) { return xScale(d.category); })
    .y(function(d) { return yScale(d.measure); });

var svg = d3.select("#lineChart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom);   

var plot = svg.selectAll("plot")
  .data(dataNest1)
 .enter()
  .append("g")
.append("path")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
  .attr("class", "line")
  .attr("d", function(d) { return line(d.values); })
  .style("stroke", colorChosen);

//plot.exit().remove(); 


}

您会注意到,单击饼图切片时,它会在现有图表下创建新的折线图,而不是更新现有图表。我已经阅读了一般更新模式教程,但仍然收效甚微。任何帮助将不胜感激。

首先,您在更新功能中做的工作太多了。如果您增加了一些变量的范围,则无需在每次更新时重新创建它们。 svgxScaleyScalemarginsline 都是您的初始抽奖和更新可以共享的内容。

其次,虽然更新模式很重要,但在这种情况下,您实际上并不是在用新数据更新图,而是在用所有新数据创建一个全新的图。考虑到这一点,我只是转储 SVG 的内容并重新添加你的行。

折线图函数:

// increase the scope of these
var margin, line, svg, xScale, yScale;

function lineChart() {

  var basics = dsLineChartBasics();

  // declared above
  margin = basics.margin,
    ...
  // declared above
  xScale = d3.scale.linear()
    ...
}

更新图表功能:

function updateLineChart(group, colorChosen) {

  var currentDatasetLineChart = datasetLineChartChosen(group);

  ...

  // adjust xScale based on new data
  xScale.domain(d3.extent(currentDatasetLineChart, function(d) {
      return d.category;
    }));

  // adjust yScale based on new data
  yScale.domain([0, d3.max(currentDatasetLineChart, function(d) {
      return d.measure;
    })]);

  // remove contents of svg
  svg.selectAll("*").remove();

  // replot
  var plot = svg.selectAll("g") //<-- don't use "plot" here it has no meaning
    .data(dataNest1)
  ...

}

完整代码示例:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  <style>
    #chart-container {
      float: left;
    }
    
    .line {
      fill: none;
      stroke-width: 3px;
    }
    
    #pieChart {
      float: left;
      width: 50%;
     }
    
    #lineChart {
      width: 50%;
      float: right;
    }
  </style>
</head>

<body>
  <div id="pieChart"></div>
  <div id="lineChart"></div>
  <script>
    function pieChart() {

      var dataset = [{
        category: "A",
        measure: 3270
      }, {
        category: "B",
        measure: 19309
      }, {
        category: "C",
        measure: 13120
      }, ];


      var width = 350,
        height = 350,
        outerRadius = Math.min(width, height) / 2,
        innerRadius = outerRadius * .5,
        color = d3.scale.category20();

      var svg = d3.select("#chart-container").append("svg")
        .attr("width", width)
        .attr("height", height)
        .attr("id", "chart");

      var vis = d3.select("#pieChart")
        .append("svg:svg")
        .data([dataset])
        .attr("width", width)
        .attr("height", height)
        .append("svg:g")
        .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");

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


      var pie = d3.layout.pie()
        .value(function(d) {
          return d.measure;
        });

      var arcs = vis.selectAll("g")
        .data(pie)
        .enter()
        .append("svg:g")
        .on("click", change);

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

      //change event for line visualization
      function change(d, i) {

        updateLineChart(d.data.category, color(i));

      }
    }
    pieChart();

    var datasetLineChart = [

      //0
      {
        "group": "All",
        "category": 0,
        "measure": 171,
        "group2": 0
      }, {
        "group": "All",
        "category": 25,
        "measure": 191,
        "group2": 0
      }, {
        "group": "All",
        "category": 50,
        "measure": 239,
        "group2": 0
      }, {
        "group": "All",
        "category": 75,
        "measure": 1212,
        "group2": 0
      }, {
        "group": "All",
        "category": 100,
        "measure": 1773,
        "group2": 0
      }, {
        "group": "All",
        "category": 125,
        "measure": 3866,
        "group2": 0
      }, {
        "group": "All",
        "category": 150,
        "measure": 9092,
        "group2": 0
      }, {
        "group": "All",
        "category": 175,
        "measure": 6973,
        "group2": 0
      }, {
        "group": "All",
        "category": 200,
        "measure": 11717,
        "group2": 0
      },
      //1
      {
        "group": "All",
        "category": 0,
        "measure": 180,
        "group2": 1
      }, {
        "group": "All",
        "category": 25,
        "measure": 188,
        "group2": 1
      }, {
        "group": "All",
        "category": 50,
        "measure": 248,
        "group2": 1
      }, {
        "group": "All",
        "category": 75,
        "measure": 950,
        "group2": 1
      }, {
        "group": "All",
        "category": 100,
        "measure": 1607,
        "group2": 1
      }, {
        "group": "All",
        "category": 125,
        "measure": 3961,
        "group2": 1
      }, {
        "group": "All",
        "category": 150,
        "measure": 8405,
        "group2": 1
      }, {
        "group": "All",
        "category": 175,
        "measure": 17304,
        "group2": 1
      }, {
        "group": "All",
        "category": 200,
        "measure": 24097,
        "group2": 1
      },
      //20
      {
        "group": "All",
        "category": 0,
        "measure": 215,
        "group2": 20
      }, {
        "group": "All",
        "category": 25,
        "measure": 369,
        "group2": 20
      }, {
        "group": "All",
        "category": 50,
        "measure": 1311,
        "group2": 20
      }, {
        "group": "All",
        "category": 75,
        "measure": 3323,
        "group2": 20
      }, {
        "group": "All",
        "category": 100,
        "measure": 5766,
        "group2": 20
      }, {
        "group": "All",
        "category": 125,
        "measure": 13473,
        "group2": 20
      }, {
        "group": "All",
        "category": 150,
        "measure": 21960,
        "group2": 20
      }, {
        "group": "All",
        "category": 175,
        "measure": 28305,
        "group2": 20
      }, {
        "group": "All",
        "category": 200,
        "measure": 34886,
        "group2": 20
      },
      //100
      {
        "group": "All",
        "category": 0,
        "measure": 228,
        "group2": 100
      }, {
        "group": "All",
        "category": 25,
        "measure": 389,
        "group2": 100
      }, {
        "group": "All",
        "category": 50,
        "measure": 1981,
        "group2": 100
      }, {
        "group": "All",
        "category": 75,
        "measure": 3646,
        "group2": 100
      }, {
        "group": "All",
        "category": 100,
        "measure": 6846,
        "group2": 100
      }, {
        "group": "All",
        "category": 125,
        "measure": 17987,
        "group2": 100
      }, {
        "group": "All",
        "category": 150,
        "measure": 23910,
        "group2": 100
      }, {
        "group": "All",
        "category": 175,
        "measure": 29333,
        "group2": 100
      }, {
        "group": "All",
        "category": 200,
        "measure": 35154,
        "group2": 100
      },

      //0
      {
        "group": "A",
        "category": 0,
        "measure": 16,
        "group2": 0
      }, {
        "group": "A",
        "category": 25,
        "measure": 18,
        "group2": 0
      }, {
        "group": "A",
        "category": 50,
        "measure": 22,
        "group2": 0
      }, {
        "group": "A",
        "category": 75,
        "measure": 132,
        "group2": 0
      }, {
        "group": "A",
        "category": 100,
        "measure": 194,
        "group2": 0
      }, {
        "group": "A",
        "category": 125,
        "measure": 386,
        "group2": 0
      }, {
        "group": "A",
        "category": 150,
        "measure": 865,
        "group2": 0
      }, {
        "group": "A",
        "category": 175,
        "measure": 761,
        "group2": 0
      }, {
        "group": "A",
        "category": 200,
        "measure": 1214,
        "group2": 0
      },
      //1
      {
        "group": "A",
        "category": 0,
        "measure": 17,
        "group2": 1
      }, {
        "group": "A",
        "category": 25,
        "measure": 17,
        "group2": 1
      }, {
        "group": "A",
        "category": 50,
        "measure": 24,
        "group2": 1
      }, {
        "group": "A",
        "category": 75,
        "measure": 104,
        "group2": 1
      }, {
        "group": "A",
        "category": 100,
        "measure": 174,
        "group2": 1
      }, {
        "group": "A",
        "category": 125,
        "measure": 339,
        "group2": 1
      }, {
        "group": "A",
        "category": 150,
        "measure": 787,
        "group2": 1
      }, {
        "group": "A",
        "category": 175,
        "measure": 1583,
        "group2": 1
      }, {
        "group": "A",
        "category": 200,
        "measure": 2198,
        "group2": 1
      },
      //20
      {
        "group": "A",
        "category": 0,
        "measure": 20,
        "group2": 20
      }, {
        "group": "A",
        "category": 25,
        "measure": 34,
        "group2": 20
      }, {
        "group": "A",
        "category": 50,
        "measure": 142,
        "group2": 20
      }, {
        "group": "A",
        "category": 75,
        "measure": 340,
        "group2": 20
      }, {
        "group": "A",
        "category": 100,
        "measure": 585,
        "group2": 20
      }, {
        "group": "A",
        "category": 125,
        "measure": 1233,
        "group2": 20
      }, {
        "group": "A",
        "category": 150,
        "measure": 1998,
        "group2": 20
      }, {
        "group": "A",
        "category": 175,
        "measure": 2578,
        "group2": 20
      }, {
        "group": "A",
        "category": 200,
        "measure": 3278,
        "group2": 20
      },
      //100
      {
        "group": "A",
        "category": 0,
        "measure": 20,
        "group2": 100
      }, {
        "group": "A",
        "category": 25,
        "measure": 34,
        "group2": 100
      }, {
        "group": "A",
        "category": 50,
        "measure": 211,
        "group2": 100
      }, {
        "group": "A",
        "category": 75,
        "measure": 363,
        "group2": 100
      }, {
        "group": "A",
        "category": 100,
        "measure": 667,
        "group2": 100
      }, {
        "group": "A",
        "category": 125,
        "measure": 1593,
        "group2": 100
      }, {
        "group": "A",
        "category": 150,
        "measure": 2111,
        "group2": 100
      }, {
        "group": "A",
        "category": 175,
        "measure": 2636,
        "group2": 100
      }, {
        "group": "A",
        "category": 200,
        "measure": 3270,
        "group2": 100
      },

      //0
      {
        "group": "C",
        "category": 0,
        "measure": 37,
        "group2": 0
      }, {
        "group": "C",
        "category": 25,
        "measure": 45,
        "group2": 0
      }, {
        "group": "C",
        "category": 50,
        "measure": 52,
        "group2": 0
      }, {
        "group": "C",
        "category": 75,
        "measure": 413,
        "group2": 0
      }, {
        "group": "C",
        "category": 100,
        "measure": 527,
        "group2": 0
      }, {
        "group": "C",
        "category": 125,
        "measure": 1252,
        "group2": 0
      }, {
        "group": "C",
        "category": 150,
        "measure": 2914,
        "group2": 0
      }, {
        "group": "C",
        "category": 175,
        "measure": 2109,
        "group2": 0
      }, {
        "group": "C",
        "category": 200,
        "measure": 3687,
        "group2": 0
      },
      //1
      {
        "group": "C",
        "category": 0,
        "measure": 42,
        "group2": 1
      }, {
        "group": "C",
        "category": 25,
        "measure": 43,
        "group2": 1
      }, {
        "group": "C",
        "category": 50,
        "measure": 52,
        "group2": 1
      }, {
        "group": "C",
        "category": 75,
        "measure": 317,
        "group2": 1
      }, {
        "group": "C",
        "category": 100,
        "measure": 491,
        "group2": 1
      }, {
        "group": "C",
        "category": 125,
        "measure": 1225,
        "group2": 1
      }, {
        "group": "C",
        "category": 150,
        "measure": 2723,
        "group2": 1
      }, {
        "group": "C",
        "category": 175,
        "measure": 6004,
        "group2": 1
      }, {
        "group": "C",
        "category": 200,
        "measure": 8668,
        "group2": 1
      },
      //20
      {
        "group": "C",
        "category": 0,
        "measure": 47,
        "group2": 20
      }, {
        "group": "C",
        "category": 25,
        "measure": 80,
        "group2": 20
      }, {
        "group": "C",
        "category": 50,
        "measure": 422,
        "group2": 20
      }, {
        "group": "C",
        "category": 75,
        "measure": 1039,
        "group2": 20
      }, {
        "group": "C",
        "category": 100,
        "measure": 1826,
        "group2": 20
      }, {
        "group": "C",
        "category": 125,
        "measure": 4537,
        "group2": 20
      }, {
        "group": "C",
        "category": 150,
        "measure": 7782,
        "group2": 20
      }, {
        "group": "C",
        "category": 175,
        "measure": 10493,
        "group2": 20
      }, {
        "group": "C",
        "category": 200,
        "measure": 13122,
        "group2": 20
      },
      //100
      {
        "group": "C",
        "category": 0,
        "measure": 51,
        "group2": 100
      }, {
        "group": "C",
        "category": 25,
        "measure": 93,
        "group2": 100
      }, {
        "group": "C",
        "category": 50,
        "measure": 664,
        "group2": 100
      }, {
        "group": "C",
        "category": 75,
        "measure": 1171,
        "group2": 100
      }, {
        "group": "C",
        "category": 100,
        "measure": 2103,
        "group2": 100
      }, {
        "group": "C",
        "category": 125,
        "measure": 6414,
        "group2": 100
      }, {
        "group": "C",
        "category": 150,
        "measure": 8713,
        "group2": 100
      }, {
        "group": "C",
        "category": 175,
        "measure": 10830,
        "group2": 100
      }, {
        "group": "C",
        "category": 200,
        "measure": 13120,
        "group2": 100
      },

      //0
      {
        "group": "B",
        "category": 0,
        "measure": 110,
        "group2": 0
      }, {
        "group": "B",
        "category": 25,
        "measure": 123,
        "group2": 0
      }, {
        "group": "B",
        "category": 50,
        "measure": 155,
        "group2": 0
      }, {
        "group": "B",
        "category": 75,
        "measure": 773,
        "group2": 0
      }, {
        "group": "B",
        "category": 100,
        "measure": 1093,
        "group2": 0
      }, {
        "group": "B",
        "category": 125,
        "measure": 2307,
        "group2": 0
      }, {
        "group": "B",
        "category": 150,
        "measure": 5579,
        "group2": 0
      }, {
        "group": "B",
        "category": 175,
        "measure": 3969,
        "group2": 0
      }, {
        "group": "B",
        "category": 200,
        "measure": 6754,
        "group2": 0
      },
      //1
      {
        "group": "B",
        "category": 0,
        "measure": 114,
        "group2": 1
      }, {
        "group": "B",
        "category": 25,
        "measure": 112,
        "group2": 1
      }, {
        "group": "B",
        "category": 50,
        "measure": 163,
        "group2": 1
      }, {
        "group": "B",
        "category": 75,
        "measure": 576,
        "group2": 1
      }, {
        "group": "B",
        "category": 100,
        "measure": 994,
        "group2": 1
      }, {
        "group": "B",
        "category": 125,
        "measure": 2422,
        "group2": 1
      }, {
        "group": "B",
        "category": 150,
        "measure": 5140,
        "group2": 1
      }, {
        "group": "B",
        "category": 175,
        "measure": 10315,
        "group2": 1
      }, {
        "group": "B",
        "category": 200,
        "measure": 13675,
        "group2": 1
      },
      //20
      {
        "group": "B",
        "category": 0,
        "measure": 139,
        "group2": 20
      }, {
        "group": "B",
        "category": 25,
        "measure": 243,
        "group2": 20
      }, {
        "group": "B",
        "category": 50,
        "measure": 799,
        "group2": 20
      }, {
        "group": "B",
        "category": 75,
        "measure": 2027,
        "group2": 20
      }, {
        "group": "B",
        "category": 100,
        "measure": 3507,
        "group2": 20
      }, {
        "group": "B",
        "category": 125,
        "measure": 8148,
        "group2": 20
      }, {
        "group": "B",
        "category": 150,
        "measure": 12621,
        "group2": 20
      }, {
        "group": "B",
        "category": 175,
        "measure": 15735,
        "group2": 20
      }, {
        "group": "B",
        "category": 200,
        "measure": 18961,
        "group2": 20
      },
      //100
      {
        "group": "B",
        "category": 0,
        "measure": 149,
        "group2": 100
      }, {
        "group": "B",
        "category": 25,
        "measure": 259,
        "group2": 100
      }, {
        "group": "B",
        "category": 50,
        "measure": 1189,
        "group2": 100
      }, {
        "group": "B",
        "category": 75,
        "measure": 2213,
        "group2": 100
      }, {
        "group": "B",
        "category": 100,
        "measure": 4311,
        "group2": 100
      }, {
        "group": "B",
        "category": 125,
        "measure": 10631,
        "group2": 100
      }, {
        "group": "B",
        "category": 150,
        "measure": 13645,
        "group2": 100
      }, {
        "group": "B",
        "category": 175,
        "measure": 16443,
        "group2": 100
      }, {
        "group": "B",
        "category": 200,
        "measure": 19309,
        "group2": 100
      }

    ];

    // set initial group value
    var group = "All";

    function datasetLineChartChosen(group) {
      var ds = [];
      for (x in datasetLineChart) {
        if (datasetLineChart[x].group == group) {
          ds.push(datasetLineChart[x]);
        }
      }
      return ds;
    }

    var firstDatasetLineChart = datasetLineChartChosen(group);

    function dsLineChartBasics() {

      var margin = {
          top: 0,
          right: 0,
          bottom: 0,
          left: 0
        },
        width = 500 - margin.left - margin.right,
        height = 300 - margin.top - margin.bottom;

      return {
        margin: margin,
        width: width,
        height: height
      }
    }


    var margin, line, svg, xScale, yScale;

    function lineChart() {

      var basics = dsLineChartBasics();

      margin = basics.margin,
        width = basics.width,
        height = basics.height;

      var dataNest = d3.nest()
        .key(function(d) {
          return d.group2;
        })
        .entries(firstDatasetLineChart);

      xScale = d3.scale.linear()
        .range([0, width])
        .domain(d3.extent(datasetLineChart, function(d) {
          return d.category;
        }));

      yScale = d3.scale.linear()
        .range([height, 0])
        .domain([0, d3.max(datasetLineChart, function(d) {
          return d.measure;
        })]);

      line = d3.svg.line()
        .interpolate("basis")
        .x(function(d) {
          return xScale(d.category);
        })
        .y(function(d) {
          return yScale(d.measure);
        });

      svg = d3.selectAll("#lineChart")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


      svg.selectAll("plot")
        .data(dataNest)
        .enter()
        .append("path")
        .attr("class", "line")
        .attr("d", function(d) {
          return line(d.values);
        })
        .style("stroke", "lightGrey");
    }

    lineChart();

    function updateLineChart(group, colorChosen) {


      var currentDatasetLineChart = datasetLineChartChosen(group);

      var dataNest1 = d3.nest()
        .key(function(d) {
          return d.group2;
        })
        .entries(currentDatasetLineChart);

      console.log(dataNest1);

      console.log(currentDatasetLineChart);

      xScale.domain(d3.extent(currentDatasetLineChart, function(d) {
          return d.category;
        }));

      yScale.domain([0, d3.max(currentDatasetLineChart, function(d) {
          return d.measure;
        })]);
        
      
      svg.selectAll("*").remove();

      var plot = svg.selectAll("g")
        .data(dataNest1)
        .enter()
        .append("g")
        .append("path")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .attr("class", "line")
        .attr("d", function(d) {
          return line(d.values);
        })
        .style("stroke", colorChosen);

      //plot.exit().remove(); 


    }
  </script>
</body>

</html>