Last active
February 22, 2026 08:57
-
-
Save long1eu/7b3003095c422131d8596bf96c1ebed5 to your computer and use it in GitHub Desktop.
Taper daily usage chart
This file contains hidden or 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 lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Taper Chart</title> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { | |
| background: #0f0f13; | |
| color: #e0e0e0; | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; | |
| padding: 32px; | |
| } | |
| h1 { font-size: 1.3rem; font-weight: 500; color: #aaa; margin-bottom: 6px; } | |
| .subtitle { font-size: 0.85rem; color: #555; margin-bottom: 28px; } | |
| canvas { display: block; border-radius: 8px; background: #16161c; } | |
| .legend { display: flex; gap: 20px; margin-top: 14px; font-size: 0.8rem; color: #666; } | |
| .legend-item { display: flex; align-items: center; gap: 6px; } | |
| .swatch { width: 12px; height: 12px; border-radius: 3px; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Taper — Daily Usage</h1> | |
| <p class="subtitle">Feb 13 – Feb 23, 2026 · Scheduled window: 10:00–18:00</p> | |
| <canvas id="c"></canvas> | |
| <div class="legend"> | |
| <div class="legend-item"><div class="swatch" style="background:#4ade80"></div> Within window (done)</div> | |
| <div class="legend-item"><div class="swatch" style="background:#f87171"></div> Outside window (over)</div> | |
| <div class="legend-item"><div class="swatch" style="background:rgba(250,204,21,0.6)"></div> Daily max</div> | |
| </div> | |
| <script> | |
| var data = [ | |
| {label:"Feb 13\n(pre)", max:3000, done:0, over:152.5}, | |
| {label:"Feb 14\nD1", max:3000, done:25, over:321}, | |
| {label:"Feb 15\nD2", max:3000, done:125, over:178.8}, | |
| {label:"Feb 16\nD3", max:3000, done:137.5,over:550}, | |
| {label:"Feb 17\nD4", max:2700, done:15.4, over:229}, | |
| {label:"Feb 18\nD5", max:2700, done:30.6, over:201.5}, | |
| {label:"Feb 19\nD6", max:2700, done:100, over:450}, | |
| {label:"Feb 20\nD7", max:2430, done:0, over:700}, | |
| {label:"Feb 21\nD8", max:2430, done:100, over:380.1}, | |
| {label:"Feb 22\nD9", max:2430, done:0, over:65}, | |
| {label:"Feb 23\nD10", max:2187, done:0, over:50}, | |
| ]; | |
| var W = Math.min(window.innerWidth - 64, 900); | |
| var H = 340; | |
| var PAD = {top:24, right:24, bottom:56, left:52}; | |
| var c = document.getElementById("c"); | |
| c.width = W; c.height = H; | |
| var ctx = c.getContext("2d"); | |
| var chartW = W - PAD.left - PAD.right; | |
| var chartH = H - PAD.top - PAD.bottom; | |
| var maxVal = 3200; | |
| var n = data.length; | |
| var barGroup = chartW / n; | |
| var barW = barGroup * 0.6; | |
| var barOff = (barGroup - barW) / 2; | |
| function toY(v) { return PAD.top + chartH - (v / maxVal) * chartH; } | |
| // Grid lines | |
| ctx.strokeStyle = "#1e1e28"; | |
| ctx.lineWidth = 1; | |
| [0, 500, 1000, 1500, 2000, 2500, 3000].forEach(function(v) { | |
| var y = toY(v); | |
| ctx.beginPath(); ctx.moveTo(PAD.left, y); ctx.lineTo(PAD.left + chartW, y); ctx.stroke(); | |
| ctx.fillStyle = "#444"; | |
| ctx.font = "10px system-ui"; | |
| ctx.textAlign = "right"; | |
| ctx.fillText(v, PAD.left - 6, y + 3); | |
| }); | |
| // Bars | |
| data.forEach(function(d, i) { | |
| var x = PAD.left + i * barGroup + barOff; | |
| var doneH = (d.done / maxVal) * chartH; | |
| var overH = (d.over / maxVal) * chartH; | |
| var total = d.done + d.over; | |
| var totalH = (total / maxVal) * chartH; | |
| var baseY = toY(0); | |
| // over (bottom) | |
| ctx.fillStyle = "rgba(248,113,113,0.85)"; | |
| ctx.fillRect(x, baseY - overH, barW, overH); | |
| // done (on top) | |
| ctx.fillStyle = "rgba(74,222,128,0.85)"; | |
| ctx.fillRect(x, baseY - overH - doneH, barW, doneH); | |
| // total label | |
| if (total > 0) { | |
| ctx.fillStyle = "#888"; | |
| ctx.font = "10px system-ui"; | |
| ctx.textAlign = "center"; | |
| ctx.fillText(Math.round(total), x + barW/2, baseY - totalH - 5); | |
| } | |
| // x labels (two lines) | |
| var parts = d.label.split("\n"); | |
| ctx.fillStyle = "#555"; | |
| ctx.font = "10px system-ui"; | |
| ctx.textAlign = "center"; | |
| ctx.fillText(parts[0], x + barW/2, H - PAD.bottom + 14); | |
| ctx.fillStyle = "#3a3a4a"; | |
| ctx.fillText(parts[1] || "", x + barW/2, H - PAD.bottom + 26); | |
| }); | |
| // Daily max line | |
| ctx.beginPath(); | |
| ctx.strokeStyle = "rgba(250,204,21,0.55)"; | |
| ctx.lineWidth = 1.5; | |
| ctx.setLineDash([6, 4]); | |
| data.forEach(function(d, i) { | |
| var x = PAD.left + i * barGroup + barOff; | |
| var cx = x + barW/2; | |
| var y = toY(d.max); | |
| if (i === 0) ctx.moveTo(cx, y); | |
| else ctx.lineTo(cx, y); | |
| }); | |
| ctx.stroke(); | |
| ctx.setLineDash([]); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment