Last active
June 12, 2016 06:09
-
-
Save cool-Blue/9f49525e782491c8b68a to your computer and use it in GitHub Desktop.
d3 fdg with font BBox positioning and sizing of nodes
This file contains hidden or 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> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title></title> | |
<style> | |
svg { | |
outline: 1px solid #282f51; | |
pointer-events: all; | |
overflow: visible; | |
} | |
g.outline { | |
outline: 1px solid red; | |
} | |
#panel div { | |
display: inline-block; | |
margin: 0 .25em 3px 0; | |
} | |
#panel div div { | |
white-space: pre; | |
margin: 0 .25em 3px 0; | |
} | |
div#inputDiv { | |
white-space: normal; | |
display: inline-block; | |
} | |
.node { | |
cursor: default; | |
} | |
.content { | |
transform-origin: 50% 50%; | |
} | |
</style> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css"> | |
</head> | |
<body> | |
<div id="panel"> | |
<div id="inputDiv"> | |
<input id="update" type="button" value="update"> | |
</div> | |
<div id="wrapAlpha">alpha:<div id="alpha"></div></div><div id="fdg"></div> | |
</div> | |
<div id="viz"></div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
<script src="https://gitcdn.xyz/repo/cool-Blue/d3-lib/master/elapsedTime/elapsedTime/elapsed%20time%201.0.js"></script> | |
<script src="script-array-base.js"></script> | |
</body> | |
</html> |
This file contains hidden or 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
//debug panel///////////////////////////////////////////////////////////////////////////// | |
d3.select("#update").on("click", (function() { | |
var dataSet = false; | |
return function() { | |
refresh(dataSets[(dataSet = !dataSet, +dataSet)]) | |
} | |
})()); | |
var alpha = d3.select("#alpha").text("waiting..."), | |
cog = d3.select("#wrapAlpha").insert("i", "#fdg").classed("fa fa-cog fa-spin", true), | |
fdgInst = d3.select("#fdg"); | |
elapsedTime = ElapsedTime("#panel", {margin: 0, padding: 0}) | |
.message(function (id) { | |
return 'fps : ' + d3.format(" >8.3f")(1/this.aveLap()) | |
}); | |
elapsedTime.consoleOn = false; | |
////////////////////////////////////////////////////////////////////////////////// | |
var dataSets = [ | |
{ | |
"nodes": [ | |
{"name": "node1", "content": "the first Node"}, | |
{"name": "node2", "content": "node2"}, | |
{"name": "node3", "content":{"fa": "fa/*-spin*/", text: "\uf013"}}, | |
{"name": "node4", "content":{"fa": "fa/*-spin*/", text: "\uf1ce"}} | |
], | |
"edges": [ | |
{"source": 2, "target": 0}, | |
{"source": 2, "target": 1}, | |
{"source": 2, "target": 3} | |
] | |
}, | |
{ | |
"nodes": [ | |
{"name": "node1", "content": "node1"}, | |
{"name": "node2", "content":{"fa": "fa/*-spin*/", text: "\uf1ce"}}, | |
{"name": "node3", "content":{"fa": "fa/*-spin*/", text: "\uf013"}}, | |
{"name": "node4", "content": "4"}, | |
{"name": "node5", "content": "5"}, | |
{"name": "node6", "content": "6"} | |
], | |
"edges": [ | |
{"source": 2, "target": 0}, | |
{"source": 2, "target": 1}, | |
{"source": 2, "target": 3}, | |
{"source": 2, "target": 4}, | |
{"source": 2, "target": 5} | |
] | |
} | |
]; | |
var refresh = (function(){ | |
var instID = Date.now(), | |
height = 160, | |
width = 500, | |
force = d3.layout.force() | |
.size([width, height]) | |
.charge(-1000) | |
.linkDistance(50) | |
.on("end", function(){cog.classed("fa-spin", false); elapsedTime.stop()}) | |
.on("start", function(){cog.classed("fa-spin", true); elapsedTime.start()}); | |
return function refresh(data) { | |
force | |
.nodes(data.nodes) | |
.links(data.edges) | |
.on("tick", (function(instID) { | |
return function(e) { | |
elapsedTime.mark(); | |
alpha.text(d3.format(" >8.4f")(e.alpha)); | |
fdgInst.text("fdg instance: " + instID); | |
lines.attr("x1", function(d) { | |
return d.source.x + d.source.cx + d.source.r; | |
}).attr("y1", function(d) { | |
return d.source.y + d.source.cy; | |
}).attr("x2", function(d) { | |
return d.target.x + d.target.cx; | |
}).attr("y2", function(d) { | |
return d.target.y + d.target.cy; | |
}); | |
node.attr("transform", function(d) { | |
return "translate(" + [d.x, d.y] + ")" | |
}); | |
} | |
})(instID)) | |
.start(); | |
var svg = d3.select("body").selectAll("svg").data([data]); | |
svg.enter().append("svg") | |
.attr({height: height, width: width}); | |
var lines = svg.selectAll(".links") | |
.data(linksData), | |
linesEnter = lines.enter() | |
.insert("line", d3.select("#nodes") ? "#nodes" : null) | |
.attr("class", "links") | |
.attr({stroke: "steelblue", "stroke-width": 3}); | |
var nodes = svg.selectAll("#nodes").data(nodesData), | |
nodesEnter = nodes.enter().append("g") | |
.attr("id", "nodes"), | |
node = nodes.selectAll(".node") | |
.data(id), | |
newNode = node.enter().append("g") | |
.attr("class","node") | |
.call(force.drag); | |
newNode.append("text") | |
.attr({class: "content", fill: "steelblue"}) | |
newNode.insert("circle", ".node .content"); | |
var glyphs = node.select("text") | |
.each(function(d) { | |
var node = d3.select(this); | |
if(d.content.fa) | |
node.style({'font-family': 'FontAwesome', 'font-size': '32px', 'dominant-baseline': 'central'}) | |
.classed(d.content.fa, true) | |
.text(d.content.text); | |
else | |
node.text(d.content) | |
.attr({"class": "content", style: null}); | |
}) | |
.call(getBB), | |
backGround = node.select("circle").each(function(d) { | |
d3.select(this).attr(makeCircleBB(d)) | |
}).style({"fill": "red", opacity: 0.8}); | |
(function(id){ | |
//adjust the bounding box after the font loads | |
var count = 0; | |
d3.timer(function() { | |
console.log(id); | |
glyphs.call(getBB); | |
backGround.each(function(d) { | |
d3.select(this).attr(makeCircleBB(d)) | |
}); | |
return /*false || id != instID*/++count > 10; //needs to keep running due to webkit zoom bug | |
}) | |
})(instID); | |
lines.exit().remove(); | |
node.exit().remove(); | |
function nodesData(d) { | |
return [d.nodes]; | |
} | |
function linksData(d) { | |
return d.edges; | |
} | |
}; | |
function getBB(selection) { | |
this.each(function(d) { | |
d.bb = this.getBBox(); | |
}) | |
} | |
function makeCircleBB(d, i, j) { | |
var bb = d.bb; | |
d.r = Math.max(bb.width, bb.height) / 2; | |
delete d.bb; //plug potential memory leak! | |
d.cy = bb.height / 2 + bb.y; | |
d.cx = bb.width / 2; | |
return { | |
r: d.r, cx: d.cx, cy: d.cy, height: bb.height, width: bb.width | |
} | |
} | |
function id(d) { | |
return d; | |
} | |
})(); | |
refresh(dataSets[0]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment