{
var nbr_circles = 100;
var radius = 2;
var new_fall_delay = 1000;
var circles_per_fall = 23;
var exitAmt = 21;
var iterations = 0;
var duration = 20;
var seat = 0.65*height;
var data = [];
for (let i = 0; i < nbr_circles; ++i) {
data.push({
x: Math.random()*width,
y: 0.1*height,
side:"down"
});
}
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
var sim = d3.forceSimulation(data)
.force("y",d3.forceY(d => {
return d.side === "down" ? seat : 100;
}))
.force("collide", d3.forceCollide(radius))
.force("limits", forceLimit.forceLimit().radius(radius).y1(seat).x0(0).x1(width))
sim.on('tick', function() {
svg
.selectAll(".current")
.attr('cx', d => d.x)
.attr('cy', d => d.y);
});
function add_circles(elapsed_time) {
if (iterations < duration) {
if (iterations > 1) {
var righties = [...data].filter(d => d.side !== "up").sort((a,b) => a.x - b.x).slice(-exitAmt);
righties.forEach(function(d,i){
d.side = "up";
});
}
for (let i = 0; i < circles_per_fall; ++i) {
data.push({
x: Math.random()*width,
y: 0.1*height,
vx: 0,
vy: 0,
side:"down"
});
}
draw_circles();
sim.nodes(data).alpha(1).restart();
}
iterations++;
}
draw_circles();
d3.interval(add_circles, new_fall_delay);
function draw_circles() {
svg
.selectAll(".current")
.data(data)
.join(
enter => enter.append("circle")
.attr("class","current")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.style('fill', d => color(d.x))
.attr("r", radius),
update => update
.style('fill', d => color(d.x))
.attr("cx", d => d.x)
.attr("cy", d => d.y)
)
}
return svg.node()
}