另一个D3.js noob在这里。
我开始编辑来自http://bl.ocks.org/mbostock/4060954的库存流图示例。
我看过几个类似的问题,例如this,this和this,但我似乎无法找到我的错误。
我有两个json模拟数据,layers0和layers1(源自上面的一个示例,来自this fiddle)。通过更改我的数据,我可以毫无问题地绘制这两个:
svg.selectAll("path")
.data(layers0/1) #layers0 or layers1, both work
.enter().append("path")
.attr("d", function(d) { return area(d.values); })
.style("fill", function() { return color(Math.random()); });
然而,当我尝试在这两个图之间创建一个过渡时,原始图消失了,我留下了一个空的空间:
function transition() {
d3.selectAll("path")
.data(layers1/0) #the alternate (or same) one from the function above
.transition()
.duration(500)
.attr("d", area);
}
最终我想要很多按钮,而transition
应该在它们之间移动,例如在this example中,但是现在我只想在两个数据集之间移动。
答案 0 :(得分:2)
好吧,我找到了一个有效的解决方案,尽管我还没有完全理解它。解决方案主要是从this fiddle复制的。我将指出示例代码和必须提供的代码之间的差异(如果有人可以解释为什么,这将是很好的)它的工作。
我会发布我的整个代码给任何发现D3令人困惑的新手。
HTML:(我正在处理金字塔应用程序,因此脚本会在头部导入)
<head>
<title>
Graph
</title>
<link rel="stylesheet" type="text/css" href="${request.static_url('monitor:static/css/graph.css')}"/>
<script type="text/javascript" src="${request.static_url('monitor:static/jquery-ui-1.10.3/jquery-1.9.1.js')}"></script>
<script type="text/javascript" src="${request.static_url('monitor:static/jquery-ui-1.10.3/ui/jquery-ui.js')}"></script>
<script type="text/javascript" src="${request.static_url('monitor:static/D3/d3.min.js')}"></script>
<script type="text/javascript" src="${request.static_url('monitor:static/js/graph.js')}"></script>
</head>
<body>
<body onload="graphplot()">
<h4 id="Heading">Streamgraph</h4>
<div id="graph_area"></div>
</body>
然后这是我的graph.js:
function graphplot(){
test_data0 = [{"0": 0.2, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.6, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.6}, {"0": 0.3, "1": 0.0, "-1": 0.1}, {"0": 0.0, "1": 0.2, "-1": 0.3}, {"0": 0.3, "1": 0.5, "-1": 0.0}, {"0": 0.3, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.0}]
test_data1 = [{"0": 0.0, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.6, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.6}, {"0": 0.3, "1": 0.3, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.3}, {"0": 0.3, "1": 0.1, "-1": 0.6}, {"0": 0.3, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.0}]
var width = $("#graph_area").width(),
height = 500;
var toggle = 0; //just so that the animation toggles between these two data
$("#graph_area").click(function(){
console.log('test')
if (toggle == 0){
streamed_history(test_data1)
toggle = 1;
}else {
streamed_history(test_data0)
toggle=0;
}
});
var colors = {'0': '#6ff500', '1': '#ffad0a', '-1': '#f90035'}, //colours for the three layers; no longer random
feedbacks = [-1, 0, 1],
stack = d3.layout.stack().offset("wiggle"); //the plot sits on its base without wiggle
//.values(function(d) { return d.values; }); --->removed. Throws: TypeError: t is undefined
var svg = d3.select("#graph_area").append("svg")
.attr("width", width)
.attr("height", height);
streamed_history(test_data0)
function streamed_history(data) {
data_array = feedbacks.map(function (f) {
return data.map(function(element, i) { return {x: i, y: element[f]}; })
}),
layers = stack(data_array) //--->No nest.entries. And the below code for only one layers variable
layers = feedbacks.map(function (f, i) {
return {layer: layers[i], feedback: f, color: colors[f]}
})
var x = d3.scale.linear()
.domain([0, data.length - 1])
.range([0, width]);
var y = d3.scale.linear()
.domain([0,1]) //--->coplicated thing removed. It just needs to be:([0, max of data])
.range([height, 0]);
var area = d3.svg.area().interpolate("basis")
.x(function(d) { return x(d.x); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
//enter
svg.selectAll("path")
.data(layers)
.enter().append("path")
.attr("d", function (d) {return area(d.layer);})
.style("fill", function(d) { return d.color; });
//update
d3.selectAll("path") //this effectively replaces transition(), since now each dataset is plotted independently with the duration of transition defined here.
.data(layers)
.transition()
.duration(500)
.attr("d", function (d) {return area(d.layer);});
}
}//end graphplot
graphplot()
希望这有助于将来的任何人!
答案 1 :(得分:0)
我试图重现你在这里要求的内容:
<button class="button1" onclick="transition()">Transition 1</button>
<button class="button2" onclick="transition2()">Transition 2</button>
<script>
var n = 20, // number of layers
m = 200, // number of samples per layer
stack = d3.layout.stack().offset("wiggle"),
layers0 = stack(d3.range(n).map(function() { return bumpLayer(m); })),
layers1 = stack(d3.range(n).map(function() { return bumpLayer(m); }));
var width = 960,
height = 500;
var x = d3.scale.linear()
.domain([0, m - 1])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(layers0.concat(layers1), function(layer) {
return d3.max(layer, function(d) { return d.y0 + d.y; }); })])
.range([height, 0]);
var color = d3.scale.linear()
.range(["#aad", "#556"]);
var area = d3.svg.area()
.x(function(d) { return x(d.x); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("path")
.data(layers0)
.enter().append("path")
.attr("d", area)
.style("fill", function() { return color(Math.random()); });
function transition() {
d3.selectAll("path")
.data(layers1)
.transition()
.duration(2500)
.attr("d", area);
}
function transition2() {
d3.selectAll("path")
.data(layers0)
.transition()
.duration(2500)
.attr("d", area);
}
// Inspired by Lee Byron's test data generator.
function bumpLayer(n) {
function bump(a) {
var x = 1 / (.1 + Math.random()),
y = 2 * Math.random() - .5,
z = 10 / (.1 + Math.random());
for (var i = 0; i < n; i++) {
var w = (i / n - y) * z;
a[i] += x * Math.exp(-w * w);
}
}
var a = [], i;
for (i = 0; i < n; ++i) a[i] = 0;
for (i = 0; i < 5; ++i) bump(a);
return a.map(function(d, i) { return {x: i, y: Math.max(0, d)}; });
}
</script>
我使用了相同的示例,并且代码原则上有效,可能还有其他一些你已经实现的东西,比如更多的html,或者数据集中有些错误?或者我可能没有理解你的问题...