将箭头颜色与D3

时间:2015-10-06 07:47:42

标签: javascript d3.js svg

我正在努力做一件显而易见的事情,即获取有向图表链接的箭头颜色以匹配边缘颜色。令人惊讶的是,我没有找到一个完整的解决方案来做到这一点,虽然this older post似乎是一个很好的起点。如果按照下面的说明调整该解决方案,我会没事的,或者如果有一种更好的方法来创建实现这种效果的箭头,我将非常感激。

首先,我有一个线性渐变颜色函数,可以按照以下属性为边缘着色:

var gradientColor = d3.scale.linear().domain([0,1]).range(["#08519c","#bdd7e7"]);

然后,就像上一篇文章一样,我有一个添加标记的功能:

function marker (color) {
  var reference;
  svg.append("svg:defs").selectAll("marker")
    .data([reference]) 
   .enter().append("svg:marker")    
    .attr("id", String)
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 15)  // This sets how far back it sits, kinda
    .attr("refY", 0)
    .attr("markerWidth", 9)
    .attr("markerHeight", 9)
    .attr("orient", "auto")
    .attr("markerUnits", "userSpaceOnUse")
   .append("svg:path")
    .attr("d", "M0,-5L10,0L0,5")
    .style("fill", color);
  return "url(#" + reference + ")";    };

然后我的链接定义是基于Curved Links example

的链接定义
var link = svg.selectAll(".link")
  .data(bilinks)
  .enter().append("path")
  .attr("class", "link")
  .style("fill", "none")
  .style("opacity", "0.5")    
  .style("stroke-width", "2")  
  .style("stroke", function(d) { return gradientColor(d[3]); } )
  .attr("marker-end", marker( "#FFCC33" ) );

这不符合书面规定;浏览器给了我一个" Uncaught TypeError:无法读取属性' 5'未定义" (其中' d [5]'指的是链接所具有的属性列表中的第五个属性)。在这种情况下,问题显然是将数据函数传递给标记函数。如果我输入静态颜色,如#34;#FFCC33"然后箭头DO改变颜色(现在)。不幸的是发布了这个"标记功能的人#34; 1.5年前的解决方案根本没有包括将颜色传递给标记功能的内容。

我不知道如何正确地提供链接的颜色。理想情况下,我可以使用箭头所附链接颜色的参考,而不是输入相同的颜色函数(因为最终我将根据按钮按下不同的方案着色链接) 。

我创建了一个JS Fiddle,其中包含了查看和解决问题所需的所有内容。目前我将静态颜色传递给标记,但它应该是它所附着的链接的颜色。我还提供了关于正确定位箭头和边缘尾部的另一个问题的功能。

1 个答案:

答案 0 :(得分:5)

我不相信你能够定义一个SVG标记并改变它的颜色。相反,您需要多次定义标记(每种颜色需要使用1个)。最近出现在D3网站上的example很不错。

enter image description here

这种方法的工作方式是,如果有不同的标记,每个标记都有很多,每个标记都定义了标记的颜色。这是所有已定义标记的屏幕截图:

enter image description here

然后这个特定的例子循环路径上的CSS类。每个路径使用的特定颜色标记在CSS类中定义,该类在任何给定时间应用于路径。

我修改了您的示例,为每条路径添加一个新的marker(并在渐变中略微更改了颜色以证明它正常工作)。这就是我所拥有的:



var width = 960,
    height = 500;

var color = d3.scale.category20();
var gradientColor = d3.scale.linear().domain([0, 15]).range(["#ff0000", "#0000ff"]);

var force = d3.layout.force()
    .linkDistance(10)
    .linkStrength(2)
    .size([width, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var defs = svg.append("svg:defs");

d3.json("http://bost.ocks.org/mike/miserables/miserables.json", function (error, graph) {
    if (error) throw error;


    function marker(color) {

        defs.append("svg:marker")
            .attr("id", color.replace("#", ""))
            .attr("viewBox", "0 -5 10 10")
            .attr("refX", 15) // This sets how far back it sits, kinda
            .attr("refY", 0)
            .attr("markerWidth", 9)
            .attr("markerHeight", 9)
            .attr("orient", "auto")
            .attr("markerUnits", "userSpaceOnUse")
            .append("svg:path")
            .attr("d", "M0,-5L10,0L0,5")
            .style("fill", color);
        
        return "url(" + color + ")";
    };

    var nodes = graph.nodes.slice(),
        links = [],
        bilinks = [];

    graph.links.forEach(function (link) {
        var s = nodes[link.source],
            t = nodes[link.target],
            i = {}, // intermediate node
            linkValue = link.value // for transfering value from the links to the bilinks
            ;
        nodes.push(i);
        links.push({
            source: s,
            target: i
        }, {
            source: i,
            target: t
        });
        bilinks.push([s, i, t, linkValue]);
    });

    force.nodes(nodes)
        .links(links)
        .start();

    var link = svg.selectAll(".link")
        .data(bilinks).enter().append("path")
        .attr("class", "link")
        .style("fill", "none")
        .style("opacity", "0.5")
        .style("stroke-width", "2")
        .each(function(d) {
            var color = gradientColor(d[3]);
            console.log(d[3]);
            d3.select(this).style("stroke", color)
                           .attr("marker-end", marker(color));
        });

    var node = svg.selectAll(".node")
        .data(graph.nodes)
        .enter().append("g")
        .attr("class", "node")
        .call(force.drag);

    node.append("circle")
        .attr("r", function (d) {
        return 2 + d.group;
    })
        .style("opacity", 0.5)
        .style("fill", function (d) {
        return color(d.group);
    });

    node.append("title")
        .text(function (d) {
        return d.name;
    });

    force.on("tick", function () {
        link.attr("d", function (d) {
            return "M" + d[0].x + "," + d[0].y + "S" + d[1].x + "," + d[1].y + " " + d[2].x + "," + d[2].y;
        });
        node.attr("transform", function (d) {
            return "translate(" + d.x + "," + d.y + ")";
        });
    });
    });

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;