如何在d3.js中访问多维数组中的数据?
我使用一维数组创建了这个迷你图。 但是当我想用多维数组创建更多的迷你图时呢。
我有这个效果
var canvasWidth = 200,
canvasHeight = 150;
var pathData = [
{ "x": 0, "y": 50},
{ "x": 20, "y": 20},
{ "x": 60, "y": 40},
{ "x": 80, "y": 30},
{ "x": 120, "y": 90},
{ "x": 150, "y": 70},
{ "x": 180, "y": 30},
{ "x": 190, "y": 90},
];
var widthScale = d3.scaleLinear()
.domain([0, 190])
.range([0, canvasWidth - 30]);
var heightScale = d3.scaleLinear()
.domain([0, 90])
.range([0, canvasHeight - 10]);
// Canvas
var canvas = d3.select("body")
.append("svg")
.attr("width", canvasWidth)
.attr("height", canvasHeight)
.append("g")
.attr("transform","translate(20)");
// _+_+_+_+_+_+_+_+ Basic of Data --> SVG Path _+_+_+_+_+_+_+_+ //
// Create accessor function
var pathFunction = d3.line()
.x(function(d) { return widthScale(d.x); })
.y(function(d) { return heightScale(d.y); })
.curve(d3.curveCatmullRom);
// Create <path> and append accessor function
var path = canvas.append("path")
.attr("d", pathFunction(pathData))
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("fill", "none");
// Add data points
var circles = canvas.selectAll("circle")
.data(pathData)
.enter()
.append("circle")
.attr("cx", function(d) { return widthScale(d.x) })
.attr("cy", function(d) { return heightScale(d.y) })
.attr("fill", "black")
.attr("r", 4);
这是因为我不能在每个迷你图中添加圆圈而被卡住了 - “
var canvasWidth = 200,
canvasHeight = 150;
var pathData = [
[
{ "x": 0, "y": 50}, { "x": 20, "y": 20},
{ "x": 60, "y": 40}, { "x": 80, "y": 30},
{ "x": 120, "y": 90}, { "x": 150, "y": 70},
{ "x": 180, "y": 30}, { "x": 190, "y": 90},
],
[
{ "x": 0, "y": 90}, { "x": 20, "y": 20},
{ "x": 30, "y": 80}, { "x": 80, "y": 30},
{ "x": 120, "y": 90}, { "x": 150, "y": 70},
{ "x": 180, "y": 30}, { "x": 190, "y": 90},
],
[
{ "x": 0, "y": 40}, { "x": 20, "y": 20},
{ "x": 30, "y": 80}, { "x": 80, "y": 30},
{ "x": 120, "y": 90}, { "x": 150, "y": 70},
{ "x": 180, "y": 30}, { "x": 190, "y": 90},
]
];
var widthScale = d3.scaleLinear()
.domain([0, 190])
.range([0, canvasWidth - 30]);
var heightScale = d3.scaleLinear()
.domain([0, 90])
.range([0, canvasHeight - 10]);
// Canvas
var container = d3.select(".main-container")
// Create accessor function
var pathFunction = d3.line()
.x(function(d) { return widthScale(d.x); })
.y(function(d) { return heightScale(d.y); })
.curve(d3.curveCatmullRom);
var canvas = container.selectAll("svg")
.data(pathData)
.enter()
.append("svg")
.attr("width", canvasWidth)
.attr("height", canvasHeight)
.append("g")
.attr("transform","translate(20)");
var sparklines = canvas.append("path")
.attr("d", pathFunction)
.attr("stroke", "#19ff9f")
.attr("stroke-width", 2)
.attr("fill","none");
var circles = canvas.selectAll("circle")
.data(pathData)
.enter()
.append("circle")
.attr("cx", function(d,i) { return widthScale(d.x); })
.attr("cy", function(d,i) { return widthScale(d.y); })
.attr("fill", "black")
.attr("r", 3);
`
CX和CY位置是NaN。而且只有3个圆圈,而不是8个数组长度(http://prntscr.com/edp7hq)
答案 0 :(得分:1)
您只需要进行一次修改:
由于您有3个内部数组,因此每个SVG都有一个绑定为数据的数组。所以,当谈到附加圈子时,而不是......
var circles = canvas.selectAll("circle")
.data(pathData)
.enter()
.append("circle")
...,它指向整个数据数组,它应该是......
var circles = canvas.selectAll("circle")
.data(d => d)
.enter()
.append("circle")
...使内部数组(即绑定到每个SVG的数据)成为每组圆的数据数组。
以下是仅使用该修改的工作代码(同样,您在heightScale
上输入错误信息):
var canvasWidth = 200,
canvasHeight = 150;
var pathData = [
[
{ "x": 0, "y": 50}, { "x": 20, "y": 20},
{ "x": 60, "y": 40}, { "x": 80, "y": 30},
{ "x": 120, "y": 90}, { "x": 150, "y": 70},
{ "x": 180, "y": 30}, { "x": 190, "y": 90},
],
[
{ "x": 0, "y": 90}, { "x": 20, "y": 20},
{ "x": 30, "y": 80}, { "x": 80, "y": 30},
{ "x": 120, "y": 90}, { "x": 150, "y": 70},
{ "x": 180, "y": 30}, { "x": 190, "y": 90},
],
[
{ "x": 0, "y": 40}, { "x": 20, "y": 20},
{ "x": 30, "y": 80}, { "x": 80, "y": 30},
{ "x": 120, "y": 90}, { "x": 150, "y": 70},
{ "x": 180, "y": 30}, { "x": 190, "y": 90},
]
];
var widthScale = d3.scaleLinear()
.domain([0, 190])
.range([0, canvasWidth - 30]);
var heightScale = d3.scaleLinear()
.domain([0, 90])
.range([0, canvasHeight - 10]);
// Canvas
var container = d3.select("body")
// Create accessor function
var pathFunction = d3.line()
.x(function(d) { return widthScale(d.x); })
.y(function(d) { return heightScale(d.y); })
.curve(d3.curveCatmullRom);
var canvas = container.selectAll("svg")
.data(pathData)
.enter()
.append("svg")
.attr("width", canvasWidth)
.attr("height", canvasHeight)
.append("g")
.attr("transform","translate(20)");
var sparklines = canvas.append("path")
.attr("d", pathFunction)
.attr("stroke", "#19ff9f")
.attr("stroke-width", 2)
.attr("fill","none");
var circles = canvas.selectAll("circle")
.data(d=>d)
.enter()
.append("circle")
.attr("cx", function(d,i) { return widthScale(d.x); })
.attr("cy", function(d,i) { return heightScale(d.y); })
.attr("fill", "black")
.attr("r", 3);
<script src="https://d3js.org/d3.v4.min.js"></script>
答案 1 :(得分:0)
我发现检查此类问题的一种有用方法是将“d”值记录到控制台:
.attr("cx", function(d,i) { console.log(d); return widthScale(d.x) })
这可能会突出显示,因为您现在使用的是多维数组,绑定到您的圆元素的数据不再能让您立即访问数据点。以下内容可能会起作用:
.attr("cx", function(d,i) { return widthScale(d[i].x) })