* Main setup: initializes GPUContext, createRenderCoordinator (low-level API), * continuous render loop, and GPU timing probes for performance measurement.
()
| 199 | * continuous render loop, and GPU timing probes for performance measurement. |
| 200 | */ |
| 201 | async function main(): Promise<void> { |
| 202 | const container = document.getElementById('chart'); |
| 203 | if (!(container instanceof HTMLElement)) throw new Error('Chart container (#chart) not found'); |
| 204 | |
| 205 | const samplingEnabledEl = document.getElementById('samplingEnabled'); |
| 206 | const benchmarkModeEl = document.getElementById('benchmarkMode'); |
| 207 | const autoBoundsVisibleEl = document.getElementById('autoBoundsVisible'); |
| 208 | const resetZoomEl = document.getElementById('resetZoom'); |
| 209 | if (!(samplingEnabledEl instanceof HTMLInputElement)) throw new Error('samplingEnabled checkbox not found'); |
| 210 | if (!(benchmarkModeEl instanceof HTMLInputElement)) throw new Error('benchmarkMode checkbox not found'); |
| 211 | if (!(autoBoundsVisibleEl instanceof HTMLInputElement)) throw new Error('autoBoundsVisible checkbox not found'); |
| 212 | if (!(resetZoomEl instanceof HTMLButtonElement)) throw new Error('resetZoom button not found'); |
| 213 | |
| 214 | // Ensure numeric readout is consistent (HTML already sets this, but keep it robust). |
| 215 | setText('pointCount', formatInt(TOTAL_POINTS)); |
| 216 | |
| 217 | // Create a canvas under #chart. |
| 218 | const canvas = document.createElement('canvas'); |
| 219 | canvas.style.display = 'block'; |
| 220 | canvas.style.width = '100%'; |
| 221 | canvas.style.height = '100%'; |
| 222 | container.appendChild(canvas); |
| 223 | |
| 224 | let gpuContext: GPUContext | null = null; |
| 225 | let coordinator: RenderCoordinator | null = null; |
| 226 | let coordinatorTargetFormat: GPUTextureFormat | null = null; |
| 227 | let lastConfigured: { width: number; height: number; format: GPUTextureFormat } | null = null; |
| 228 | |
| 229 | let sliderHost: HTMLDivElement | null = null; |
| 230 | let slider: DataZoomSlider | null = null; |
| 231 | let unsubscribeZoom: (() => void) | null = null; |
| 232 | |
| 233 | let zoomRange: ZoomRange | null = null; |
| 234 | |
| 235 | const { data } = createMillionPointsData(); |
| 236 | |
| 237 | const createUserOptions = (sampling: SeriesSampling, autoBounds: 'visible' | 'global'): ChartGPUOptions => ({ |
| 238 | grid: { left: 70, right: 24, top: 24, bottom: 44 }, |
| 239 | xAxis: { type: 'value', min: 0, max: X_MAX, name: 'Index' }, |
| 240 | yAxis: { type: 'value', autoBounds, name: 'Value' }, |
| 241 | tooltip: { show: false }, |
| 242 | dataZoom: [{ type: 'inside' }, { type: 'slider' }], |
| 243 | palette: ['#4a9eff'], |
| 244 | animation: false, |
| 245 | series: [ |
| 246 | { |
| 247 | type: 'line', |
| 248 | name: '1,000,000 points', |
| 249 | data, |
| 250 | color: '#4a9eff', |
| 251 | lineStyle: { width: 1, opacity: 1 }, |
| 252 | sampling, |
| 253 | samplingThreshold: DEFAULT_SAMPLING_THRESHOLD, |
| 254 | }, |
| 255 | ], |
| 256 | }); |
| 257 | |
| 258 | const applyAutoBounds = ( |
no test coverage detected