Back in the day, music visualizers were magic. Whether it was the old Windows Media Player or Winamp, watching sound morph into motion felt like stepping into another dimension.

But somewhere along the way, the magic faded. Visualizers became rare, often tucked away in outdated software or bloated libraries with 100 dependencies.
So when our team set out to build Waviz, we had a simple but bold goal:
Bring back real-time, reactive music visuals — but this time, with no dependencies, full creative control, and real performance.
And we’d do it with just Canvas and Web Audio API.
Vision
Waviz isn’t just a tool — it’s a playground. We wanted to make a system that empowers both:
Tinkerers who want to dig deep into audio signals and manipulate visuals on a granular level, and Casual devs who just want to drop in a component and watch the beat come alive.
To do that, we split our architecture into two layers:
- Core Engine (vanilla JavaScript): A zero-dependency rendering engine built with the Canvas API and Web Audio API.
- React Wrapper: Plug-and-play components for rapid integration, touch interaction, and style presets.
But this post is about the heart of it all — how we made particles dance to your music with just Canvas.
What Can You Draw with Just Canvas?
We didn’t use D3.
We didn’t use P5.
Just <canvas>
and raw pixels.
Canvas gave us:
- Hardware-accelerated performance
- Low-level drawing control
- Freedom from the DOM
This meant we could render hundreds of particles per frame, animate with full control, and never worry about framework overhead. The core of Waviz operates by using clearRect()
to reset the canvas each frame, initiating a new drawing path with beginPath()
, rendering each particle or visual element with roundRect()
, and applying color with either fill()
or stroke()
.
All of this is powered by the CanvasRenderingContext2D
API, with physics-inspired properties like globalAlpha
, gravity
, and velocity
—all implemented in vanilla JavaScript, no graphics libraries attached.
Drawing Dots in React with Waviz
Our dots()
method takes in a 2D array of data points (usually derived from audio) and plots them as smooth, rounded rectangles — a.k.a., dots.
dots(data: number[][], samples: number = 100) {
const sampling = Math.ceil(data.length / samples);
for (let i = 0; i < data.length; i += sampling) {
this.ctx.roundRect(data[i][0], data[i][1], 1, 1, 1000);
}
}
Each dot is placed using roundRect()
— which creates a rectangle with extremely curved corners, making it appear circular. This method is surprisingly powerful: it gives each data point a subtle, smooth presence on the screen.

Building Particle Systems with Physics
Waviz builds particles using a lightweight internal class called particle
. It tracks attributes like position, velocity, gravity, and lifespan—updating and redrawing each one every frame.
Here’s the simplified structure:
class particle {
canvasSize: number[];
position: number[];
velocity: number[];
gravity: number;
live: boolean = true;
born: number = frame;
update(): void {
// Update velocity
this.velocity = [this.velocity[0], this.velocity[1] + this.gravity];
// Update position
const x = this.position[0] + this.velocity[0];
const y = this.position[1] + this.velocity[1];
this.position = [x, y];
}
Every few frames, new particles are “born” from real-time audio data. Then they:
- Fall based on gravity
- Move with random initial velocity
- Die once they leave the canvas or exceed lifespan
And during each render frame:
if (this.particleSystem) {
this.particleSystem.forEach((e, i) => {
// Set lifespan
if (frame - e.born > lifespan) {
e.live = false;
}
// Update and kill particles
if (e.live === true) {
e.update();
} else if (e.live === false || this.frame - e.born > 1) {
this.particleSystem.splice(i, 1);
}
// Draw Particle
this.ctx.roundRect(e.position[0], e.position[1], 1, 1, 1000);
});

We don’t rely on any animation frameworks — everything is pure Canvas API.
Canvas, Reimagined
From dots that pulse to particles that dance, everything you see in Waviz is drawn with just one humble tool — the HTML canvas. But behind that simplicity lies intention: a commitment to creative freedom, low-dependency rendering, and visuals that feel alive.
Whether you’re a developer looking to fine-tune visuals with raw audio data, or a hobbyist just looking to plug in and vibe, Waviz was built for you. It’s modular, lightweight, and ready to be hacked, customized, and reimagined.
So go ahead — drop a beat, spin your favorite track, and see what sound looks like.
Check out our documentation and presets at https://wavizjs.com
Star us on GitHub: https://github.com/Waviz-Team/Waviz
Built with love by the Waviz Team. Contributions welcome.