mirror of https://github.com/nealey/vail.git
Chart is now a class, for easy usin'
This commit is contained in:
parent
96decf8166
commit
125579ec70
|
@ -2,67 +2,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Chart-O-Matic</title>
|
<title>Chart-O-Matic</title>
|
||||||
<script>
|
<script type="module" src="chart.mjs"></script>
|
||||||
data = []
|
|
||||||
|
|
||||||
const Millisecond = 1
|
|
||||||
const Second = 1000 * Millisecond
|
|
||||||
const ChartWidth = 20 * Second
|
|
||||||
|
|
||||||
function draw(canvas) {
|
|
||||||
let ctx = canvas.getContext("2d")
|
|
||||||
let now = Date.now()
|
|
||||||
let begin = now - ChartWidth
|
|
||||||
|
|
||||||
let xScale = canvas.width / ChartWidth
|
|
||||||
|
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
|
||||||
ctx.save()
|
|
||||||
|
|
||||||
// Make 0,0 be the lower-left corner, like in PostScript
|
|
||||||
ctx.scale(1, -1)
|
|
||||||
ctx.translate(0, -canvas.height)
|
|
||||||
|
|
||||||
ctx.strokeStyle = "red"
|
|
||||||
ctx.lineWidth = 2
|
|
||||||
let y = 0
|
|
||||||
ctx.moveTo(0, y)
|
|
||||||
ctx.beginPath()
|
|
||||||
for (let point of data) {
|
|
||||||
let x = (point[0] - begin) * xScale
|
|
||||||
ctx.lineTo(x, y)
|
|
||||||
y = point[1] * canvas.height
|
|
||||||
ctx.lineTo(x, y)
|
|
||||||
}
|
|
||||||
ctx.stroke()
|
|
||||||
|
|
||||||
ctx.restore()
|
|
||||||
requestAnimationFrame(() => draw(canvas))
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
let now = Date.now()
|
|
||||||
let earliest = now - ChartWidth
|
|
||||||
|
|
||||||
data.push([now, Math.sin(now/Second)>0?1:0])
|
|
||||||
while (data[0][0] < earliest) {
|
|
||||||
data.shift()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
let canvas = document.querySelector("#chart")
|
|
||||||
canvas.width = ChartWidth / (20 * Millisecond)
|
|
||||||
setInterval(update, 50 * Millisecond)
|
|
||||||
draw(canvas)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.readyState === "loading") {
|
|
||||||
document.addEventListener("DOMContentLoaded", init)
|
|
||||||
} else {
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>The Amazing Chart-O-Matic</h1>
|
<h1>The Amazing Chart-O-Matic</h1>
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
Loading…
Reference in New Issue