Published
Edited
Dec 9, 2020
5 forks
34 stars
Insert cell
Insert cell
Insert cell
{
let startTime = new Date().getTime(),
seconds = 0,
secondsRounded = 0,
ticks = 0,
speeds = [];
const ctx = DOM.context2d(myBoids.width(), height);
// const scale = width / height,
let projection = d3.geoIdentity(); //.scale(scale),
let path = d3.geoPath(projection).context(ctx);

let holding = false;
// ctx.canvas.addEventListener("mousedown", e => { holding = true; addBoidOnEvent(e); });
// ctx.canvas.addEventListener("mouseup", e => { holding = false });
// ctx.canvas.addEventListener("mousemove", e => { if (holding) addBoidOnEvent(e); });

while (true && myBoids.flock.length) {
myBoids.tick();
// ctx.clearRect(0, 0, myBoids.width(), myBoids.height());
// ctx.fillStyle = "rgba(255,255,255,0.1)";
ctx.globalAlpha = 0.9;
ctx.fillStyle = cwf[0];
ctx.fillRect(0, 0, width, height);
ctx.globalAlpha = 1;

let contours = contour(myBoids.flock);
for (const contour of contours) {
const threshold = contour.value;
ctx.beginPath(),
// (ctx.fillStyle = color(threshold)),
path(contour),
ctx.stroke();
}

ctx.beginPath();
myBoids.each(boid => {
boid.vel[1] = -1.8;
const a = vecmath.trans(boid.pos, boid.ang - Math.PI * .5, 3),
b = vecmath.trans(boid.pos, boid.ang, 9),
c = vecmath.trans(boid.pos, boid.ang + Math.PI * .5, 3);


ctx.moveTo(...a);
ctx.lineTo(...b);
ctx.lineTo(...c);
ctx.lineTo(...a);

ctx.arc(boid.pos[0], boid.pos[1], 1.5, 0, Math.PI * 2);

const color = d3.interpolateRdPu((.6 * myBoids.maxSpeed()) / boid.speed);
ctx.strokeStyle = color;
ctx.strokeStyle = cwf[2];
ctx.fillStyle = d3.color(color).brighter(2);
ctx.fillStyle = "#111";

});
ctx.fill();
ctx.stroke();

seconds = (new Date().getTime() - startTime) / 1e3;
ticks++;
document.querySelector(".ticker").innerHTML = `${
myBoids.flock.length
} boids at ${d3.mean(speeds)} frames per second`;

if (Math.round(seconds) !== secondsRounded) {
speeds.push(ticks);
if (speeds.length > 2) speeds.shift();
secondsRounded = Math.round(seconds);
ticks = 0;
}

yield ctx.canvas;
}
}
Insert cell
thresholds = [
//[0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1]
0.005,
0.01,
0.015,
0.02,
0.025,
0.03,
0.035,
0.04,
0.045,
0.05,
0.055,
0.06,
0.065,
0.07,
0.075,
0.08,
0.085,
0.09,
0.095,
0.1
]
Insert cell
import { Boids } from "@harrystevens/vanilla-boids"
Insert cell
import { vecmath } from "@harrystevens/vector-math"
Insert cell
myBoids = {
const sim = new Boids();

// Add 500 boids
for (let i = 0; i < width * .5; i++) {
sim.add();
// yield sim
}
return sim;
}
Insert cell
myBoids
.height(height + 100)
.alignment(0.72)
.cohesion(0.5)
.separation(0.85)
.perception(20)
.quadtree(true)
.maxSpeed(2.75)
Insert cell
import { cwf } from "@codingwithfire/cwf-season-2-reusable-style-elements"
Insert cell
myBoids
Insert cell
contour = d3
.contourDensity()
.x(d => d.pos[0])
.y(d => d.pos[1])
// .thresholds(10)
.thresholds(function() {
return thresholds;
})
// .cellSize(1)
.size([width, height + 100])
Insert cell
height = 500
Insert cell
d3 = require("d3@6", "https://files-5ouswn75j.vercel.app/d3-contour.js")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more