From 125579ec70950644aad51cb3cbde17cc625453e3 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sun, 24 Apr 2022 13:17:15 -0400 Subject: [PATCH] Chart is now a class, for easy usin' --- static/chart.html | 62 +-------------------------- static/chart.mjs | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 61 deletions(-) create mode 100644 static/chart.mjs diff --git a/static/chart.html b/static/chart.html index 46a962f..29dc459 100644 --- a/static/chart.html +++ b/static/chart.html @@ -2,67 +2,7 @@ Chart-O-Matic - +

The Amazing Chart-O-Matic

diff --git a/static/chart.mjs b/static/chart.mjs new file mode 100644 index 0000000..2fbfc8a --- /dev/null +++ b/static/chart.mjs @@ -0,0 +1,105 @@ +/** @typedef {Number} Duration */ + const Millisecond = 1 + const Second = 1000 * Millisecond + + /** + * A chart of historical values. + * + * Curently this assumes all values are between 0 and 1, + * since that's all I need. + */ +class HistoryChart { + /** + * @param {Element} canvas Canvas element to draw on + * @param {string} strokeStyle strokeStyle to draw in + * @param {Duration} duration Time to display history for + */ + constructor(canvas, strokeStyle, duration) { + this.canvas = canvas + this.ctx = canvas.getContext("2d") + this.duration = duration + + this.data = [] + this.max = 1 + this.min = 0 + + // One canvas pixel = 20ms + canvas.width = duration / (20 * Millisecond) + + // Set origin to lower-left corner + this.ctx.scale(1, -1) + this.ctx.translate(0, -canvas.height) + + this.ctx.strokeStyle = strokeStyle + this.ctx.lineWdith = 2 + + this.draw() + } + + /** + * Add an event point at a given time. + * + * These must always be added in time order. + * + * This also cleans up the event list, + * purging anything that is too old to be displayed. + * + * @param when Time the event happened + * @param value Value for the event + */ + Add(when, value) { + let now = Date.now() + let earliest = now - this.duration + + this.data.push([when, value]) + while (this.data[0][0] < earliest) { + this.data.shift() + } + + console.log(this.data) + } + + draw() { + let now = Date.now() + let earliest = now - this.duration + let xScale = this.canvas.width / this.duration + let y = 0 + + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) + + this.ctx.moveTo(0, y) + this.ctx.beginPath() + for (let point of this.data) { + let x = (point[0] - earliest) * xScale + this.ctx.lineTo(x, y) + y = point[1] * this.canvas.height + this.ctx.lineTo(x, y) + } + this.ctx.stroke() + + requestAnimationFrame(() => this.draw()) + } +} + +export {HistoryChart} + + +// XXX: remove after testing +let chart + +function init() { + let canvas = document.querySelector("#chart") + chart = new HistoryChart(canvas, "red", 20 * Second) + setInterval(update, 500 * Millisecond) +} + +function update() { + let now = Date.now() + chart.Add(now, Math.sin(now/Second)/2 + 0.5) +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init) +} else { + init() +} \ No newline at end of file