Created
February 25, 2016 21:13
-
-
Save gmlnchv/80dd206440cca39800b8 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
Template.home.onDestroyed(function () { | |
if (Observe) { | |
Observe.stop(); | |
} | |
}); | |
Template.home.onRendered(function() { | |
var nodes = Entries.find().fetch(); | |
var layout = new Layout('#entries', nodes); | |
var radius = 100; | |
var jitter = 0.5; | |
var collisionPadding = 4; | |
Observe = Entries.find().observe({ | |
added: function(document) { | |
layout.addNode(document); | |
layout.render(); | |
}, | |
changed: function(newDocument) { | |
d3.select(`[data-id=${newDocument._id}]`) | |
.select('.node-likes') | |
.text(newDocument.likes) | |
}, | |
removed: function(document) { | |
d3.select(`[data-id=${document._id}]`) | |
.remove() | |
} | |
}); | |
function Layout(selector, nodes) { | |
this.nodes = nodes; | |
// init svg | |
var svg = d3.select(selector); | |
// clean up all previous items before render | |
svg.selectAll('*').remove(); | |
// init force layout | |
var force = d3.layout.force() | |
.nodes(this.nodes) | |
.gravity(0) | |
.charge(0) | |
.on('tick', tick); | |
var circle = svg.selectAll('g'); | |
// auto-adjust to changed window size | |
resize(); | |
d3.select(window).on('resize', resize); | |
function getSize() { | |
var size = {}; | |
size.width = window.innerWidth; | |
size.height = window.innerHeight - document.getElementById('submit-container').getBoundingClientRect().height; | |
return size; | |
} | |
// tick | |
function tick(e) { | |
var dampenedAlpha; | |
dampenedAlpha = e.alpha * 0.1; | |
// Most of the work is done by custom gravity and collide functions | |
circle | |
.each(gravity(dampenedAlpha)) | |
.each(collide(jitter)) | |
.attr('transform', function(d) { | |
// var x = Math.max(radius, Math.min(getSize().width - radius, d.x)); | |
// var y = Math.max(radius, Math.min(getSize().height - radius, d.y)); | |
// | |
return `translate(${d.x}, ${d.y})`; | |
}); | |
} | |
function gravity(alpha) { | |
var ax, ay, cx, cy; | |
cx = getSize().width / 2; | |
cy = getSize().height / 2; | |
ax = alpha / 8; | |
ay = alpha; | |
return function(d) { | |
d.x += (cx - d.x) * ax; | |
return d.y += (cy - d.y) * ay; | |
}; | |
} | |
function collide(jitter) { | |
return function(d) { | |
return nodes.forEach(function(d2) { | |
var distance, minDistance, moveX, moveY, x, y; | |
if (d !== d2) { | |
x = d.x - d2.x; | |
y = d.y - d2.y; | |
distance = Math.sqrt(x * x + y * y); | |
minDistance = radius * 2 + collisionPadding; | |
if (distance < minDistance) { | |
distance = (distance - minDistance) / distance * jitter; | |
moveX = x * distance; | |
moveY = y * distance; | |
d.x -= moveX; | |
d.y -= moveY; | |
d2.x += moveX; | |
return d2.y += moveY; | |
} | |
} | |
}) | |
} | |
} | |
// resize svg and force layout when screen size change | |
function resize() { | |
var width = getSize().width; | |
var height = getSize().height; | |
svg.attr('width', width).attr('height', height); | |
force.size([width, height]).resume(); | |
} | |
// dynamically update the graph | |
this.render = function() { | |
// add nodes | |
circle = circle | |
.data(force.nodes(), d => d._id) | |
// .call(force.drag); | |
circle | |
.enter() | |
.insert('g') | |
.attr('data-id', d => d._id) | |
.attr('class', 'node') | |
.each(function(d) { | |
d3.select(this).append('circle') | |
.attr('r', radius - .75) | |
.style('fill', '#fff') | |
d3.select(this).append('text') | |
.attr('class', 'node-name') | |
.attr('dy', '-3em') | |
.style('text-anchor', 'middle') | |
.text(d => d.name) | |
.style('fill', '#000') | |
d3.select(this).append('text') | |
.attr('class', 'node-likes') | |
.attr('dy', '3em') | |
.style('text-anchor', 'middle') | |
.text(d => d.likes) | |
.style('fill', '#000') | |
}) | |
.on('click', () => force.stop()) | |
circle.exit().remove(); | |
force.start(); | |
}; | |
// graph data manipulation | |
this.addNode = function(doc) { | |
this.nodes.push(doc); | |
}; | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment