Skip to content

Instantly share code, notes, and snippets.

@jwilber
Last active January 5, 2019 21:11
Show Gist options
  • Save jwilber/5d1b69d7ed63ed7bd6e1706dc973c261 to your computer and use it in GitHub Desktop.
Save jwilber/5d1b69d7ed63ed7bd6e1706dc973c261 to your computer and use it in GitHub Desktop.
d3v4 force add new nodes
license: mit
var Graph = function(targetElement, graph) {
var self = this,
width = targetElement.offsetWidth,
height = width / 2,
svg = d3.select(targetElement).append('svg')
.attr("width", width)
.attr("height", height),
simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2)),
nodeGroup = svg.append("g")
.attr("class", "nodes"),
update = function() {
// Redefine and restart simulation
simulation.nodes(graph.nodes)
.on("tick", ticked);
// Update the nodes
node = nodeGroup.selectAll("circle").data(graph.nodes);
// Enter any new nodes
nodeEnter = node.enter().append("circle")
.attr("r", 5)
node = nodeEnter.merge(node);
// Exit any old nodes
node.exit().remove();
function ticked() {
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
},
expandGraph = function(links, nodes) {
for (var i=0; i < nodes.length; i++) {
console.log('adding node', nodes[i]);
graph.nodes.push(nodes[i]);
}
update();
};
// Public functions
this.expandGraph = expandGraph;
update();
};
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.option {font-size: 30px;}
</style>
</head>
<body>
<center>
<input name="updateButton"
type="button"
value="Add Node"
onclick="clickButton()"
class="option"/>
</center>
<script>
// chart stuff
const width = 1000
const height = 600
const svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
// initital data
let sampleData = d3.range(2).map((d,i) => ({r: 40 - i * 0.5}));
function changeNetwork() {
d3.selectAll('.force1')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
};
function force1(data) {
const manyBody = d3.forceManyBody().strength(2)
const center = d3.forceCenter().x((width/2)).y((height/2))
// define force
let force = d3.forceSimulation()
.force('charge', manyBody)
.force('center', center)
.force('collision', d3.forceCollide(d => d.r + 2))
.velocityDecay(.48);
force
.nodes(data)
.on('tick', changeNetwork);
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('class', 'force1')
.style('fill', 'coral')
.attr('r', d => d.r)
return force
}
function clickButton() {
// generate random data point
let ranNum = Math.round(Math.random() * 20);
let newDataPoint = {r: 40 - ranNum * 0.5}
// update datasource
sampleData = sampleData.concat(newDataPoint);
let nodes = svg.selectAll('circle.force1')
.data(sampleData);
let nodeEnter = nodes.enter()
.append('circle')
.attr('class', 'force1')
.style('fill', 'blue')
.attr('r', d => d.r / 2)
nodes = nodeEnter.merge(nodes)
.on('tick', changeNetwork)
f1.nodes(sampleData);
f1.alpha(1).restart()
}
let f1 = force1(sampleData);
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment