Swarm Intelligence
60 "boids" on a canvas applying Reynolds' three rules — move toward and align with neighbors within 80 px, steer away under 25 px — with a capped speed and edges that wrap around: groups form, split and turn together, leaving short trails. A 2D canvas sharp on Retina, a loop that stops off screen, a still image when the user reduces motion. Computed emergent behavior, with no artificial intelligence and no interaction.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Liquid has 31 effects, including 6 free. Explore the category →
3 usage examples



How it works
The .fx-0415-root frame is 300 px tall and full width, and the canvas fits it (display: block, 100% × 100%). Internal size = displayed size × devicePixelRatio, drawing in CSS pixels through setTransform: measured at density 2, 1280 × 600 for 640 × 300. A ResizeObserver follows the frame; boids not yet placed, or left outside the frame when it shrinks, are placed again at random. Stable height after 20 resizes (measured in Chromium 151, Firefox 153 and WebKit 26).
On each frame, each boid looks at the other 59. Those within 80 px are its neighbors: it turns toward their center (cohesion, × 0.003), brings its velocity closer to their average velocity (alignment, × 0.05) and steers away from those within 25 px (separation, × 0.05). Its speed is capped at 3 px per frame; it leaves one side and comes back on the other. Nobody leads the group: the flocks arise from these three local rules, which is what emergent behavior means. The computation compares every pair, 3,540 distances per frame for 60 boids.
Each boid is a violet #a855f7 dot with a 3 px radius. The canvas is never cleared: an rgba(10, 10, 15, 0.15) veil per frame fades previous positions, giving a trail of about fifteen frames that shows the flight direction. The requestAnimationFrame loop stops when an IntersectionObserver sees the canvas leave the screen (measured: 0 frames per second off screen against 120 on screen) and resumes when it comes back; the swarm picks up where it was.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the script computes 100 steps without showing them (groups form), draws 8 for short trails, then stops: a still image of several flocks. Measured in all three engines: 0% of pixels changed in 500 ms. - Decorative role: the canvas has no text. If the swarm illustrates a point (birds, a bee swarm, a lab rule), write that point in HTML next to it, as in the examples.
- Fast motion: boids dart up to 3 px per frame and turn sharply; 7% of pixels change in 500 ms. Avoid placing long text on top; slow them down (
speed > 1.5) for a calm background. - Speed tied to the screen: everything is counted per frame; at 120 Hz, the swarm moves twice as fast as at 60 Hz.
Browser compatibility
2D canvas + 4.1 KB of JavaScript, no dependency. Measured in Chromium 151, Firefox 153 and WebKit 26: same flocks, internal size doubled at density 2, stable height, loop stopped off screen, still image under reduced motion. Measured cost per frame at 640 × 300: 0.1 ms of JavaScript in Chromium and 1 ms in Firefox for 60 boids; 0.7 ms and 2 ms for 300 boids (25 times more pairs). ResizeObserver exists since Chrome 64, Firefox 69 and Safari 13.1.
Without JavaScript, the frame stays bluish black, with no boids. Without IntersectionObserver, the loop also runs off screen; without ResizeObserver, the canvas follows window resizing only.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0415-root">
<div class="ai-swarm-container">
<canvas class="ai-swarm-canvas" width="393" height="280"></canvas>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Boid count (JS — length: 60) |
60 | Cost grows with the square of the count: 300 boids, 25 times more pairs (measured: 0.7 ms per frame in Chromium, 2 ms in Firefox). Beyond 500, split the frame into cells to compare only nearby neighbors. |
Neighborhood radii (JS — dist < 80 and dist < 25) |
80 px to see, 25 px to steer away | A 150 px view gives large single flocks; 40 px many small groups. Separation at 40 px loosens the groups. |
Forces (JS — 0.003, 0.05, 0.05) |
cohesion 0.003, separation 0.05, alignment 0.05 | Alignment at 0.15: very orderly flights. Separation at 0: boids pile into tight balls. Cohesion at 0.01: groups tighten and swirl. |
Top speed (JS — speed > 3 and both * 3) |
3 px per frame | 1.5 for a calm background; change all three values together. |
Trails (JS — rgba(10, 10, 15, 0.15)) |
15% veil per frame | 0.05 lengthens the trails, 1 removes them (crisp dots). Keep the .fx-0415-root background color. |
Dots (JS — '#a855f7' and arc(…, 3, …)) |
violet, 3 px radius | Dark 2 px dots on a light sky make starlings; golden ones, bees. |
Height (CSS — .fx-0415-root { height: 300px }) |
300 px | The canvas follows; a smaller frame gathers the swarm into a single cluster. |
FAQ
boid.vx *= -1 when boid.x goes out).