Last active
July 15, 2016 23:28
-
-
Save xtrntr/9f272baf62768c5ced7714915bd88f7a to your computer and use it in GitHub Desktop.
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
function restart() { | |
// path (link) group | |
path = path.data(links); | |
// update existing links | |
path.classed('selected', function(d) { return d === selected_link; }) | |
.style('marker-start', function(d) { return d.left ? 'url(#start-arrow)' : ''; }) | |
.style('marker-end', function(d) { return d.right ? 'url(#end-arrow)' : ''; }); | |
// add new links | |
path.enter().append('svg:path') | |
.attr('class', 'link') | |
.classed('selected', function(d) { return d === selected_link; }) | |
.style('marker-start', function(d) { return d.left ? 'url(#start-arrow)' : ''; }) | |
.style('marker-end', function(d) { return d.right ? 'url(#end-arrow)' : ''; }) | |
.on('mousedown', function(d) { | |
if(d3.event.ctrlKey) return; | |
// select link | |
mousedown_link = d; | |
if(mousedown_link === selected_link) selected_link = null; | |
else selected_link = mousedown_link; | |
selected_node = null; | |
restart(); | |
}); | |
// remove old links | |
path.exit().remove(); | |
// circle (node) group | |
// NB: the function arg is crucial here! nodes are known by id, not by index! | |
circle = circle.data(nodes, function(d) { return d.id; }); | |
// update existing nodes (reflexive & selected visual states) | |
circle.selectAll('circle') | |
.style('fill', function(d) { return (d === selected_node) ? d3.rgb(colors(d.id)).brighter().toString() : colors(d.id); }) | |
.classed('reflexive', function(d) { return d.reflexive; }); | |
// add new nodes | |
var g = circle.enter().append('svg:g'); | |
g.append('svg:circle') | |
.attr('class', 'node') | |
.attr('r', 12) | |
.style('fill', function(d) { return (d === selected_node) ? d3.rgb(colors(d.id)).brighter().toString() : colors(d.id); }) | |
.style('stroke', function(d) { return d3.rgb(colors(d.id)).darker().toString(); }) | |
.classed('reflexive', function(d) { return d.reflexive; }) | |
.on('mouseover', function(d) { | |
if(!mousedown_node || d === mousedown_node) return; | |
// enlarge target node | |
d3.select(this).attr('transform', 'scale(1.1)'); | |
}) | |
.on('mouseout', function(d) { | |
if(!mousedown_node || d === mousedown_node) return; | |
// unenlarge target node | |
d3.select(this).attr('transform', ''); | |
}) | |
.on('mousedown', function(d) { | |
if(d3.event.ctrlKey) return; | |
// select node | |
mousedown_node = d; | |
if(mousedown_node === selected_node) selected_node = null; | |
else selected_node = mousedown_node; | |
selected_link = null; | |
// reposition drag line | |
drag_line | |
.style('marker-end', 'url(#end-arrow)') | |
.classed('hidden', false) | |
.attr('d', 'M' + mousedown_node.x + ',' + mousedown_node.y + 'L' + mousedown_node.x + ',' + mousedown_node.y); | |
restart(); | |
}) | |
.on('mouseup', function(d) { | |
if(!mousedown_node) return; | |
// needed by FF | |
drag_line | |
.classed('hidden', true) | |
.style('marker-end', ''); | |
// check for drag-to-self | |
mouseup_node = d; | |
if(mouseup_node === mousedown_node) { resetMouseVars(); return; } | |
// unenlarge target node | |
d3.select(this).attr('transform', ''); | |
// add link to graph (update if exists) | |
// NB: links are strictly source < target; arrows separately specified by booleans | |
var source, target, direction; | |
if(mousedown_node.id < mouseup_node.id) { | |
source = mousedown_node; | |
target = mouseup_node; | |
direction = 'right'; | |
} else { | |
source = mouseup_node; | |
target = mousedown_node; | |
direction = 'left'; | |
} | |
var link; | |
link = links.filter(function(l) { | |
return (l.source === source && l.target === target); | |
})[0]; | |
if(link) { | |
link[direction] = true; | |
} else { | |
link = {source: source, target: target, left: false, right: false}; | |
link[direction] = true; | |
links.push(link); | |
} | |
// select new link | |
selected_link = link; | |
selected_node = null; | |
restart(); | |
}); | |
// show node IDs | |
g.append('svg:text') | |
.attr('x', 0) | |
.attr('y', 4) | |
.attr('class', 'id') | |
.text(function(d) { return d.id; }); | |
// remove old nodes | |
circle.exit().remove(); | |
// set the graph in motion | |
force.start(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment