(clientX, clientY, newZoom)
| 1196 | } |
| 1197 | |
| 1198 | function zoomAtPoint(clientX, clientY, newZoom) { |
| 1199 | const wrapper = document.querySelector(".preview-wrapper"); |
| 1200 | if (!wrapper || !previewViewport) { |
| 1201 | setZoom(newZoom); |
| 1202 | return; |
| 1203 | } |
| 1204 | // OLED: zoom is pixel-perfect via updatePreviewSize, so skip cursor-anchored transform math. |
| 1205 | if (driverMode === "u8g2") { |
| 1206 | setZoom(newZoom); |
| 1207 | return; |
| 1208 | } |
| 1209 | const rect = wrapper.getBoundingClientRect(); |
| 1210 | const px = clientX - rect.left; |
| 1211 | const py = clientY - rect.top; |
| 1212 | const oldZ = clamp(zoomFactor || 1, 0.5, 3); |
| 1213 | const targetZ = clamp(newZoom, 0.5, 3); |
| 1214 | const wx = (px - viewportPanX) / oldZ; |
| 1215 | const wy = (py - viewportPanY) / oldZ; |
| 1216 | viewportPanX = px - wx * targetZ; |
| 1217 | viewportPanY = py - wy * targetZ; |
| 1218 | zoomFactor = targetZ; |
| 1219 | if (zoomSlider) zoomSlider.value = String(Math.round(zoomFactor * 100)); |
| 1220 | if (zoomInput) zoomInput.value = String(Math.round(zoomFactor * 100)); |
| 1221 | applyViewportTransform(); |
| 1222 | } |
| 1223 | |
| 1224 | document.addEventListener("keydown", (e) => { |
| 1225 | const tag = e.target && e.target.tagName ? e.target.tagName.toLowerCase() : ""; |
no test coverage detected