Ball Pit Graph
by eprouver
HTML
<!-- Perfect square indication of event types -->
<!-- event types by color fitted into a square of circles -->
<!-- used for an infographic -->
<button onclick="newGraph()">New Ball Pit</button>
<div id="holder"></div>
CSS
svg{
width: 100%;
height: auto;
max-height: 80vh;
}
JavaScript
function newGraph(){
document.getElementById('holder').innerHTML = '';
var data = [];
var num = 1 + ~~(Math.random() * 50);
//Generate fake data;
for(var i = 0; i < num; i++){
data.push({
"description": {
"subject": {
"_id": ~~(Math.random() * 3) + 1
}
},
"startdate": ~~(Math.random() * 1000)
});
}
var width = 500,
height = 500;
function nextSquare(n){
s = Math.sqrt(n);
while(s % 1 != 0){
n += 1;
s = Math.sqrt(n);
}
return Math.sqrt(n)
}
var svg = d3.select('#holder').append("svg")
.attr("width", width)
.attr('viewBox', '0 0 ' + width + ' ' + height);
var sides = nextSquare(data.length);
var colors = d3.scale.category10().domain(0, 19);
data = data.sort(function(b,a){
return b.startdate - a.startdate;
});
var y = d3.scale.ordinal()
.domain(d3.range(0, sides))
.rangeRoundBands([0, height]);
var x = d3.scale.ordinal()
.domain(d3.range(0, sides))
.rangeRoundBands([0, width]);
var band = Math.abs(x.rangeBand()) / 2;
var i = 0;
for(var r = 0; r < sides; r++){
for(var c = 0; c < sides; c++){
svg.append('circle').datum(data[i] || {})
.attr('class', 'dot')
.attr('r', band - 5)
.attr('cy', band + (2 * band * r) )
.attr('cx', band + (2 * band * c) )
.attr('fill', '#ccc')
.transition()
.duration(300)
.delay(i*100)
.attr('fill', function(d){
if(!d.description){
return '#ccc'
}
return colors(d.description.subject._id);
})
i++;
}
}
}
newGraph();