JSFiddle - React, Tailwind, and code Playground

HTML

<canvas id="c" height="200" width="500"></canvas>

JavaScript

function Wave(canvas, nCircles, nLines, nSteps) {
	this.canvas = canvas;
	if (this.canvas) {
		this.height = this.canvas.height;
		this.width = this.canvas.width;
		this.context = this.canvas.getContext("2d");
	}
	this.circles = this.generate(nCircles||4, nLines||7);
	this.nSteps = nSteps||400;
	this.draw();
}

Wave.prototype = {
	generate: function(nCircles, nLines) {
		// needs to be power of two plus one, which we get because we use 0..size inclusive
		var size = 2 << nLines;
		var circles = [];
		// generate n circles
		for (var i=0; i<nCircles; i++) {
			var points = [];
			// fill each circle with random walk - try to keep it inside 0..1 to avoid cropping
            var min, max;
			min = max = points[0] = points[size] = Math.random();
			for (var j = size / 2; j >= 1; j = j / 2) {
				for (var k = j; k < size; k += 2 * j) {
					// crop at 0..1 - if this is terrible, maybe scale instead
					points[k] = (points[k - j] + points[k + j]) / 2 + (Math.random() - 0.5)/(size/j);
                    if (points[k] < min) min = points[k];
                    if (points[k] > max) max = points[k];
				}
			}
            for (var p=0; p<points.length; p++) {
                points[p] = (points[p]-min)*(1/(max-min));
            }
			circles.push({phase: (Math.PI/nCircles)*i, points: points});
		}
		return circles;
	},
	draw: function() {
        var xSqueeze = 0.75;
		this.context.clearRect(0, 0, this.width, this.height);
		this.context.strokeStyle = "black";
		this.context.lineJoin = "miter";
		// circle 0 is far left, last is far right. Interpolate point between circle n and n+1
		for (var i=0; i<this.circles.length-1; i++) {
			// find center of each circle
			var ox = (i+0.5)*(this.width/this.circles.length),
				oy = this.height/2,
				circle = this.circles[i];
			this.context.beginPath();
			for (var o=0; o<circle.points.length; o++) {
				var x = ox+xSqueeze*circle.points[o]*Math.min(this.height/2,...