()
| 83 | }; |
| 84 | |
| 85 | async function main(): Promise<void> { |
| 86 | const container = document.getElementById('chart'); |
| 87 | const autoScrollEl = document.getElementById('autoScroll'); |
| 88 | const resetEl = document.getElementById('reset'); |
| 89 | |
| 90 | if (!(container instanceof HTMLElement)) throw new Error('Chart container not found'); |
| 91 | if (!(autoScrollEl instanceof HTMLInputElement)) throw new Error('autoScroll control not found'); |
| 92 | if (!(resetEl instanceof HTMLButtonElement)) throw new Error('reset control not found'); |
| 93 | |
| 94 | let streamCfg: StreamConfig = DEFAULT_STREAM; |
| 95 | |
| 96 | let rawData: DataPoint[] = createSeedData(800); |
| 97 | let nextX = (() => { |
| 98 | const last = rawData[rawData.length - 1] as DataPoint | undefined; |
| 99 | if (!last) return 0; |
| 100 | const x = Array.isArray(last) ? last[0] : last.x; |
| 101 | return Number.isFinite(x) ? x : 0; |
| 102 | })(); |
| 103 | |
| 104 | let autoScroll = true; |
| 105 | autoScrollEl.checked = autoScroll; |
| 106 | |
| 107 | let options: ChartGPUOptions = createBaseOptions(rawData, autoScroll); |
| 108 | const chart = await ChartGPU.create(container, options); |
| 109 | const ro = attachCoalescedResizeObserver(container, chart); |
| 110 | |
| 111 | chart.resize(); |
| 112 | |
| 113 | const applyOptions = (): void => { |
| 114 | // When toggling autoScroll, keep the currently accumulated CPU-side data. |
| 115 | options = createBaseOptions(rawData, autoScroll); |
| 116 | chart.setOption(options); |
| 117 | }; |
| 118 | |
| 119 | autoScrollEl.addEventListener('change', () => { |
| 120 | autoScroll = autoScrollEl.checked === true; |
| 121 | applyOptions(); |
| 122 | }); |
| 123 | |
| 124 | const reset = (): void => { |
| 125 | rawData = createSeedData(800); |
| 126 | const last = rawData[rawData.length - 1] as DataPoint | undefined; |
| 127 | const lastX = last ? (Array.isArray(last) ? last[0] : last.x) : 0; |
| 128 | nextX = Number.isFinite(lastX) ? lastX : 0; |
| 129 | applyOptions(); |
| 130 | }; |
| 131 | |
| 132 | resetEl.addEventListener('click', reset); |
| 133 | |
| 134 | // Streaming loop: append small batches frequently. |
| 135 | let intervalId: number | null = null; |
| 136 | const startStreaming = (): void => { |
| 137 | if (intervalId !== null) return; |
| 138 | intervalId = window.setInterval(() => { |
| 139 | const batch: DataPoint[] = new Array(streamCfg.pointsPerTick); |
| 140 | for (let i = 0; i < streamCfg.pointsPerTick; i++) { |
| 141 | nextX += 0.02; |
| 142 | const y = |
no test coverage detected