()
| 89 | }; |
| 90 | |
| 91 | async function main(): Promise<void> { |
| 92 | const container = getEl<HTMLDivElement>('chart'); |
| 93 | |
| 94 | const binSizeInput = getEl<HTMLInputElement>('binSize'); |
| 95 | const binSizeValue = getEl<HTMLSpanElement>('binSizeValue'); |
| 96 | const colormapSelect = getEl<HTMLSelectElement>('colormap'); |
| 97 | const normalizationSelect = getEl<HTMLSelectElement>('normalization'); |
| 98 | const totalPointsEl = getEl<HTMLSpanElement>('totalPoints'); |
| 99 | const binnedPointsEl = getEl<HTMLSpanElement>('binnedPoints'); |
| 100 | |
| 101 | binSizeValue.textContent = binSizeInput.value; |
| 102 | binSizeInput.addEventListener('input', () => { |
| 103 | binSizeValue.textContent = binSizeInput.value; |
| 104 | }); |
| 105 | |
| 106 | const points = await createPointsChunked(1_000_000, 1337); |
| 107 | const n = points.length; |
| 108 | const fmt = new Intl.NumberFormat(undefined); |
| 109 | totalPointsEl.textContent = fmt.format(n); |
| 110 | |
| 111 | const baseOptions: ChartGPUOptions = { |
| 112 | theme: 'dark', |
| 113 | xAxis: { type: 'value' }, |
| 114 | yAxis: { type: 'value' }, |
| 115 | series: [ |
| 116 | { |
| 117 | type: 'scatter', |
| 118 | name: 'density', |
| 119 | data: points, |
| 120 | mode: 'density', |
| 121 | binSize: Number(binSizeInput.value), |
| 122 | densityColormap: colormapSelect.value as any, |
| 123 | densityNormalization: normalizationSelect.value as any, |
| 124 | sampling: 'none', |
| 125 | } as any, |
| 126 | ], |
| 127 | }; |
| 128 | |
| 129 | const chart = await ChartGPU.create(container, baseOptions); |
| 130 | |
| 131 | // Since points are sorted by x, we can estimate how many points the density pass will bin by |
| 132 | // mapping percent-space zoom to an x-window and doing a binary search. |
| 133 | const xMin = n > 0 ? points[0]![0] : 0; |
| 134 | const xMax = n > 0 ? points[n - 1]![0] : 1; |
| 135 | const xSpan = xMax - xMin; |
| 136 | |
| 137 | let lastBinnedText = ''; |
| 138 | let lastUpdateMs = 0; |
| 139 | const updateBinnedReadout = (): void => { |
| 140 | const zoom = chart.getZoomRange(); |
| 141 | const startPct = Math.max(0, Math.min(100, zoom?.start ?? 0)); |
| 142 | const endPct = Math.max(0, Math.min(100, zoom?.end ?? 100)); |
| 143 | const a = Math.min(startPct, endPct) / 100; |
| 144 | const b = Math.max(startPct, endPct) / 100; |
| 145 | |
| 146 | const visibleXMin = xMin + a * xSpan; |
| 147 | const visibleXMax = xMin + b * xSpan; |
| 148 | const i0 = lowerBoundByX(points, visibleXMin); |
no test coverage detected