沿着D3 Sankey图中的链接的渐变

Viv*_*idD 14 javascript gradient d3.js sankey-diagram

是一个jsfiddle Sankey diagram:

在此输入图像描述

我试图修改链接的颜色,以便每个链接的颜色实际上是从源节点颜色到其目标节点颜色的渐变.(假设不透明度将保持为0.2或0.5,这取决于鼠标是否在链接上徘徊;因此链接将保持比节点稍微"淡化")

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

在此输入图像描述

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

另外,请注意原始Sankey图中的链接在拖动节点时移动,并且即使在那些暂时状态下也必须显示渐变.一个小问题是链接和节点的透明度以及绘制顺序.我会很感激想法和提示.

Ame*_*aBR 35

@VividD:刚刚看到你的评论,但无论如何我还是完成了.在你自己想出来之前,请随意忽略这一点,但我想确保知道如何去做.另外,这是一个非常常见的问题,非常适合参考.

如何沿着直线定位渐变

需要提醒的人阅读这之后,它只会工作,因为路径几乎是直线,所以线性渐变的外观半体面-路径行程设置为梯度并没有做出与路径渐变曲线!

  1. 在初始化中,<defs>在SVG中创建(定义)元素并将选择保存到变量:

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

    function getGradID(d){return "linkGrad-" + d.source.name + d.target.name;}
    function nodeColor(d) { return d.color = color(d.name.replace(/ .*/, ""));}
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在其中创建<linearGradient>对象选择<defs>并将其连接到链接数据,然后根据源和目标数据对象设置停止偏移和线坐标.

    对于您的示例,如果您只是使所有渐变水平,它可能看起来很好.由于这是方便的默认我认为我们所要做的就是告诉渐变以适应它绘制的路径的大小:

    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) 
              });
    
    Run Code Online (Sandbox Code Playgroud)

    不幸的是,当路径是完全直线时,其边界框不存在(无论笔划宽度有多宽),最终结果是渐变不会被绘制.

    所以我不得不切换到更一般的模式,其中渐变位置和沿源和目标之间的线成角度:

    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 */
    
    Run Code Online (Sandbox Code Playgroud)
  4. 当然,现在渐变是基于坐标系而不是基于路径的长度定义的,你必须在节点移动时更新那些坐标,所以我必须将这些定位语句包装在我可以调用的函数中在dragmove()功能中.

  5. 最后,在创建链接路径时,将其填充设置为url()引用从数据派生的相应唯一渐变ID 的CSS 函数(使用预定义的实用程序函数):

    link.style("stroke", function(d){
        return "url(#" + getGradID(d) + ")";
    })
    
    Run Code Online (Sandbox Code Playgroud)

还有瞧!
Sankey图与数据中的自定义渐变