Проблема создания нескольких графиков на одной странице - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть две функции, каждая из которых должна рисовать разные диаграммы из одного и того же набора данных в два SVG с атрибутами id one и two соответственно.

Я создал разные переменные для добавления диаграммы к соответствующему 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 голосов
/ 09 ноября 2018

Слово предостережения о Javascript: когда вы делаете это ...

variable = 'Income';

... вместо:

var variable = 'Income';

... или даже используя const или let, ваша 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", и обе диаграммы имеют одинаковый путь.

Решение : не создавать глобальные переменные, не присваивать значение необъявленной переменной.

Вот та же самая скрипка, просто добавляем var перед каждой переменной: https://jsfiddle.net/qrj803za/3/

Кроме того, позаботьтесь о других глобалах, которые вы создаете здесь (например, result, data_vis и т. Д.)

0 голосов
/ 08 ноября 2018

Одним из возможных исправлений является получение ваших данных один раз и фильтра дважды.

Вот скрипка , которую я создаю с использованием d3v5 , которая использует fetch API , что упрощает предотвращение подобных проблем. В общем, будьте осторожны с обратными вызовами при написании кода Javascript.

Основным изменением в этом коде является следующее:

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

Остальное очень похоже на ваш код.

РЕДАКТИРОВАТЬ : Ответ Герардо Фуртадо также затрагивает важную проблему, касающуюся причины проблемы. Вы также должны следовать предложениям в этом ответе. Мое решение оставляет проблему, указанную в этом ответе, нерешенной. Вместо этого мой ответ сфокусирован на обеспечении предполагаемого порядка исполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...