spb/svgarden Public
SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)
HTML 79.2%
Astro 10.3%
JavaScript 6%
CSS 3.7%
Shell 0.8%
1<!--2 ============================================================3 SVGarden — https://www.svgarden.dev4 Author : Simon-Pierre Boucher5 Contact: contact@spboucher.ai6 File : snippets/charts/chart-sparkline-live.html7 Desc : Live sparkline — new points stream in, old ones slide out8 ============================================================9-->10<!--svgarden11title: Live sparkline12slug: chart-sparkline-live13category: charts14tags: [chart, sparkline, live, streaming, js]15difficulty: advanced16techniques: ["fixed-window data buffer", "points attribute rewrite", "transition retrigger", prefers-reduced-motion]17how_it_works: >18 The script keeps a fixed-length array as a sliding window: every tick pushes a19 new random-walk value, shifts the oldest out, and rewrites the polyline's20 points attribute from scratch — with 22 points that is far cheaper than any21 clever incremental DOM surgery. The slide illusion is a transition retrigger22 trick: after each rewrite the group is jumped 10 units right with transitions23 disabled (the new geometry then overlaps the old frame exactly), and one24 requestAnimationFrame later the transition is re-enabled and the group eases25 back to zero. The tick delay is re-read from --sg-duration on every cycle via26 a setTimeout chain, so the speed slider takes effect on the very next point,27 and prefers-reduced-motion stops the stream after the first paint.28customizable:29 - { var: "--sg-color", label: "Line color", type: color, default: "#7F77DD" }30 - { var: "--sg-size", label: "Width", type: range, min: 140, max: 380, default: 220, unit: px }31 - { var: "--sg-duration", label: "Tick every", type: range, min: 0.3, max: 2, step: 0.1, default: 0.7, unit: s }32created: 2026-08-1033-->34<div class="sg-chart-sparkline-live" style="--sg-color:#7F77DD; --sg-size:220px; --sg-duration:0.7s;">35 <svg viewBox="0 0 220 60" role="img" aria-label="Live-updating sparkline of streaming values">36 <title>Live sparkline</title>37 <line class="sg-chart-sparkline-live-base" x1="5" y1="58" x2="215" y2="58" />38 <g class="sg-chart-sparkline-live-win">39 <polygon class="sg-chart-sparkline-live-area" points="" />40 <polyline class="sg-chart-sparkline-live-line" points="" />41 </g>42 <circle class="sg-chart-sparkline-live-dot" cx="215" cy="30" r="3" />43 </svg>44</div>45<script>46 document.querySelectorAll('.sg-chart-sparkline-live:not([data-sg-init])').forEach(function (root) {47 root.setAttribute('data-sg-init', '');48 var line = root.querySelector('.sg-chart-sparkline-live-line');49 var area = root.querySelector('.sg-chart-sparkline-live-area');50 var win = root.querySelector('.sg-chart-sparkline-live-win');51 var dot = root.querySelector('.sg-chart-sparkline-live-dot');52 var N = 22, data = [30];53 for (var i = 1; i < N; i++) data.push(Math.max(8, Math.min(52, data[i - 1] + Math.random() * 14 - 7)));54 function render() {55 var pts = data.map(function (v, i) { return (5 + i * 10) + ',' + (58 - v).toFixed(1); }).join(' ');56 line.setAttribute('points', pts);57 area.setAttribute('points', pts + ' 215,58 5,58');58 dot.setAttribute('cy', (58 - data[N - 1]).toFixed(1));59 }60 render();61 if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;62 function tick() {63 data.push(Math.max(8, Math.min(52, data[N - 1] + Math.random() * 14 - 7)));64 data.shift();65 win.style.transition = 'none';66 render();67 win.style.transform = 'translateX(10px)';68 requestAnimationFrame(function () {69 var s = parseFloat(getComputedStyle(root).getPropertyValue('--sg-duration')) || 0.7;70 win.style.transition = 'transform ' + s + 's linear';71 win.style.transform = 'translateX(0)';72 setTimeout(tick, s * 1000);73 });74 }75 tick();76 });77</script>78<style>79 .sg-chart-sparkline-live {80 width: var(--sg-size);81 }82 .sg-chart-sparkline-live svg {83 display: block;84 width: 100%;85 overflow: hidden;86 }87 .sg-chart-sparkline-live-base {88 stroke: rgba(128, 128, 128, 0.3);89 stroke-width: 1;90 }91 .sg-chart-sparkline-live-line {92 fill: none;93 stroke: var(--sg-color);94 stroke-width: 2;95 stroke-linecap: round;96 stroke-linejoin: round;97 }98 .sg-chart-sparkline-live-area {99 fill: var(--sg-color);100 opacity: 0.12;101 }102 .sg-chart-sparkline-live-dot {103 fill: var(--sg-color);104 transform-box: fill-box;105 transform-origin: center;106 animation: sg-chart-sparkline-live-pulse 1.4s ease-in-out infinite;107 }108 @keyframes sg-chart-sparkline-live-pulse {109 0%, 100% { transform: scale(1); opacity: 1; }110 50% { transform: scale(1.7); opacity: 0.55; }111 }112</style>113