Skip to content

Commit 4ef87f0

Browse files
fix: improve canvas pan/zoom robustness and event handling
1 parent 6522940 commit 4ef87f0

File tree

1 file changed

+25
-21
lines changed

1 file changed

+25
-21
lines changed

src/simulator/src/listeners.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -420,20 +420,18 @@ export default function startListeners() {
420420
}
421421

422422
// Keyboard zoom shortcuts
423-
// Zoom in: Cmd/Ctrl + '+' or Cmd/Ctrl + '='
424-
// (On US keyboards, '+' is Shift+'=', so we accept both to handle with/without Shift)
425-
// Also accepts keyCode 107 for numpad '+'
423+
// Zoom in: Cmd/Ctrl + '+' or numpad '+'
424+
// (On US keyboards, '+' is Shift+'='; we only check for '+' to avoid
425+
// triggering on plain '=' which would require Cmd/Ctrl+Shift+= instead)
426426
if (
427427
(simulationArea.controlDown &&
428-
(e.keyCode == 187 || e.keyCode == 171 || e.key == '+' || e.key == '=')) ||
428+
(e.keyCode == 187 || e.keyCode == 171 || e.key == '+')) ||
429429
e.keyCode == 107
430430
) {
431431
e.preventDefault()
432432
ZoomIn()
433433
}
434-
// Zoom out: Cmd/Ctrl + '-'
435-
// (Only '-', not '_', since '_' requires Shift and could cause confusion)
436-
// Also accepts keyCode 109 for numpad '-'
434+
// Zoom out: Cmd/Ctrl + '-' or numpad '-'
437435
if (
438436
(simulationArea.controlDown &&
439437
(e.keyCode == 189 || e.keyCode == 173 || e.key == '-')) ||
@@ -631,9 +629,9 @@ export default function startListeners() {
631629
*/
632630
function applyCanvasPan(deltaX, deltaY) {
633631
// Pan the canvas by adjusting origin
634-
// Invert delta: positive scroll should move content down/right
635-
globalScope.ox -= deltaX
636-
globalScope.oy -= deltaY
632+
// Positive scroll moves content down/right
633+
globalScope.ox += deltaX
634+
globalScope.oy += deltaY
637635

638636
// Round to avoid subpixel rendering issues
639637
globalScope.ox = Math.round(globalScope.ox)
@@ -661,12 +659,10 @@ export default function startListeners() {
661659
}
662660

663661
// Register wheel/trackpad event listeners for canvas panning
664-
document
665-
.getElementById('simulationArea')
666-
.addEventListener('mousewheel', handleCanvasPan)
667-
document
668-
.getElementById('simulationArea')
669-
.addEventListener('DOMMouseScroll', handleCanvasPan)
662+
const simulationAreaElement = document.getElementById('simulationArea')
663+
simulationAreaElement.addEventListener('wheel', handleCanvasPan, { passive: false })
664+
simulationAreaElement.addEventListener('mousewheel', handleCanvasPan, { passive: false })
665+
simulationAreaElement.addEventListener('DOMMouseScroll', handleCanvasPan, { passive: false })
670666

671667
document.addEventListener('cut', (e) => {
672668
if (verilogModeGet()) return
@@ -807,11 +803,13 @@ resizeTabs()
807803
*/
808804
function applyZoomChange(direction) {
809805
const zoomDelta = direction * 0.1 * DPR
810-
const newScale = globalScope.scale + zoomDelta
811-
812-
// Ensure scale stays within valid bounds
813-
if (newScale >= 0.5 * DPR && newScale <= 4 * DPR) {
814-
changeScale(zoomDelta)
806+
const targetScale = Math.max(
807+
0.5 * DPR,
808+
Math.min(4 * DPR, globalScope.scale + zoomDelta)
809+
)
810+
811+
if (targetScale !== globalScope.scale) {
812+
changeScale(targetScale - globalScope.scale)
815813
gridUpdateSet(true)
816814
scheduleUpdate()
817815
}
@@ -853,6 +851,8 @@ export function setZoomFromSlider(
853851
minZoom = 0.5 * DPR,
854852
maxZoom = 4 * DPR
855853
) {
854+
if (maxSliderValue === minSliderValue || maxZoom === minZoom) return
855+
856856
// Normalize slider value to 0-1 range
857857
const normalizedValue = (sliderValue - minSliderValue) / (maxSliderValue - minSliderValue)
858858

@@ -893,6 +893,10 @@ export function getZoomSliderValue(
893893
minZoom = 0.5 * DPR,
894894
maxZoom = 4 * DPR
895895
) {
896+
if (maxSliderValue === minSliderValue || maxZoom === minZoom) {
897+
return minSliderValue
898+
}
899+
896900
const currentScale = globalScope.scale
897901

898902
// Clamp current scale to valid range

0 commit comments

Comments
 (0)