|
28 | 28 | ## Highlights |
29 | 29 |
|
30 | 30 | - **`ChartGPU` component (recommended)**: async create/dispose lifecycle + debounced `ResizeObserver` sizing |
31 | | -- **Event props**: `onClick`, `onCrosshairMove`, `onZoomChange`, etc. |
32 | | -- **Imperative `ref` API**: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`) |
33 | | -- **Hooks**: `useChartGPU(...)`, `useConnectCharts(..., syncOptions?)` |
34 | | -- **Helper re-exports (from `@chartgpu/chartgpu`)**: `createChart`, `connectCharts`, `createAnnotationAuthoring` |
| 31 | +- **Event props**: `onClick`, `onCrosshairMove`, `onZoomChange`, `onDataAppend`, `onDeviceLost`, etc. |
| 32 | +- **Imperative `ref` API**: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`, `needsRender`, `renderFrame`, `getRenderMode`, `setRenderMode`) |
| 33 | +- **Hooks**: `useChartGPU(...)`, `useGPUContext()`, `useConnectCharts(..., syncOptions?)` |
| 34 | +- **Helper re-exports (from `@chartgpu/chartgpu`)**: `createChart`, `connectCharts`, `createPipelineCache`, `getPipelineCacheStats`, `destroyPipelineCache`, `createAnnotationAuthoring` |
35 | 35 |
|
36 | 36 | ## Quick start |
37 | 37 |
|
@@ -85,15 +85,17 @@ Check browser compatibility at [caniuse.com/webgpu](https://caniuse.com/webgpu). |
85 | 85 | - **`ChartGPU`** React component (recommended) |
86 | 86 | - lifecycle management (async create + dispose) |
87 | 87 | - `ResizeObserver` resize (debounced) |
88 | | - - event props: `onClick`, `onCrosshairMove`, `onZoomChange`, etc. |
89 | | - - imperative `ref` API: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`) |
| 88 | + - event props: `onClick`, `onCrosshairMove`, `onZoomChange`, `onDataAppend`, `onDeviceLost`, etc. |
| 89 | + - multi-chart dashboards: `gpuContext` prop (share a `GPUDevice` across charts) |
| 90 | + - imperative `ref` API: `ChartGPUHandle` (`getChart`, `getContainer`, `appendData`, `setOption`, `setZoomRange`, `setInteractionX`, `getInteractionX`, `hitTest`, `needsRender`, `renderFrame`, `getRenderMode`, `setRenderMode`) |
90 | 91 | - **Hooks** |
91 | | - - `useChartGPU(containerRef, options)` — create/manage a chart instance |
| 92 | + - `useChartGPU(containerRef, options, gpuContext?)` — create/manage a chart instance (optionally share GPU resources) |
| 93 | + - `useGPUContext()` — create a shared `GPUAdapter` + `GPUDevice` + `PipelineCache` for multi-chart dashboards |
92 | 94 | - `useConnectCharts([chartA, chartB, ...], syncOptions?)` — sync crosshair/interaction-x (and optionally zoom) across charts |
93 | 95 | - **Deprecated** |
94 | 96 | - `ChartGPUChart` (legacy adapter; use `ChartGPU` instead) |
95 | 97 | - **Helper re-exports** (from peer dependency `@chartgpu/chartgpu`) |
96 | | - - `createChart`, `connectCharts`, `createAnnotationAuthoring` |
| 98 | + - `createChart`, `connectCharts`, `createAnnotationAuthoring`, `createPipelineCache`, `getPipelineCacheStats`, `destroyPipelineCache` |
97 | 99 |
|
98 | 100 | For details, start with the [API reference](./docs/API.md). |
99 | 101 |
|
@@ -133,6 +135,56 @@ disconnect(); |
133 | 135 |
|
134 | 136 | If you prefer a hook-driven approach, you can use `onReady` (or `useChartGPU`) to capture instances, then call `useConnectCharts(...)` once both are available. |
135 | 137 |
|
| 138 | +### External render mode (app-owned render loop) |
| 139 | + |
| 140 | +```tsx |
| 141 | +import { useEffect, useRef } from 'react'; |
| 142 | +import { ChartGPU } from 'chartgpu-react'; |
| 143 | +import type { ChartGPUHandle } from 'chartgpu-react'; |
| 144 | + |
| 145 | +function ExternalLoop() { |
| 146 | + const ref = useRef<ChartGPUHandle>(null); |
| 147 | + |
| 148 | + useEffect(() => { |
| 149 | + let raf = 0; |
| 150 | + const loop = () => { |
| 151 | + if (ref.current?.needsRender()) { |
| 152 | + ref.current.renderFrame(); |
| 153 | + } |
| 154 | + raf = requestAnimationFrame(loop); |
| 155 | + }; |
| 156 | + raf = requestAnimationFrame(loop); |
| 157 | + return () => cancelAnimationFrame(raf); |
| 158 | + }, []); |
| 159 | + |
| 160 | + return <ChartGPU ref={ref} options={{ ...options, renderMode: 'external' }} />; |
| 161 | +} |
| 162 | +``` |
| 163 | + |
| 164 | +### Multi-chart dashboards (shared GPU device + pipeline cache) |
| 165 | + |
| 166 | +```tsx |
| 167 | +import { ChartGPU, useGPUContext } from 'chartgpu-react'; |
| 168 | + |
| 169 | +function Dashboard() { |
| 170 | + const { adapter, device, pipelineCache, isReady, error } = useGPUContext(); |
| 171 | + |
| 172 | + if (error) return <div>{error.message}</div>; |
| 173 | + if (!isReady || !adapter || !device) return <div>Loading…</div>; |
| 174 | + |
| 175 | + const gpuContext = pipelineCache |
| 176 | + ? { adapter, device, pipelineCache } |
| 177 | + : { adapter, device }; |
| 178 | + |
| 179 | + return ( |
| 180 | + <> |
| 181 | + <ChartGPU options={optionsA} gpuContext={gpuContext} /> |
| 182 | + <ChartGPU options={optionsB} gpuContext={gpuContext} /> |
| 183 | + </> |
| 184 | + ); |
| 185 | +} |
| 186 | +``` |
| 187 | + |
136 | 188 | ### Annotation authoring UI (`createAnnotationAuthoring`) |
137 | 189 |
|
138 | 190 | ```tsx |
|
0 commit comments