gpt4 book ai didi

javascript - D3 Sankey 图中链接的梯度

转载 作者:可可西里 更新时间:2023-11-01 01:36:43 27 4
gpt4 key购买 nike

HereSankey 图的jsfiddle:

enter image description here

我正在尝试修改链接的颜色,以便每个链接的颜色实际上是从其源节点颜色到其目标节点颜色的渐变。 (假设不透明度将保持 0.2 或 0.5,具体取决于鼠标是否悬停在链接上;因此链接将保持比节点“浅”一点)

我看了这个不错的,很有启发性的example ,它绘制了这个渐变填充循环:

enter image description here

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

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

最佳答案

@VividD:刚看到你的评论,但我已经快完成了。在您自己弄清楚之前,请随意忽略它,但我想确保也知道如何去做。另外,这是一个非常常见的问题,非常适合作为引用。

如何获得沿直线定位的渐变

With the caveat for anyone reading this later, that it will only work because the paths are almost straight lines, so a linear gradient will look half-decent -- setting a path stroke to a gradient does not make the gradient curve with the path!

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

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

    function getGradID(d){return "linkGrad-" + d.source.name + d.target.name;}
    function nodeColor(d) { return d.color = color(d.name.replace(/ .*/, ""));}
  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)
    });

    不幸的是,当路径是完全直线时,它的边界框不存在(无论笔画宽度有多宽),并且net result is the gradient doesn't get painted .

    所以我不得不切换到更通用的模式,其中渐变沿着源和目标之间的线定位和倾斜:

    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 */
  4. 当然,既然梯度是基于坐标系而不是基于路径的长度定义的,那么只要节点移动就必须更新这些坐标,所以我不得不将这些定位语句包装在我可以在 dragmove() 中调用的函数功能。

  5. 最后,在创建链接路径时,将其填充设置为 CSS url()引用从数据中导出的相应唯一梯度 ID 的函数(使用预定义的效用函数):

    link.style("stroke", function(d){
    return "url(#" + getGradID(d) + ")";
    })

Voila!
Sankey diagram with custom gradients from the data

关于javascript - D3 Sankey 图中链接的梯度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21206081/

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