Skip to content

Instantly share code, notes, and snippets.

@bjorsq
Created March 4, 2018 12:11
Show Gist options
  • Select an option

  • Save bjorsq/f7d7ef318cea58bed03e52f2f4d0c858 to your computer and use it in GitHub Desktop.

Select an option

Save bjorsq/f7d7ef318cea58bed03e52f2f4d0c858 to your computer and use it in GitHub Desktop.
Force directed graph
<svg width="960" height="600"></svg>
function getData(){
var data = {'nodes':[],'links':[]};
for(var i = 0; i < 6; i++){
data.nodes.push({id:'node_'+i});
if (i > 0) {
data.links.push({'source':'node_0','target':'node_'+i});
}
for(var j = 0; j < 6; j++) {
data.nodes.push({id:'node_'+i+'_'+j});
if (j > 0) {
data.links.push({'source':'node_'+i,'target':'node_'+i+'_'+j});
}
}
}
return data;
}
var graph = getData();
var width = window.innerWidth
var height = window.innerHeight
var svg = d3.select('svg')
svg.attr('width', width).attr('height', height);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var linkElements = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line");
var nodeElements = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 10)
.attr("fill", '#0fc')
.on('click', selectNode);
var textElements = svg.append("g")
.attr("class", "texts")
.selectAll("text")
.data(graph.nodes)
.enter().append("text")
.text(function (node) { return node.id })
.attr("font-size", 15)
.attr("dx", 15)
.attr("dy", 4);
nodeElements.append("title")
.text(function(d) { return d.id; });
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
linkElements
.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; });
textElements
.attr('x', function (node) { return node.x })
.attr('y', function (node) { return node.y })
nodeElements
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
function getNeighbors(node) {
return links.reduce(function (neighbors, link) {
if (link.target.id === node.id) {
neighbors.push(link.source.id)
} else if (link.source.id === node.id) {
neighbors.push(link.target.id)
}
return neighbors
},
[node.id]
)
}
function isNeighborLink(node, link) {
return link.target.id === node.id || link.source.id === node.id
}
function selectNode(selectedNode)
{
var neighbors = getNeighbors(selectedNode)
// we modify the styles to highlight selected nodes
nodeElements.attr('fill', function (node) { return getNodeColor(node, neighbors) })
textElements.attr('fill', function (node) { return getTextColor(node, neighbors) })
linkElements.attr('stroke', function (link) { return getLinkColor(selectedNode, link) })
}
function getNodeColor(node, neighbors) {
if (Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1) {
return 'blue'
}
return 'red'
}
function getLinkColor(node, link) {
return isNeighborLink(node, link) ? 'green' : '#E5E5E5'
}
function getTextColor(node, neighbors) {
return Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1 ? 'green' : 'black'
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
stroke-width: 1.5px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment