Created
February 21, 2016 02:32
-
-
Save Cosxin/0600c9f986dc91acdcef to your computer and use it in GitHub Desktop.
force layout with tooltip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.link { | |
fill: none; | |
stroke: #666; | |
stroke-width: 1.5px; | |
} | |
path.link.suit { | |
stroke:red; | |
} | |
path.link.licensing { | |
stroke:blue | |
; | |
} | |
path.link.resolved { | |
stroke:green; | |
} | |
circle { | |
fill: #ccc; | |
stroke: #333; | |
stroke-width: 1.5px; | |
} | |
.node.fixed { | |
fill: #f00; | |
} | |
text { | |
font: 10px sans-serif; | |
pointer-events: none; | |
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff; | |
} | |
div.d3-tip { | |
line-height: 1; | |
font-weight: bold; | |
padding: 12px; | |
background: #001; | |
color: #F00; | |
border-radius: 2px; | |
pointer-events: none; | |
} | |
.d3-tip span { | |
color: #ff00c7; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script> | |
<script> | |
// http://blog.thomsonreuters.com/index.php/mobile-patent-suits-graphic-of-the-day/ | |
var links = [ | |
{source: "Microsoft", target: "Amazon", type: "licensing"}, | |
{source: "Microsoft", target: "HTC", type: "licensing"}, | |
{source: "Samsung", target: "Apple", type: "suit"}, | |
{source: "Motorola", target: "Apple", type: "suit"}, | |
{source: "Nokia", target: "Apple", type: "resolved"}, | |
{source: "HTC", target: "Apple", type: "suit"}, | |
{source: "Kodak", target: "Apple", type: "suit"}, | |
{source: "Microsoft", target: "Barnes & Noble", type: "suit"}, | |
{source: "Microsoft", target: "Foxconn", type: "suit"}, | |
{source: "Oracle", target: "Google", type: "suit"}, | |
{source: "Apple", target: "HTC", type: "suit"}, | |
{source: "Microsoft", target: "Inventec", type: "suit"}, | |
{source: "Samsung", target: "Kodak", type: "resolved"}, | |
{source: "LG", target: "Kodak", type: "resolved"}, | |
{source: "RIM", target: "Kodak", type: "suit"}, | |
{source: "Sony", target: "LG", type: "suit"}, | |
{source: "Kodak", target: "LG", type: "resolved"}, | |
{source: "Apple", target: "Nokia", type: "resolved"}, | |
{source: "Qualcomm", target: "Nokia", type: "resolved"}, | |
{source: "Apple", target: "Motorola", type: "suit"}, | |
{source: "Microsoft", target: "Motorola", type: "suit"}, | |
{source: "Motorola", target: "Microsoft", type: "suit"}, | |
{source: "Huawei", target: "ZTE", type: "suit"}, | |
{source: "Ericsson", target: "ZTE", type: "suit"}, | |
{source: "Kodak", target: "Samsung", type: "resolved"}, | |
{source: "Apple", target: "Samsung", type: "suit"}, | |
{source: "Kodak", target: "RIM", type: "suit"}, | |
{source: "Nokia", target: "Qualcomm", type: "suit"} | |
]; | |
var nodes = {}; | |
// 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}); | |
}); | |
var width = 960, | |
height = 500; | |
var force = d3.layout.force() | |
.nodes(d3.values(nodes)) | |
.links(links) | |
.size([width, height]) | |
.linkDistance(60) | |
.charge(-300) | |
.on("tick", tick) | |
.start(); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var tip = d3.tip().attr('class','d3-tip') | |
.html(function(d){ | |
var x = links.filter(g=>g.source.name==d.name).map(t=>t.target.name).toString(); | |
var y = links.filter(g=>g.target.name==d.name).map(t=>t.target.name).toString(); | |
return "<span>" + "inbound: " + x + "</span><br><span>" + "outbound: " + y + "</span>";}); | |
var colors = {licensing:"blue",suit:"red",resolved:"green"}; | |
// Per-type markers, as they don't inherit styles. | |
svg.append("defs").selectAll("marker") | |
.data(["suit", "licensing", "resolved"]) | |
.enter().append("marker") | |
.attr("id", function(d) { return d; }) | |
.attr("viewBox", "0 -5 10 10") | |
.attr("refX", 15) | |
.attr("refY", -1.5) | |
.attr("markerWidth", 6) | |
.attr("markerHeight", 6) | |
.attr("orient", "auto") | |
.append("path") | |
.attr("d", "M0,-5L10,0L0,5"); | |
svg.call(tip); | |
var path = svg.append("g").selectAll("path") | |
.data(force.links()) | |
.enter().append("path") | |
.attr("class", function(d) { return "link " + d.type; }) | |
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; }); | |
var ct = svg.append("g").selectAll(".node") | |
.data(force.nodes()) | |
.enter().append("g").attr("class","node"); | |
var circle = ct.append("circle") | |
.attr("r", 8) | |
.style("fill", function(d) { return "yellow";}); | |
var clabel = ct.append("text") | |
.attr("dy",function(d){return 10;}) | |
.text(function(d){return d.name;}); | |
ct.call(force.drag); | |
ct.on("mouseover",tip.show).on("mouseout",tip.hide).on("dblclick",pin); | |
// Use elliptical arc path segments to doubly-encode directionality. | |
function tick() { | |
path.attr("d", linkArc); | |
ct.attr("transform", transform); | |
} | |
function linkArc(d) { | |
var dx = d.target.x - d.source.x, | |
dy = d.target.y - d.source.y, | |
dr = Math.sqrt(dx * dx + dy * dy); | |
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; | |
} | |
function transform(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
} | |
function pin(d){ | |
d3.select(this).classed("fixed", d.fixed = !d.fixed); | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.link { | |
fill: none; | |
stroke: #666; | |
stroke-width: 1.5px; | |
} | |
path.link.suit { | |
stroke:red; | |
} | |
path.link.licensing { | |
stroke:blue | |
; | |
} | |
path.link.resolved { | |
stroke:green; | |
} | |
circle { | |
fill: #ccc; | |
stroke: #333; | |
stroke-width: 1.5px; | |
} | |
.node.fixed { | |
fill: #f00; | |
} | |
text { | |
font: 10px sans-serif; | |
pointer-events: none; | |
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff; | |
} | |
div.d3-tip { | |
line-height: 1; | |
font-weight: bold; | |
padding: 12px; | |
background: #001; | |
color: #F00; | |
border-radius: 2px; | |
pointer-events: none; | |
} | |
.d3-tip span { | |
color: #ff00c7; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script> | |
<script> | |
// http://blog.thomsonreuters.com/index.php/mobile-patent-suits-graphic-of-the-day/ | |
var links = [ | |
{source: "Microsoft", target: "Amazon", type: "licensing"}, | |
{source: "Microsoft", target: "HTC", type: "licensing"}, | |
{source: "Samsung", target: "Apple", type: "suit"}, | |
{source: "Motorola", target: "Apple", type: "suit"}, | |
{source: "Nokia", target: "Apple", type: "resolved"}, | |
{source: "HTC", target: "Apple", type: "suit"}, | |
{source: "Kodak", target: "Apple", type: "suit"}, | |
{source: "Microsoft", target: "Barnes & Noble", type: "suit"}, | |
{source: "Microsoft", target: "Foxconn", type: "suit"}, | |
{source: "Oracle", target: "Google", type: "suit"}, | |
{source: "Apple", target: "HTC", type: "suit"}, | |
{source: "Microsoft", target: "Inventec", type: "suit"}, | |
{source: "Samsung", target: "Kodak", type: "resolved"}, | |
{source: "LG", target: "Kodak", type: "resolved"}, | |
{source: "RIM", target: "Kodak", type: "suit"}, | |
{source: "Sony", target: "LG", type: "suit"}, | |
{source: "Kodak", target: "LG", type: "resolved"}, | |
{source: "Apple", target: "Nokia", type: "resolved"}, | |
{source: "Qualcomm", target: "Nokia", type: "resolved"}, | |
{source: "Apple", target: "Motorola", type: "suit"}, | |
{source: "Microsoft", target: "Motorola", type: "suit"}, | |
{source: "Motorola", target: "Microsoft", type: "suit"}, | |
{source: "Huawei", target: "ZTE", type: "suit"}, | |
{source: "Ericsson", target: "ZTE", type: "suit"}, | |
{source: "Kodak", target: "Samsung", type: "resolved"}, | |
{source: "Apple", target: "Samsung", type: "suit"}, | |
{source: "Kodak", target: "RIM", type: "suit"}, | |
{source: "Nokia", target: "Qualcomm", type: "suit"} | |
]; | |
var nodes = {}; | |
// 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}); | |
}); | |
var width = 960, | |
height = 500; | |
var force = d3.layout.force() | |
.nodes(d3.values(nodes)) | |
.links(links) | |
.size([width, height]) | |
.linkDistance(60) | |
.charge(-300) | |
.on("tick", tick) | |
.start(); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var tip = d3.tip().attr('class','d3-tip') | |
.html(function(d){ | |
var x = links.filter(g=>g.source.name==d.name).map(t=>t.target.name).toString(); | |
var y = links.filter(g=>g.target.name==d.name).map(t=>t.target.name).toString(); | |
return "<span>" + "inbound: " + x + "</span><br><span>" + "outbound: " + y + "</span>";}); | |
var colors = {licensing:"blue",suit:"red",resolved:"green"}; | |
// Per-type markers, as they don't inherit styles. | |
svg.append("defs").selectAll("marker") | |
.data(["suit", "licensing", "resolved"]) | |
.enter().append("marker") | |
.attr("id", function(d) { return d; }) | |
.attr("viewBox", "0 -5 10 10") | |
.attr("refX", 15) | |
.attr("refY", -1.5) | |
.attr("markerWidth", 6) | |
.attr("markerHeight", 6) | |
.attr("orient", "auto") | |
.append("path") | |
.attr("d", "M0,-5L10,0L0,5"); | |
svg.call(tip); | |
var path = svg.append("g").selectAll("path") | |
.data(force.links()) | |
.enter().append("path") | |
.attr("class", function(d) { return "link " + d.type; }) | |
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; }); | |
var ct = svg.append("g").selectAll(".node") | |
.data(force.nodes()) | |
.enter().append("g").attr("class","node"); | |
var circle = ct.append("circle") | |
.attr("r", 8) | |
.style("fill", function(d) { return "yellow";}); | |
var clabel = ct.append("text") | |
.attr("dy",function(d){return 10;}) | |
.text(function(d){return d.name;}); | |
ct.call(force.drag); | |
ct.on("mouseover",tip.show).on("mouseout",tip.hide).on("dblclick",pin); | |
// Use elliptical arc path segments to doubly-encode directionality. | |
function tick() { | |
path.attr("d", linkArc); | |
ct.attr("transform", transform); | |
} | |
function linkArc(d) { | |
var dx = d.target.x - d.source.x, | |
dy = d.target.y - d.source.y, | |
dr = Math.sqrt(dx * dx + dy * dy); | |
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; | |
} | |
function transform(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
} | |
function pin(d){ | |
d3.select(this).classed("fixed", d.fixed = !d.fixed); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment