在同一页面中创建多个图表时出现问题

时间:2018-11-08 15:05:17

标签: javascript d3.js svg

我有两个函数,每个函数应该从同一个数据集中绘制两个ID分别为 one two 的SVG的图表。

我创建了不同的变量以将图表附加到其相应的SVG:

var svg1 = d3.select("#one")
var svg2 = d3.select("#two")

问题在于为第二个SVG绘制图表的功能会覆盖两个图表。

如果分别运行每个功能,则可以看到图表正确返回。 (注释每个函数调用,以查看另一个图表中被覆盖的数据)

JS Fiddle

<html>
<body>
<svg id="one"></svg>
<svg id="two"></svg>
<script>
// variables we'll be filtering by
var quantile;
var amount;
var type;
var risk;

w = window.innerWidth;
h = window.innerHeight;

// <-- Make Selection -->
// Possible values --
// quantile: [1 2 3 4]
// variable: ['Income' 'Payments' 'Consumption' 'Utility']
// amount: [ 5000 30000 70000]
// type: ['Loan' 'ISA']
// risk: [1 2 3 4]

quantile = 1;
amount=5000;
type = 'Loan';
risk = 2;

getFirst();
getSecond();

function getFirst() {

variable= 'Income';

// chart stuff
 margin = {top: h/4, right: w/4, bottom: h/4, left: w/4},
    width = window.innerWidth - margin.left - margin.right,
    height = window.innerHeight - margin.top - margin.bottom;

x = d3.scaleLinear()
  .rangeRound([0, width]);

y = d3.scaleLinear()
  .rangeRound([height,0]);

valueline = d3.line()
    .x(function(d) { return x(d.key); })
    .y(function(d) { return y(d.value); });

var svg1 = d3.select("#one")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform",
          "translate(" + margin.left + "," + margin.top + ")");

// data
d3.csv("https://raw.githubusercontent.com/JainFamilyInstitute/isa-app/master/data/data_vis.csv?token=AXiiVXcAwXZjLK4-3tiyxKwj8yaVMVDmks5b6b8NwA%3D%3D", function(error, data) {
  if (error) throw error;

  // filter by selection
  data = data.filter(function(d) { 
          return (d.quantile == quantile) &
          (d.variable == variable) &
          (d.amount == amount) &
          (d.type == type) &
          (d.risk == risk) }); 

  // create visualizable array with only ages and amounts for selected series
  data_filtered = data.map(({ quantile,amount,risk,type,variable, ...item }) => item);
  data_vis = data_filtered[0];
  console.log(data_vis);

  result = [];
  for(i=22;i<101;i++){
    key = i;
    value =parseFloat(data_vis[i]);
    result.push({
            key: key,
            value: value
        });
  }

  // console.log(data_vis);
  console.log(result);

  // Scale the range of the data
  x.domain([d3.min(result, function(d) { return d.key; }), d3.max(result, function(d) { return d.key; })]);
  y.domain([0, d3.max(result, function(d) { return d.value; })]);

  // Add the valueline path.
  svg1.append("path")
      .data([result])
      .attr("class", "line")
      .attr("d", valueline);

  // Add the X Axis
  svg1.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  // Add the Y Axis
    function y_grid_lines() {
    return d3.axisLeft(y)
  }

  svg1.append("g")
    .attr("class", "grid")
    .call(y_grid_lines()
      .tickSize(-width)
      );

});

}


function getSecond() {

variable= 'Payments';

// chart stuff
margin = {top: h/4, right: w/4, bottom: h/4, left: w/4},
    width = window.innerWidth - margin.left - margin.right,
    height = window.innerHeight - margin.top - margin.bottom;

x = d3.scaleLinear()
  .rangeRound([0, width]);

y = d3.scaleLinear()
  .rangeRound([height,0]);

valueline = d3.line()
    .x(function(d) { return x(d.key); })
    .y(function(d) { return y(d.value); });

var svg2 = d3.select("#two")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform",
          "translate(" + margin.left + "," + margin.top + ")");

// data
d3.csv("https://raw.githubusercontent.com/JainFamilyInstitute/isa-app/master/data/data_vis.csv?token=AXiiVXcAwXZjLK4-3tiyxKwj8yaVMVDmks5b6b8NwA%3D%3D", function(error, data) {
  if (error) throw error;

  // filter by selection
  data = data.filter(function(d) { 
          return (d.quantile == quantile) &
          (d.variable == variable) &
          (d.amount == amount) &
          (d.type == type) &
          (d.risk == risk) }); 

  // create visualizable array with only ages and amounts for selected series
  data_filtered = data.map(({ quantile,amount,risk,type,variable, ...item }) => item);
  data_vis = data_filtered[0];
  console.log(data_vis);

  result = [];
  for(i=22;i<101;i++){
    key = i;
    value =parseFloat(data_vis[i]);
    result.push({
            key: key,
            value: value
        });
  }

  // console.log(data_vis);
  console.log(result);

  // Scale the range of the data
  x.domain([d3.min(result, function(d) { return d.key; }), d3.max(result, function(d) { return d.key; })]);
  y.domain([0, d3.max(result, function(d) { return d.value; })]);

  // Add the valueline path.
  svg2.append("path")
      .data([result])
      .attr("class", "line")
      .attr("d", valueline);

  // Add the X Axis
  svg2.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  // Add the Y Axis
  svg2.append("g")
      .call(d3.axisLeft(y));

});

}
</script>

</html>

2 个答案:

答案 0 :(得分:0)

一种可能的解决方法是,一次获取您的数据,两次获取过滤器。

这是我使用 d3v5 创建的fiddle,它使用了 fetch API ,可以更轻松地避免此类问题。通常,在编写Javascript代码时要警惕回调。

此代码的主要变化如下:

d3.csv("<remote csv>").then(function(data) {
getIncome(data);
getPayments(data);
});

其余部分与您的代码非常相似。

编辑:Gerardo Furtado的回答还解决了有关问题原因的重要问题。您还应该遵循该答案中的建议。我的解决方案未解决该答案中解决的问题。相反,我的答案集中在确保执行的预期顺序上。

答案 1 :(得分:0)

关于Java语言的警告:当您这样做时...

variable = 'Income';

...而不是:

var variable = 'Income';

...甚至使用constlet,您的variable是全局变量,也就是说,它不在getIncome()getPayments()内部

结合d3.csv的回调不会立即运行的事实,会发生以下情况:

  1. 您一次调用两个函数:

    getIncome();
    getPayments();
    
  2. getIncome()内,您拥有:

    function getIncome() {
        variable= 'Income';
        //etc...
    

    这使variable成为具有"Income"值的全局变量。

  3. 然后,当涉及到getPayments()时,您将拥有:

    function getPayments() {
        variable= 'Payments';  
        //etc...
    

    现在variable的值为"Payments",但是第一个函数(getIncome())的回调尚未执行

因此,当第一个函数运行时,variable的值为"Payments",并且两个图表都具有相同的路径。

解决方案:请勿创建全局变量,请勿将值分配给未声明的变量。

这里是您的小提琴,只是在每个变量前添加varhttps://jsfiddle.net/qrj803za/3/

另外,还要照顾您在此处创建的其他全局变量(例如resultdata_vis等)