簡體   English   中英

d3:從2d對象數組中繪制多線折線圖

[英]d3: drawing a multi-line line graph from a 2d array of objects

我正在嘗試在d3中繪制一個多線折線圖,然后在每個刻度線上更新它。 我遇到的問題是我最終得到的錯誤是數據為零的圖表。 我在這里找到了其他答案,但它們都是針對d3的舊版本或者比我更簡單的數據。

我的數據看起來像這樣(顯然是簡化的,但結構是一樣的):

let data = [
  [{name: "a", val: 1}, {name: "b", val: 2}],
  [{name: "a", val: 2}, {name: "b", val: 3}],
  [{name: "a", val: 3}, {name: "b", val: 4}],
  [{name: "a", val: 4}, {name: "b", val: 5}],
]

我想要兩行:每個索引的A值之一和每個索引的B值之一。 關於SO的其他帖子也提出了同樣的問題,但是d3的3.0。

從這個問題,我推斷到以下幾點:

let svg = ...
let g = svg.append("g")...

let line = d3.line()
    .x((d:any, i:number) => x(i))
    .y((d:any) => y(d.value))
g.selectAll(".line")
    .data(data)
    .enter().append("path")
    .attr("class", "line")
    .attr("d", line);

這會在每個tick上拋出一個錯誤: Error: <path> attribute d: Expected number, "MNaN,20Z" ,我並不太驚訝,因為TypeScript也抱怨:

TS2345: Argument of type 'Line<[number, number]>' is not assignable to parameter of type 'ValueFn<SVGPathElement, GraphablePacketCount[], string | number | boolean | null>'.
    Types of parameters 'data' and 'datum' are incompatible.

我試過的其他東西:

for (const datum of data) {
    g.append("svg:line").data(datum)...
}

d3的一般更新模式的線性版本:

let lines = g.selectAll("line").data(data);
lines.enter().append(...);

這只是一個空圖。 在這種情況下, console.log(lines.enter())為我提供數據,它只是不呈現。

我接下來要嘗試什么呢?

您的數據數組具有val字段,但在行的y訪問器中您使用value

但即便如此,您的問題在於您按錯誤的維度切割數據。 將數據綁定到行,因此數據(outter)數組中的每個元素應該是單行的數據,然后內部數組應該是該行的點(因為行生成器接受點數組)。 但是你有其他的方式,因為你首先逐點前進,然后才區分線。

您必須通過在源處調整數據或在綁定之前進行轉換來調整數據。 見下面的例子

 <!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin: 0; position: fixed; top: 0; right: 0; bottom: 0; left: 0; } </style> </head> <body> <script> // Feel free to change or delete any of the code you see in this editor! var svg = d3.select("body").append("svg") .attr("width", 300) .attr("height", 100); let data = [ [{ name: "a", val: 1 }, { name: "b", val: 2 }], [{ name: "a", val: 2 }, { name: "b", val: 3 }], [{ name: "a", val: 3 }, { name: "b", val: 4 }], [{ name: "a", val: 4 }, { name: "b", val: 5 }], ]; var byLineDataMap = data.reduce(function(lineData, point) { point.forEach(function(linePoint) { if (!lineData[linePoint.name]) lineData[linePoint.name] = []; lineData[linePoint.name].push({ val: linePoint.val }); }); return lineData; }, {}); var byLineData = Object.entries(byLineDataMap); /* var byLineData = [ ['a', [{val: 1}, ...]], ['b', [{val: 2}, ...]] ]; */ var x = d3.scaleLinear() .domain([0, 4]) .range([50, 250]); var y = d3.scaleLinear() .domain([1, 5]) .range([80, 20]); var color = d3.scaleOrdinal() .domain(['a', 'b']) .range(['red', 'blue']); var lineGen = d3.line() .x(function(d, i) { return x(i) }) .y(function(d, i) { return y(d.val) }); svg.selectAll('path') .data(byLineData) .enter() .append('path') .style('stroke', function(d) { return color(d[0]); }) .attr('d', function(d) { return lineGen(d[1]); }); </script> </body> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM