d3js построение неопределенных линейных диаграмм невозможно повторить

#d3.js #linechart

#d3.js #линейная диаграмма

Вопрос:

Я учусь d3js , и мне нужна помощь в создании линейных диаграмм. Я довольно успешно рисую простые объекты и гистограммы. Линейные диаграммы кажутся крутым холмом для подъема.

 const data = [{
    "LINE1": [
      10,
      11,
      12,
      15
    ]
  },
  {
    "LINE2": [
      21,
      22,
      23,
      32
    ]
  },
  {
    "LINE3": [
      11,
      12,
      13,
      15
    ]
  }
]

// set the dimensions and margins of the graph
var margin = {
    top: 50,
    right: 100,
    bottom: 130,
    left: 120
  },
  width = 900 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#ca")
  .append("svg")
  .attr("width", width   margin.left   margin.right)
  .attr("height", height   margin.top   margin.bottom)
  .append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`);

// Add X axis
var x = d3.scaleLinear()
  .domain(d3.extent(data, (d) => d.length))
  .range([0, width]);

svg.append("g")
  .attr("transform", "translate(0,"   height   ")")
  .call(d3.axisBottom(x).ticks(5));

// Add Y axis
// I need help in this area, how can I get the min and max values set in the domain?
var y = d3.scaleLinear()
  .domain([0, d3.max(data, (d) => d.values)])
  .range([height, 0]);

svg.append("g")
  .call(d3.axisLeft(y));

// Draw the line
// I need help in this area, how can I get the lines plotted, js gives error in this!
svg.selectAll(".line")
  .data(data)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("stroke-width", 1.5)
  .attr("d", (d) => {
    console.log(d)
    var k = d3.line()
      .x((d) => x(d))
      .y((d) => y(d))
      (d.values);
    console.log(k);
    return k;
  });  
 <div id="ca">
</div>
<script src="https://d3js.org/d3.v6.min.js"></script>  

Как я могу получить линейные диаграммы, построенные в соответствии с имеющимся у меня форматом данных?

Ответ №1:

Я заставил ваш пример работать, но здесь есть несколько вещей, которые вам нужно знать:

  1. Ваша структура данных была очень хаотичной. Если вы хотите иметь массив объектов в качестве данных, убедитесь, что все объекты имеют одинаковые ключи. Это нормально, если вы используете [{y: [...]}, {y: [...]}] , но [{LINE1: [...]}, {LINE2: [...]}] с этим очень сложно работать. Я изменил ваши данные, чтобы они были больше похожи [[...], [...], [...]] на структуру.

  2. Не создавайте отдельную d3.line для каждой строки, просто создайте ее один раз и вызовите. Это фабрика строк, что означает, что это функция, которая при вызове возвращает строку. Если он не является общим, он может использовать разные домены и диапазоны, что делает диаграмму сложной или даже бесполезной.

  3. Если первый аргумент в функции является d , то второй является i индексом узла в массиве. В этом случае вы используете это, чтобы начать с x=0 и перейти к x=3 . Вы использовали d , чтобы попытаться получить это значение.

  4. Имейте в виду структуру ваших данных. Вы продолжали хотеть получить доступ d.values , но этого никогда не существовало!

 const data = Object.values({
  "LINE1": [
    10,
    11,
    12,
    15
  ],
  "LINE2": [
    21,
    22,
    23,
    32
  ],
  "LINE3": [
    11,
    12,
    13,
    15
  ]
});

var line = d3.line()
  .x((d, i) => x(i))
  .y((d) => y(d));

// set the dimensions and margins of the graph
var margin = {
    top: 50,
    right: 100,
    bottom: 130,
    left: 120
  },
  width = 900 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#ca")
  .append("svg")
  .attr("width", width   margin.left   margin.right)
  .attr("height", height   margin.top   margin.bottom)
  .append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`);

// Add X axis
var x = d3.scaleLinear()
  .domain([0, d3.max(data, (d) => d.length)])
  .range([0, width]);

svg.append("g")
  .attr("transform", "translate(0,"   height   ")")
  .call(d3.axisBottom(x).ticks(5));

// Add Y axis
// I need help in this area, how can I get the min and max values set in the domain?
var y = d3.scaleLinear()
  .domain([0, d3.max(data, (d) => Math.max(...d))])
  .range([height, 0]);

svg.append("g")
  .call(d3.axisLeft(y));

// Draw the line
// I need help in this area, how can I get the lines plotted, js gives error in this!
svg.selectAll(".line")
  .data(data)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("stroke-width", 1.5)
  .attr("d", (d) => line(d));  
 <div id="ca">
</div>
<script src="https://d3js.org/d3.v6.min.js"></script>