rain
by Ryan
HTML
<script src="https://d3js.org/d3.v3.min.js"></script>
<button id="pause">Pause</button>
<div>fps: <span id="fps"></span></div>
<div id="chart"></div>
CSS
body { font: 10px sans-serif; }
svg { background-color: #000; }
circle {
fill: #666;
stroke: #eee;
}
JavaScript
var margin = 10,
width = 600 - margin*2,
height = 400 - margin*2;
var config = {
circle: {
life: 800,
r: { min: 3, mean: 15, std: 0 },
o: { min: 0, max: 1}
},
rate: {
epoch: { min: 0, mean: 100, std: 50 },
count: { min: 0, mean: 1, std: 0 }
}
};
var dist = {
circle: {
r: d3.random.normal(config.circle.r.mean, config.circle.r.std)
},
rate: {
epoch: d3.random.normal(config.rate.epoch.mean, config.rate.epoch.std),
count: d3.random.normal(config.rate.count.mean, config.rate.count.std)
}
};
var fn = {
circle: {
x: function(){ return Math.random() * (width - margin*2) + margin; },
y: function(){ return Math.random() * (height - margin*2) + margin; },
r: function(){ return Math.max(config.circle.r.min, dist.circle.r()) }
},
rate: {
epoch: function(){ return Math.max(0, dist.rate.epoch()); },
count: function(){ return Math.max(0, dist.rate.count()); }
}
};
// The list of circles
var circles = [];
var paused = false;
var g = d3.select("div#chart").append("svg")
.attr("width", width + margin*2).attr("height", height + margin*2)
.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")");
var lastTs = Date.now();
var nowTs = Date.now();
var fps = d3.select('#fps');
d3.timer(function() {
nowTs = Date.now();
for(var i=circles.length-1; i>=0; i--){
var d = circles[i];
var age = nowTs - d.ts;
if(!paused){
if(config.circle.life < age){
d.c.remove();
circles.splice(i, 1);
} else {
var ageRatio = age/config.circle.life;
var r = d.r.min + ageRatio * (d.r.max - d.r.min);
var o = config.circle.o.max - ageRatio * (config.circle.o.max - config.circle.o.min);
d.c.attr('r', r).attr('opacity', o);
}
} else {
d.ts...