Last active
January 12, 2024 07:16
-
-
Save mtvbrianking/943fe580e5432f41f6ca154a5d92182a to your computer and use it in GitHub Desktop.
chart.js timeseries demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>chart.js timeseries demo</title> | |
</head> | |
<body style="padding: 25px; margin: 25px;"> | |
<div style="width: 85%"> | |
<button id="reset-zoom">Reset Zoom</button> | |
<button id="fetch-today">Today</button> | |
<button id="fetch-yesterday">Yesterday</button> | |
<!-- <button id="fetch-week">This week</button> --> | |
<!-- <button id="fetch-month">This Month</button> --> | |
<!-- <button id="fetch-quarter">This Quarter</button> --> | |
<!-- <button id="fetch-year">This Year</button> --> | |
<canvas id="my-chart" /> | |
</div> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script> | |
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/index.min.js"></script> --> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-adapter-date-fns.bundle.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/hammer.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-zoom.min.js"></script> | |
<script type="module"> | |
import { format, subDays, getTime, startOfDay, endOfDay } from "https://cdn.jsdelivr.net/npm/[email protected]/+esm"; | |
function seedData(start, end) { | |
console.log('seeding', { start: start, end: end }); | |
const data = []; | |
let y = 100; | |
for (let x = start; x <= end; x += 1000) { | |
y += 5 - Math.random() * 10; | |
data.push({ x, y }); | |
} | |
return data; | |
} | |
function fetchData(x1, x2) { | |
const step = Math.max(1, Math.round((x2 - x1) / 100000)); | |
const data = []; | |
let i = 0; | |
while (i < seed.length && seed[i].x < x1) { | |
i++; | |
} | |
while (i < seed.length && seed[i].x <= x2) { | |
data.push(seed[i]); | |
i += step; | |
} | |
// let dur = Math.floor(x2 - x1); | |
// console.log(`Fetched: ${data.length} from ${Math.floor(x1)} to ${Math.floor(x2)} for ${dur.toLocaleString("en-US")}`); | |
return data; | |
} | |
// console.log("fetchData(start, end).length", fetchData(start, end).length); | |
function startFetch({chart}) { | |
const {min, max} = chart.scales.x; | |
// console.log('zoom', chart.getZoomLevel()); | |
console.log('Fetch data btn ' + Math.floor(min) + ' and ' + Math.floor(max)); | |
clearTimeout(timer); | |
timer = setTimeout(() => { | |
let fetched = fetchData(min, max); | |
chart.data.datasets[0].data = fetched; | |
chart.stop(); // make sure animations are not running | |
chart.update('none'); | |
}, 500); | |
} | |
// --------- | |
let timer; | |
let end = getTime(new Date()); // now | |
let start = getTime(subDays(end, 1)); // 2 days ago | |
let then = getTime(subDays(end, 7)); // a week ago | |
let seed = seedData(then, end); | |
// ------------------------------------- | |
const data = { | |
datasets: [ | |
{ | |
label: "# of orders", | |
// backgroundColor: '#eeeeee', | |
// borderColor: '#ff0000', | |
// fill: false, | |
data: fetchData(start, end) | |
} | |
] | |
}; | |
const scales = { | |
x: { | |
// type: "time", | |
type: "timeseries", | |
parsing: false, | |
// min: start, | |
// max: end, | |
min: (args) => { | |
const {chart, scale} = args; | |
return chart.data.datasets[0].data[0].x; | |
}, | |
max: (args) => { | |
const {chart, scale} = args; | |
let size = chart.data.datasets[0].data.length; | |
return chart.data.datasets[0].data[size - 1].x; | |
}, | |
ticks: { | |
autoSkip: true, | |
autoSkipPadding: 50, | |
maxRotation: 0 | |
}, | |
time: { | |
displayFormats: { | |
second: "HH:mm:ss", | |
minute: "HH:mm", | |
hour: "MMM-dd HH:mm", | |
day: "MMM-dd", | |
month: "yyyy-MM", | |
year: "yyyy", | |
} | |
}, | |
title: { | |
display: true, | |
text: "Period" | |
} | |
}, | |
y: { | |
type: "linear", | |
title: { | |
display: true, | |
text: "No of Orders" | |
} | |
} | |
}; | |
const config = { | |
type: "line", | |
data: data, | |
options: { | |
plugins: { | |
title: { | |
text: "Chart.js timescale demo", | |
display: true | |
}, | |
zoom: { | |
pan: { | |
enabled: true, | |
modifierKey: "ctrl", | |
onPanComplete: startFetch, | |
}, | |
zoom: { | |
drag: { | |
enabled: true | |
}, | |
mode: "x", | |
onZoomComplete: startFetch, | |
} | |
} | |
}, | |
scales: scales | |
} | |
}; | |
// Chart.register(zoomPlugin); esm | |
const ctx = document.getElementById("my-chart"); | |
const chart = new Chart(ctx, config); | |
window.chart = chart; | |
document.getElementById("reset-zoom").addEventListener("click", function () { | |
chart.resetZoom(); | |
console.log("zoom level: ", chart.getZoomLevel()); | |
}); | |
document.getElementById("fetch-today").addEventListener("click", function () { | |
let now = new Date(); | |
let from = getTime(startOfDay(now)); | |
let to = getTime(endOfDay(now)); | |
clearTimeout(timer); | |
timer = setTimeout(() => { | |
let fetched = fetchData(from, to); | |
chart.data.datasets[0].data = fetched; | |
chart.stop(); | |
chart.update('none'); | |
}, 500); | |
}); | |
document.getElementById("fetch-yesterday").addEventListener("click", function () { | |
let yesterday = subDays(new Date(), 1); | |
let from = getTime(startOfDay(yesterday)); | |
let to = getTime(endOfDay(yesterday)); | |
clearTimeout(timer); | |
timer = setTimeout(() => { | |
let fetched = fetchData(from, to); | |
chart.data.datasets[0].data = fetched; | |
chart.stop(); | |
chart.update('none'); | |
}, 500); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Working with time series data in MySQL