-1

我正在尝试在力有向图上实现标记边缘。

我使用的例子可以在这里找到。

示例中的相关代码位在此处给出。

我的代码如下:

<style>
.node {
    stroke: #fff;
    stroke-width: 0.5px;
}

.node text {
    pointer-events: none;
    font: 15px helvetica;
}

.link {
    fill: none;
    stroke: #bbb;
    stroke-width: 3.0px;
    opacity: 0.5;
}

.highlight {
    stroke: #259359;
}

</style>
<body>
<script src= "//d3js.org/d3.v3.min.js" > </script> 
<script>

    var width = 700,
        height = 550;


    var color = d3.scale.category20();

    var force = d3.layout.force()
        .linkStrength(1)
        .distance(0.01)
        .gravity(0.2)
        .charge(-500)
        .size([width, height]);

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);
    svg.append("defs").selectAll("marker")
        .data(["end"]) // Different link/path types can be defined here
        .enter().append("marker") // This section adds in the arrows
        .attr("id", String)
        .attr("viewBox", "0 -5 10 10")
        .attr("refX", 16)
        .attr("refY", 0)
        .attr("markerWidth", 3)
        .attr("markerHeight", 3)
        .attr("orient", "auto")
        .append("path")
        .attr("d", "M0,-5L10,0L0,5")
        .style("stroke", "#bbb");


    d3.json("fg.json", function(error, graph) {
        if (error) throw error;


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

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

        force
            .nodes(nodes)
            .links(links)
            .size([width, height])
            .start();

        var link = svg.selectAll(".link")
            .data(bilinks)
            .enter().append("path")
            .attr("class", "link")
            .style("marker-end", "url(#end)")
            .on("mouseover", function() {
                d3.select(d3.event.target).classed("highlight", true);
            })
            .on("mouseout", function() {
                d3.select(d3.event.target).classed("highlight", false);
            });

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

        node.append("circle")
            .attr("r", 8)
            .style("fill", function(d) {
                return color(d.group);
            })
        node.append("text")
            .attr("dx", 15)
            .attr("dy", ".40em")
            .text(function(d) {
                return d.name
            })
            .style("stroke", "gray");


        //

        var padding = 30, // separation between circles
            radius = 1;

        function collide(alpha) {
            var quadtree = d3.geom.quadtree(graph.nodes);
            return function(d) {
                var rb = 2 * radius + padding,
                    nx1 = d.x - rb,
                    nx2 = d.x + rb,
                    ny1 = d.y - rb,
                    ny2 = d.y + rb;
                quadtree.visit(function(quad, x1, y1, x2, y2) {
                    if (quad.point && (quad.point !== d)) {
                        var x = d.x - quad.point.x,
                            y = d.y - quad.point.y,
                            l = Math.sqrt(x * x + y * y);
                        if (l < rb) {
                            l = (l - rb) / l * alpha;
                            d.x -= x *= l;
                            d.y -= y *= l;
                            quad.point.x += x;
                            quad.point.y += y;
                        }
                    }
                    return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
                });
            };
        }

    var edgepaths = svg.selectAll(".edgepath")
        .data(graph.links)
        .enter()
        .append('path')
        .attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
               'class':'edgepath',
               'fill-opacity':0,
               'stroke-opacity':0,
               'fill':'blue',
               'stroke':'red',
               'id':function(d,i) {return 'edgepath'+i}})
        .style("pointer-events", "none");

    var edgelabels = svg.selectAll(".edgelabel")
        .data(graph.links)
        .enter()
        .append('text')
        .style("pointer-events", "none")
        .attr({'class':'edgelabel',
               'id':function(d,i){return 'edgelabel'+i},
               'dx':80,
               'dy':0,
               'font-size':10,
               'fill':'#aaa'});

    edgelabels.append('textPath')
        .attr('xlink:href',function(d,i) {return '#edgepath'+i})
        .style("pointer-events", "none")
        .text(function(d,i){return 'label '+i});

        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 + ")";
            });

            edgepaths.attr('d', function(d) { var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y;
                                               return path});       

            edgelabels.attr('transform',function(d,i){
                if (d.target.x<d.source.x){
                    bbox = this.getBBox();
                    rx = bbox.x+bbox.width/2;
                    ry = bbox.y+bbox.height/2;
                    return 'rotate(180 '+rx+' '+ry+')';
                    }
                else {
                    return 'rotate(0)';
                    }
            });
           node.each(collide(0.5));
        });


    });

</script>

数据如下:

    {
      "nodes":[
        {"name":"alkene","group":1},
        {"name":"alkane","group":1},
        {"name":"halogenoalkane","group":2},
        {"name":"dihalogenoalkane","group":2},
        {"name":"amine","group":3},
        {"name":"alcohol","group":4},
        {"name":"ketone","group":5},
        {"name":"aldehyde","group":6},
        {"name":"hydroxynitrile","group":7},
        {"name":"ester","group":8},
        {"name":"carboxylic acid","group":9},
        {"name":"acyl chloride","group":9},
        {"name":"amide","group":10},
        {"name":"nitrile","group":11}
      ],
      "links":[
        {"source":0,"target":2,"value":2},
        {"source":0,"target":1,"value":1},
        {"source":2,"target":0,"value":8},
        {"source":0,"target":3,"value":10},
        {"source":2,"target":4,"value":10},
        {"source":5,"target":2,"value":1},
        {"source":2,"target":5,"value":1},
        {"source":6,"target":5,"value":1},
        {"source":5,"target":6,"value":1},
        {"source":7,"target":5,"value":1},
        {"source":5,"target":7,"value":1},
        {"source":7,"target":8,"value":2},
        {"source":7,"target":10,"value":1},
        {"source":10,"target":7,"value":1},
        {"source":5,"target":9,"value":3},
        {"source":10,"target":9,"value":3},
        {"source":13,"target":10,"value":5},
        {"source":10,"target":11,"value":1},
        {"source":11,"target":10,"value":1},
        {"source":11,"target":12,"value":1}
      ]
    }

不幸的是,图表上的标签不可见。

最终目标是在每条边上显示相应的值“值”。

你能告诉我我做错了什么吗?

感谢您的时间。

更新

通过涂底液成功地将标签添加到边缘

"M" + d[0].x + "," + d[0].y + "S" + d[1].x + "," + d[1].y + " " + d[2].x + "," + d[2].y

为了

'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y

但是,问题仍然存在:如何添加“值”数据而不是标签“标签 i”?此外,它们在鼠标悬停时的外观如何实现?

更新二

通过为边缘标签的 textPath 定义 .data(graph.links) 然后返回 d.value 来显示“值”数据。你能告诉我鼠标悬停是如何实现的吗?如果每条边的“值”数据只能在悬停时看到,那就太好了。谢谢!

4

1 回答 1

0

从这个例子:http: //jsfiddle.net/7HZcR/3/

我创建了相同的视图,但在这里使用您的数据:http: //jsfiddle.net/thatOneGuy/7HZcR/515/

所以你需要实现箭头。

您以前所拥有的,您无法记录数据,mouseover因为您带来的数据不包含它。

所以在这个我已经把数据带到了这样的地方:

var links = graph.links;

将其设置为您的数据,但由于它只有索引作为源和目标,您需要将节点附加到源和目标,以便正确定位:

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});

现在带回的数据将类似于:

{
   source : someNode,
   target : someNode,
   value : linkValue
}

因此,我创建了一个文本输出来确定将值放在链接上的位置会很困难,因为您必须计算出曲线等:

var textOutput = svg.append('text').attr('class', 'textOutput')
.attr("transform","translate(50, 100)"); 

所以mouseover设置 textOutput :

.on('mouseover', function(d){
    console.log(d);
    d3.select(this).style('stroke', 'red').style('stroke-width', '5')
    textOutput.text('LINK VALUE : ' + d.value);
    })
     .on('mouseout', function(d){ 
    d3.select(this).style('stroke', '#666') .style('stroke-width', '1')
    });

希望有帮助:)

于 2016-06-08T08:56:12.757 回答