gpt4 book ai didi

javascript - 将新数据添加到 d3 streamgraph 时的转换

转载 作者:数据小太阳 更新时间:2023-10-29 05:10:33 25 4
gpt4 key购买 nike

我用d3画的流图和官方的例子很像http://bl.ocks.org/mbostock/4060954 :

enter image description here

唯一的区别是我如何用新数据更新它。我不仅想要垂直(y 值)过渡,还想在右侧添加新的数据点。整个图应该在水平方向上压缩

达到预期的结果没有问题,唯一的问题是两种状态之间的转换看起来不像预期的那样。

您可以在 JSfiddle 上找到一个奇怪的过渡效果的最小示例:http://jsfiddle.net/jaYJ9/4/

按更新键看效果

test_data0 = [{"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.0, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.3}, {"0": 0.3, "1": 0.0, "-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.0, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.3}, {"0": 0.3, "1": 0.0, "-1": 0.0}, {"0": 0.3, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.0}]

$('#update').click(function(){
streamed_history(test_data1)
});
var width = 300,
height = 200,
colors = {'0': '#6ff500', '1': '#ffad0a', '-1': '#f90035'},
feedbacks = [-1, 0, 1],
stack = d3.layout.stack();
var svg = d3.select("#timeline").append("svg")
.attr("width", width)
.attr("height", height);
var y = d3.scale.linear()
.domain([0, 1])
.range([height, 0]);

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)
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 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")
.data(layers)
.transition()
.duration(2000)
.attr("d", function (d) {return area(d.layer);});
}

最佳答案

这个问题围绕着这样一个事实,即对于 SVG 动画,您只能将点推到路径的末端。

首先,修复(这仅在图形始终垂直密集并且图形最高的顺序一致的情况下才有效):

...
var area = d3.svg.area().interpolate("basis")
...
.y0(function(d) { return y(null); }) // The null here is super important!
...
...
// Add this function
function fixPath (path) {
var Lidx = path.indexOf('L');
var Cidx = path.slice(Lidx).indexOf('C');
var PCidx = path.slice(0,Lidx).lastIndexOf('C');

var lp = path.substr(PCidx, Lidx-PCidx);
var ss = path.substr(Lidx, Cidx);

return (path.slice(0,Lidx) + lp + ss + path.slice(Lidx));
}
...
svg.selectAll("path")
.data(layers.reverse()) // Gotta reverse the order!
.attr("d", function (d) { return fixPath(area(d.layer)); }) // Have to double up the bottom right corner to avoid artifacts
...
...
d3.selectAll("path")
.data(layers)
.attr("d", function (d) { return fixPath(area(d.layer)); }) // When updating too!
...

这里的工作示例:http://jsfiddle.net/f5JSR/2/

现在,解释...

图表中的每个色带都是一条闭合路径,d3.js 构建它们以使这些色带中没有一个相互重叠。问题是,这意味着这些路径中的每一个都从左下角开始,并一直循环回到自身。当您在这些路径上添加一个新点时,您是在末尾添加它,它会逆时针插入路径的其余部分(创建那种奇怪的动画效果)。

我最初尝试使用 SVG 裁剪和 fill-rule: evenodd 属性来解决这个问题,但似乎要使用裁剪你必须创建复合路径,并且添加新点会将它们推到最后这条复合路径的一部分(例如,您不能将一个点推到复合路径的第一条路径上),所以问题仍然存在。

相反,此解决方案摒弃了 d3.js 的巧妙之处,而是让您的所有色带扩展到图表的底部(这就是 y(null); 行所做的)。然后它对路径进行排序,以便首先绘制最高的路径。如果一个图的高度低于另一个图的高度,这种方法就会失效。

最后,当点被推到右下角时,可能会出现一些奇怪的伪影。为了解决这个问题,我使用 fixPath 函数将右下角的点数加倍。

无论如何,此解决方案适用于您的示例案例。我希望这会有所帮助。

关于javascript - 将新数据添加到 d3 streamgraph 时的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15296640/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com