WaveGrapher
by Santiago J
HTML
<canvas id="stage"></canvas>
CSS
#stage {
background-color: #eee;
}
JavaScript
var W = 720, H = 720;
var canvas = document.querySelector("#stage");
canvas.width = W;
canvas.height = H;
var ctx = canvas.getContext("2d");
var Wave = (function() {
var Wave = function(freqs, amps) {
this.freqs = freqs;
this.amps = amps;
this.w = this.h = 1;
this.backCanvas = document.createElement("canvas");
this.bctx = this.backCanvas.getContext("2d");
this.backOffset = 0;
// Normalize amplitudes
var sumAmps = 0;
for (var i = 0; i < amps.length; i++) {
sumAmps += amps[i];
}
for (var i = 0; i < amps.length; i++) {
amps[i] /= sumAmps;
}
};
Wave.prototype.setBox = function(w, h) {
this.w = w;
this.h = h;
this.backCanvas.width = 2*w;
this.backCanvas.height = h;
this.backDraw(this.backOffset);
};
Wave.prototype.backDraw = function(offset) {
var ctx = this.bctx;
var amp = this.h / 2;
var yc = amp;
var radPerPx = 2 * Math.PI / this.w;
var freqs = this.freqs;
var amps = this.amps;
var n = Math.min(freqs.length, amps.length);
var xEnd = 2 * this.w;
this.backOffset = offset;
ctx.clearRect(0, 0, xEnd, this.h);
ctx.beginPath();
for (var i = 0; i <= xEnd; i++) {
var val = 0;
for (var j = 0; j < n; j++) {
val += amps[j] * Math.sin((i+offset) * freqs[j] * radPerPx);
}
ctx.lineTo(i, yc - amp * val);
}
ctx.stroke();
};
Wave.prototype.quickDraw = function(ctx, x, y, w, h, offset) {
if (offset < this.backOffset || offset > this.backOffset + this.w) {
this.backDraw(offset);
}
ctx.drawImage(this.backCanvas,
offset - this.backOffset, 0, this.w, this.h,
x, y, w, h);
};
Wave.prototype.drawInBox =...