Javascript D3 Sankey图中沿链接的梯度
JSFIDLE是一个Javascript D3 Sankey图中沿链接的梯度,javascript,d3.js,gradient,sankey-diagram,Javascript,D3.js,Gradient,Sankey Diagram,JSFIDLE是一个Sankey图的中间部分: 我试图修改链接的颜色,使每个链接的颜色实际上是从源节点颜色到目标节点颜色的渐变。(假设不透明度将保持为0.2或0.5,这取决于鼠标是否悬停在链接上;因此链接将保持比节点稍微“苍白”) 我看了一下这个漂亮且有启发性的图,它绘制了这个渐变填充的循环: 但是,我无法将该解决方案集成到我的解决方案中,它对于给定的任务来说太复杂了 另外,请注意,原始Sankey图中的链接在拖动节点时移动,即使在这些临时状态下也必须显示渐变。还有一个小问题是链接和节点的透
Sankey图的中间部分
:
我试图修改链接的颜色,使每个链接的颜色实际上是从源节点颜色到目标节点颜色的渐变。(假设不透明度将保持为0.2或0.5,这取决于鼠标是否悬停在链接上;因此链接将保持比节点稍微“苍白”)
我看了一下这个漂亮且有启发性的图,它绘制了这个渐变填充的循环:
但是,我无法将该解决方案集成到我的解决方案中,它对于给定的任务来说太复杂了
另外,请注意,原始Sankey图中的链接在拖动节点时移动,即使在这些临时状态下也必须显示渐变。还有一个小问题是链接和节点的透明度以及图形的顺序。我希望你能给我一些想法和提示。@livided:我刚刚看到你的评论,但我已经快做完了。在你自己弄明白之前,请不要介意,但我想确保我也知道如何去做。另外,这是一个非常常见的问题,很好的参考
如何获得沿直线定位的渐变
对于以后阅读本文的人,需要注意的是,它只会起作用,因为路径几乎是直线,所以线性渐变看起来有点像样——将路径笔划设置为渐变不会使渐变与路径成曲线强>
(定义)元素,并将选择保存到一个变量:
var defs = svg.append("defs");
function getGradID(d){return "linkGrad-" + d.source.name + d.target.name;}
function nodeColor(d) { return d.color = color(d.name.replace(/ .*/, ""));}
中创建对象选择并将其连接到链接数据,然后根据源和目标数据对象设置停止偏移和线坐标
对于您的示例,如果您只是将所有渐变设置为水平,它可能看起来会很好。因为这是默认设置,我想我们所要做的就是告诉渐变,使其适合正在绘制的路径的大小:
var grads = defs.selectAll("linearGradient")
.data(graph.links, getLinkID);
grads.enter().append("linearGradient")
.attr("id", getGradID)
.attr("gradientUnits", "objectBoundingBox"); //stretch to fit
grads.html("") //erase any existing <stop> elements on update
.append("stop")
.attr("offset", "0%")
.attr("stop-color", function(d){
return nodeColor( (d.source.x <= d.target.x)? d.source: d.target)
});
grads.append("stop")
.attr("offset", "100%")
.attr("stop-color", function(d){
return nodeColor( (d.source.x > d.target.x)? d.source: d.target)
});
dragmove()
函数中调用该函数url()
函数,该函数引用从数据派生的相应唯一渐变id(使用预定义的实用程序函数):
哦,我开始讨厌迈克·博斯托克的例子了。它看起来很漂亮,但它的下面乱七八糟,不是你想在数据可视化中使用的东西,更不用说交互式的了。由于(a)您对d3非常满意,(b)您的路径几乎是水平线,不会扭曲,因此您应该仍然能够为每个路径创建自定义渐变。将
gradientUnits
设置为objectBoundingBox
,它应该可以根据移动节点进行调整。@AmeliaBR,我觉得您的提示是正确的。我会尝试一些东西,如果我有一些结果就会回来。谢谢!实际上,我一直想写一个这样的例子。我对我链接到的另一个问题的“对不起,这太难了”的回答很不满意,并且一直在困惑,最终想出了使用d3创建自定义定位渐变的想法。这实际上是一个很好的例子,因为每个链接都有自定义颜色,所以您必须创建单独的渐变。相比之下,如果您有一个包含数百个链接的节点图,并且希望使用渐变来显示源与目标,那么这种方法会创建大量额外的DOM内容。另一个注意事项是:如果有人使用“objectBoundingBox”方法,移动节点后,您仍需要检查是否需要反转渐变颜色,这取决于源或目标是在左侧还是右侧。我正在使用自定义颜色来使用此代码为rect着色:但是渐变停止工作。你能帮忙吗?
grads.enter().append("linearGradient")
.attr("id", getGradID)
.attr("gradientUnits", "userSpaceOnUse");
grads.attr("x1", function(d){return d.source.x;})
.attr("y1", function(d){return d.source.y;})
.attr("x2", function(d){return d.target.x;})
.attr("y2", function(d){return d.target.y;});
/* and the stops set as before */
link.style("stroke", function(d){
return "url(#" + getGradID(d) + ")";
})