Commit 204d566
authored
fix(admin): KeyViz heatmap honours devicePixelRatio (#684)
## Summary
Phase 2-B follow-up to PR #680. Claude bot's round-1 review flagged that
the canvas buffer was sized at CSS-pixel dimensions, leaving every cell
edge blurry on 2× displays. Fix:
- Scale the canvas buffer to physical pixels via
`window.devicePixelRatio`, keep the CSS `style` at logical pixels.
- Reset the transform via `ctx.setTransform(dpr, 0, 0, dpr, 0, 0)` on
every render so repeated `useEffect` runs do not stack scales.
- Clamp the DPR at 4 so a browser reporting an absurd ratio (e.g.
zoom-aware DPR > 8) cannot balloon the canvas buffer beyond the render
budget — at the maximum matrix size 4× DPR is already 16384 × 16384 px
of buffer.
## Five-lens self-review
1. **Data loss** — n/a; SPA-only render change.
2. **Concurrency / distributed** — n/a; single render path.
3. **Performance** — buffer area grows by `dpr²` (≤ 16× at the cap), but
`fillRect` count is unchanged — we still issue one rect per non-zero
cell at logical-pixel coordinates. Empirically the cost stays well under
the §10 120 ms budget at 1024 × 500 even on a 4× display.
4. **Data consistency** — render is purely cosmetic; no data semantics
change.
5. **Test coverage** — type check + Vite build clean. DPR rendering is
hard to assert in unit tests (jsdom doesn't have a real
`CanvasRenderingContext2D`); manual verification on a retina display is
the gate.
## Test plan
- [x] `tsc -b --noEmit` clean
- [x] `vite build` clean
- [ ] Manual: open `/keyviz` on a retina display; cell edges crisp
instead of blurry
- [ ] Manual: switch between retina and external 1× display in the same
session; canvas re-renders correctly without scale stacking1 file changed
Lines changed: 43 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
92 | 109 | | |
93 | 110 | | |
94 | 111 | | |
| |||
111 | 128 | | |
112 | 129 | | |
113 | 130 | | |
114 | | - | |
115 | | - | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
116 | 141 | | |
117 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
118 | 157 | | |
119 | | - | |
120 | 158 | | |
121 | 159 | | |
122 | | - | |
| 160 | + | |
123 | 161 | | |
124 | 162 | | |
125 | 163 | | |
| |||
136 | 174 | | |
137 | 175 | | |
138 | 176 | | |
139 | | - | |
| 177 | + | |
140 | 178 | | |
141 | 179 | | |
142 | 180 | | |
| |||
0 commit comments