summaryrefslogtreecommitdiff
path: root/src/relabi/canvas.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/relabi/canvas.js')
-rw-r--r--src/relabi/canvas.js90
1 files changed, 79 insertions, 11 deletions
diff --git a/src/relabi/canvas.js b/src/relabi/canvas.js
index dfbffa0..d2c55a2 100644
--- a/src/relabi/canvas.js
+++ b/src/relabi/canvas.js
@@ -17,14 +17,14 @@ export default class RelabiCanvas {
// Speed of the wave in pixels per second
this.speed = 1 / 5;
- // Attach to the DOM
- this.parent = parent = document.body;
- this.canvas = document.createElement("canvas");
- this.ctx = this.canvas.getContext("2d");
- this.parent.appendChild(this.canvas);
+ // Position of current time on the screen, from the left
+ this.tZeroOffset = 20;
+ // Attach to the DOM
+ this.appendCanvas(parent);
// Initialize array
this.values = new Array(window.innerWidth).fill(0);
+ this.notes = [];
this.append([]);
// Clear the canvas
@@ -35,6 +35,16 @@ export default class RelabiCanvas {
}
/**
+ * Append the canvas
+ */
+ appendCanvas(parent) {
+ this.parent = parent || document.body;
+ this.canvas = this.canvas || document.createElement("canvas");
+ this.ctx = this.ctx || this.canvas.getContext("2d");
+ this.parent.appendChild(this.canvas);
+ }
+
+ /**
* Draw the next frame
*/
requestAnimationFrame(frame) {
@@ -63,10 +73,20 @@ export default class RelabiCanvas {
/**
* Append values
*/
- append(time, values) {
+ append(time, values, notes) {
this.lastAppendTime = time;
this.lastAppendFrame = this.lastFrame;
- this.values = this.values.concat(values).slice(-this.canvas.width);
+ this.values = this.values
+ .concat(values)
+ .slice(-this.canvas.width)
+ .sort((a, b) => a[0] - b[0]);
+
+ if (notes?.length) {
+ this.notes = this.notes
+ .concat(notes)
+ .slice(-50)
+ .sort((a, b) => a[0] - b[0]);
+ }
}
/**
@@ -76,6 +96,7 @@ export default class RelabiCanvas {
this.clear();
this.drawRelabiWave(frame);
this.drawBounds();
+ this.drawNotes(frame);
}
/**
@@ -90,12 +111,22 @@ export default class RelabiCanvas {
const y = getWaveHeight(bound.level, height);
ctx.beginPath();
- ctx.setLineDash([10, 5]);
+ ctx.setLineDash([4, 4]);
+ ctx.lineWidth = 1;
ctx.strokeStyle = bound.color || "#888";
ctx.moveTo(0, y);
ctx.lineTo(width, y);
ctx.stroke();
}
+
+ // Draw the zero position
+ ctx.beginPath();
+ ctx.setLineDash([1, 1]);
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = "#666";
+ ctx.moveTo(width - this.tZeroOffset, 0);
+ ctx.lineTo(width - this.tZeroOffset, height);
+ ctx.stroke();
}
/**
@@ -110,7 +141,8 @@ export default class RelabiCanvas {
// Start the path
ctx.beginPath();
- ctx.strokeStyle = "white";
+ ctx.strokeStyle = "#dff";
+ ctx.lineWidth = 0.75;
ctx.setLineDash([]);
// This is the offset in seconds from the last frame we computed
@@ -130,13 +162,13 @@ export default class RelabiCanvas {
// Subtracting the frame offset pulls it negative.
const timeOffset = this.lastAppendTime + frameOffset - time;
- const x = width - timeOffset * this.speed * width - 10;
+ const x = width - timeOffset * this.speed * width - this.tZeroOffset;
+ const y = getWaveHeight(value, height);
if (x < 0) {
continue;
}
- const y = getWaveHeight(value, height);
if (index === 0) {
ctx.moveTo(x, y);
}
@@ -147,6 +179,42 @@ export default class RelabiCanvas {
// Paint the line
ctx.stroke();
}
+
+ /**
+ * Draw the notes
+ */
+ drawNotes(frame) {
+ const { canvas, ctx } = this;
+ const { width, height } = canvas;
+
+ // This is the offset in seconds from the last frame we computed
+ const frameOffset = (frame - this.lastAppendFrame) / 1000;
+
+ // Make a path connecting all values
+ for (const note of this.notes) {
+ const [time, value, direction] = note;
+ const timeOffset = this.lastAppendTime + frameOffset - time;
+ const x = width - timeOffset * this.speed * width - this.tZeroOffset;
+ const y = getWaveHeight(value, height);
+
+ // Don't draw notes that haven't played yet
+ if (x > width - this.tZeroOffset) {
+ continue;
+ }
+
+ // Draw notes as a dot that fades out
+ const opacity = 1 - (timeOffset * this.speed * width) / 1000;
+ if (opacity < 0.001) {
+ continue;
+ }
+ ctx.beginPath();
+ ctx.arc(x - 2.5, y, 5, 0, 2 * Math.PI);
+ ctx.fillStyle = direction
+ ? `rgba(255,128,192,${opacity})`
+ : `rgba(192,255,128,${opacity})`;
+ ctx.fill();
+ }
+ }
}
/**