简体   繁体   中英

Show tool-tip on links of force directed graph in d3js

I am working on a simple force directed graph as given in This link. It works well but I want to show tool-tip on edges also as it shows on nodes. Whenever I move the mouse on an edge, it shows some tool-tip on the link (data may be retrieved from JSON file). Is there a builtin method or I have to show the div on mouse-over (in this case how to get the position of mouse, where the div would be shown)

  1. Is there a builtin method?

Ans : Yes. There is a built in way. Most HTML elements support the title attribute. When you move the mouse pointer over that element, a little tool-tip is shown for a certain amount of time or until you leave that element.

Demo:

 var w = 500, h = 200 var vis = d3.select("body").append("svg:svg") .attr("width", w) .attr("height", h); var graph = { nodes: [{ name: 'A' }, { name: 'B' }], links: [{ source: 0, target: 1 }] }; var force = d3.layout.force() .nodes(graph.nodes) .links(graph.links) .gravity(.05) .distance(100) .charge(-100) .size([w, h]) .start(); var link = vis.selectAll("line.link") .data(graph.links) .enter().append("svg:line") .attr("class", "link"); link.append("title").text(function(d) { return d.source.name + " -> " + d.target.name }); var node = vis.selectAll("g.node") .data(graph.nodes) .enter().append("svg:g") .attr("class", "node") .call(force.drag); node.append("circle").attr("r", 5); node.append("title").text(function(d) { return d.name }); force.on("tick", function() { link.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; }); node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); }); 
 line { stroke: red; stroke-width: 3; } cicrle { fill: red; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 

  1. or I have to show the div on mouse-over? How to get the position of mouse? Where the div would be shown?

Ans:

If you would like to show a tooltip with html content, you can show a div on mouse-over. You can get the mouse position using d3.mouse method.

Demo:

 var width = 960; var height = 500; var margin = 20; var pad = margin / 2; var color = d3.scale.category20(); var graph = { "nodes": [{ "name": "Myriel", "group": 1 }, { "name": "Napoleon", "group": 1 }, { "name": "Mlle.Baptistine", "group": 1 }, { "name": "Mme.Magloire", "group": 1 }, { "name": "CountessdeLo", "group": 1 }, { "name": "Geborand", "group": 1 }, { "name": "Champtercier", "group": 1 }, { "name": "Cravatte", "group": 1 }, { "name": "Count", "group": 1 }, { "name": "OldMan", "group": 1 }, { "name": "Labarre", "group": 2 }, { "name": "Valjean", "group": 2 }, { "name": "Marguerite", "group": 3 }, { "name": "Mme.deR", "group": 2 }, { "name": "Isabeau", "group": 2 }, { "name": "Gervais", "group": 2 }, { "name": "Tholomyes", "group": 3 }, { "name": "Listolier", "group": 3 }, { "name": "Fameuil", "group": 3 }, { "name": "Blacheville", "group": 3 }, { "name": "Favourite", "group": 3 }, { "name": "Dahlia", "group": 3 }, { "name": "Zephine", "group": 3 }, { "name": "Fantine", "group": 3 }, { "name": "Mme.Thenardier", "group": 4 }, { "name": "Thenardier", "group": 4 }, ], "links": [{ "source": 1, "target": 0, "value": 1 }, { "source": 2, "target": 0, "value": 8 }, { "source": 3, "target": 0, "value": 10 }, { "source": 3, "target": 2, "value": 6 }, { "source": 4, "target": 0, "value": 1 }, { "source": 5, "target": 0, "value": 1 }, { "source": 6, "target": 0, "value": 1 }] }; drawGraph(graph); function drawGraph(graph) { var svg = d3.select("#force").append("svg") .attr("width", width) .attr("height", height); // draw plot background svg.append("rect") .attr("width", width) .attr("height", height) .style("fill", "#eeeeee"); // create an area within svg for plotting graph var plot = svg.append("g") .attr("id", "plot") .attr("transform", "translate(" + pad + ", " + pad + ")"); // https://github.com/mbostock/d3/wiki/Force-Layout#wiki-force var layout = d3.layout.force() .size([width - margin, height - margin]) .charge(-120) .linkDistance(function(d, i) { return (d.source.group == d.target.group) ? 50 : 100; }) .nodes(graph.nodes) .links(graph.links) .start(); drawLinks(graph.links); drawNodes(graph.nodes); // add ability to drag and update layout // https://github.com/mbostock/d3/wiki/Force-Layout#wiki-drag d3.selectAll(".node").call(layout.drag); // https://github.com/mbostock/d3/wiki/Force-Layout#wiki-on layout.on("tick", function() { d3.selectAll(".link") .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; }); d3.selectAll(".node") .attr("cx", function(d) { return dx; }) .attr("cy", function(d) { return dy; }); }); } // Draws nodes on plot function drawNodes(nodes) { // used to assign nodes color by group var color = d3.scale.category20(); // https://github.com/mbostock/d3/wiki/Force-Layout#wiki-nodes d3.select("#plot").selectAll(".node") .data(nodes) .enter() .append("circle") .attr("class", "node") .attr("id", function(d, i) { return d.name; }) .attr("cx", function(d, i) { return dx; }) .attr("cy", function(d, i) { return dy; }) .attr("r", function(d, i) { return 4; }) .style("fill", function(d, i) { return color(d.group); }) .on("mouseover", function(d, i) { var x = d3.mouse(this)[0]; var y = d3.mouse(this)[1]; var tooltip = d3.select("#plot") .append("text") .text(d.name) .attr("x", x) .attr("y", y) //.attr("dy", -r * 2) .attr("id", "tooltip"); }) .on("mouseout", function(d, i) { d3.select("#tooltip").remove(); }); } // Draws edges between nodes function drawLinks(links) { var scale = d3.scale.linear() .domain(d3.extent(links, function(d, i) { return d.value; })) .range([1, 6]); // https://github.com/mbostock/d3/wiki/Force-Layout#wiki-links d3.select("#plot").selectAll(".link") .data(links) .enter() .append("line") .attr("class", "link") .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; }) .style("stroke-width", function(d, i) { return scale(d.value) + "px"; }) .style("stroke-dasharray", function(d, i) { return (d.value <= 1) ? "2, 2" : "none"; }).on("mouseover", function(d, i) { var x = d3.mouse(this)[0]; var y = d3.mouse(this)[1]; var tooltip = d3.select("#plot") .append("text") .text(d.source.name + " -> " + d.target.name) .attr("x", x) .attr("y", y) //.attr("dy", -r * 2) .attr("id", "tooltip"); }) .on("mouseout", function(d, i) { d3.select("#tooltip").remove(); }); } 
 body { font-family: 'Source Sans Pro', sans-serif; font-weight: 300; } b { font-weight: 900; } .outline { fill: none; stroke: #888888; stroke-width: 1px; } #tooltip { font-size: 10pt; font-weight: 900; fill: #000000; stroke: #ffffff; stroke-width: 0.25px; } .node { stroke: #ffffff; stroke-weight: 1px; } .link { fill: none; stroke: #888888; stroke-weight: 1px; stroke-opacity: 0.5; } .highlight { stroke: red; stroke-weight: 4px; stroke-opacity: 1.0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div align="center" id="force"></div> 

You can use the <title> element for line elements in the same way the linked demo does for circle elements. For instance,

link.append("title")
  .text(function(d) { return "This is my title"; });

would create such tooltips in the demo linked. Note that, according to the spec , you should ensure the title element is the first child of the parent.

Also note that this may not be an effective way to communicate with the user; hovering over a line is rather difficult, especially in a moving graph. One potential solution would be to wrap each line in a larger group with an invisible line of larger width, and add the title as the first child of the group, as the title element also works just fine with <g> elements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM