Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/406.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript D3 Sankey图中沿链接的梯度_Javascript_D3.js_Gradient_Sankey Diagram - Fatal编程技术网

Javascript D3 Sankey图中沿链接的梯度

Javascript D3 Sankey图中沿链接的梯度,javascript,d3.js,gradient,sankey-diagram,Javascript,D3.js,Gradient,Sankey Diagram,JSFIDLE是一个Sankey图的中间部分: 我试图修改链接的颜色,使每个链接的颜色实际上是从源节点颜色到目标节点颜色的渐变。(假设不透明度将保持为0.2或0.5,这取决于鼠标是否悬停在链接上;因此链接将保持比节点稍微“苍白”) 我看了一下这个漂亮且有启发性的图,它绘制了这个渐变填充的循环: 但是,我无法将该解决方案集成到我的解决方案中,它对于给定的任务来说太复杂了 另外,请注意,原始Sankey图中的链接在拖动节点时移动,即使在这些临时状态下也必须显示渐变。还有一个小问题是链接和节点的透

JSFIDLE是一个
Sankey图的中间部分

我试图修改链接的颜色,使每个链接的颜色实际上是从源节点颜色到目标节点颜色的渐变。(假设不透明度将保持为0.2或0.5,这取决于鼠标是否悬停在链接上;因此链接将保持比节点稍微“苍白”)

我看了一下这个漂亮且有启发性的图,它绘制了这个渐变填充的循环:

但是,我无法将该解决方案集成到我的解决方案中,它对于给定的任务来说太复杂了

另外,请注意,原始Sankey图中的链接在拖动节点时移动,即使在这些临时状态下也必须显示渐变。还有一个小问题是链接和节点的透明度以及图形的顺序。我希望你能给我一些想法和提示。

@livided:我刚刚看到你的评论,但我已经快做完了。在你自己弄明白之前,请不要介意,但我想确保我也知道如何去做。另外,这是一个非常常见的问题,很好的参考

如何获得沿直线定位的渐变 对于以后阅读本文的人,需要注意的是,它只会起作用,因为路径几乎是直线,所以线性渐变看起来有点像样——将路径笔划设置为渐变不会使渐变与路径成曲线

  • 在初始化过程中,在SVG中创建一个
    (定义)元素,并将选择保存到一个变量:

    var defs = svg.append("defs");
    
  • 定义一个函数,该函数将从链接数据对象为渐变创建唯一的id。为确定节点颜色的函数命名也是一个好主意:

    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()
    函数中调用该函数

  • 最后,在创建链接路径时,将其填充设置为CSS
    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) + ")";
    })