[英]Dynamically generating multiple d3 svg graphs
I've got an array of objects called graphData
(size varies). 我有一个名为
graphData
的对象数组(大小不一)。 Each element contains all the information required to create a d3 graph, and I am able to successfully draw the graphs if I access graphData
elements by hardcoding (ie graphdata[0]
, graphdata[1]
etc). 每个元素都包含创建d3图形所需的所有信息,如果我通过硬编码访问
graphData
元素(即graphdata[0]
, graphdata[1]
等),我能够成功绘制图形。
The problem comes when I attempt to use a for loop to generate one graph for each of the elements. 当我尝试使用for循环为每个元素生成一个图时,问题就来了。 Looked around stackoverflow and the web, but the solutions are all about generating a fixed number of multiple graphs, not generating multiple graphs dynamically.
看看stackoverflow和web,但解决方案都是关于生成固定数量的多个图,而不是动态生成多个图。
Below is my working code for generating one graph. 下面是我生成一个图表的工作代码。 What is the recommended way to generate x number of graphs automatically?
什么是自动生成x个图形的推荐方法?
var graphData = data.graph;
var RADIUS = 15;
var edgeData = graphData[0].edges;
var nodeData = graphData[0].nodes;
var stageNum = graphData[0].stage;
var xScale = d3.scale.linear()
.domain([d3.min(edgeData, function (d) {
return d.start[0];
}),
d3.max(edgeData, function (d) {
return d.start[0];
})])
.range([50, w - 100]);
var yScale = d3.scale.linear()
.domain([d3.min(edgeData, function (d) {
return d.start[1];
}),
d3.max(edgeData, function (d) {
return d.start[1];
})])
.range([50, h - 100]);
var rScale = d3.scale.linear()
.domain([0, d3.max(edgeData, function (d) {
return d.start[1];
})])
.range([14, 17]);
// already have divs with classes stage1, stage2... created.
var svg = d3.select(".stage" + stageNum).append("svg")
.attr({"width": w, "height": h})
.style("border", "1px solid black");
var elemEdge = svg.selectAll("line")
.data(edgeData)
.enter();
var edges = elemEdge.append("line")
.attr("x1", function (d) {
return xScale(d.start[0]);
})
.attr("y1", function (d) {
return yScale(d.start[1]);
})
.attr("x2", function (d) {
return xScale(d.end[0]);
})
.attr("y2", function (d) {
return yScale(d.end[1]);
})
.attr("stroke-width", 2)
.attr("stroke", "black");
var elemNode = svg.selectAll("circle")
.data(nodeData)
.enter();
var nodes = elemNode.append("circle")
.attr("cx", function (d) {
return xScale(parseInt(d.x));
})
.attr("cy", function (d) {
return yScale(parseInt(d.y));
})
.attr({"r": rScale(RADIUS)})
.style("fill", "yellow")
.style("stroke", "black");
Mike Bostock recommends implementing charts as reusable closures with methods . Mike Bostock建议使用方法将图表实现为可重复使用的闭包 。 This would be an ideal implementation in your case as you want to have
在您的情况下,这将是您想要的理想实现
In broad strokes, what you want to do is wrap your code above into a function in very much the same way Mike describes in the post above, and then have data
be an attribute of your closure. 粗略地说,你想要做的是将上面的代码包装到一个函数中,就像Mike在上面的帖子中描述的那样,然后将
data
作为闭包的属性。 So here is some badly hacked code: 所以这里有一些严重被黑的代码:
// your implementation here
var chart = function(){...}
var graphData = d3.json('my/graphdata.json', function(error, data){
// now you have your data
});
// let's say you have a div called graphs
var myGraphs = d3.select('.graphs')
.data(graphData)
.enter()
.append('g')
//now you have g elements for each of your datums in the graphData array
//we use the saved selection above and call the chart function on each of the elements in the selection
myGraphs.call(chart);
//note that internally in your `chart` closure, you have to take in a selection
//object and process it(data is already bound to each of your selections from above):
function chart(selection) {
selection.each(function(data) {
//...
Here is some more good reading on the topic . 这是关于这个主题的一些更好的阅读 。
Well you can try the following approach. 那么你可以尝试以下方法。
var graphData = data.graph;
//forEach will return each element for the callback, you can then make use of the e1 to draw the graph.
graphData.forEach(function(e1){
//graph code goes here.
});
providing this as your source array 提供此作为您的源数组
//it's just a single circle in 3, 4
var stuff = [3, 4];
var source = [ [stuff, stuff], [stuff] ];
a bit of Array stuff 一点数组的东西
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
Array.prototype.min = function() {
return Math.min.apply(null, this);
};
setup: 建立:
var dim = [];
source.forEach(function(elem){
elem.forEach(function(circle){
dim.push(circle.min());
dim.push(circle.max());
});
});
var min = dim.min();
var max = dim.max();
var x = d3.scale.linear()
.domain([min, max])
.scale([yourscale]);
var y = d3.scale.linear()
.domain([min, max])
.scale([yourscale]);
d3.select('body').selectAll('div')
.data(source) //first step: a div with an svg foreach array in your array
.enter()
.append('div')
.append('svg')
.selectAll('circle') //second step: a circle in the svg for each item in your array
.data(function(d){
return d; //returns one of the [stuff] arrays
}).enter()
.append('circle')
.attr('r', 5)
.attr('cx', function(d){
return x(d[0]);
})
.attr('cy', function(d){
return y(d[1]);
})
.style('fill','blue');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.