feat: add zoom and pan functionality with wheel listener in SimulatorCanvas
parent
3ace72d0f8
commit
2744b398e3
|
|
@ -96,6 +96,29 @@ export const SimulatorCanvas = () => {
|
||||||
initSimulator();
|
initSimulator();
|
||||||
}, [initSimulator]);
|
}, [initSimulator]);
|
||||||
|
|
||||||
|
// Attach wheel listener as non-passive so preventDefault() works
|
||||||
|
useEffect(() => {
|
||||||
|
const el = canvasRef.current;
|
||||||
|
if (!el) return;
|
||||||
|
const onWheel = (e: WheelEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
const factor = e.deltaY < 0 ? 1.1 : 0.9;
|
||||||
|
const newZoom = Math.min(5, Math.max(0.1, zoomRef.current * factor));
|
||||||
|
const mx = e.clientX - rect.left;
|
||||||
|
const my = e.clientY - rect.top;
|
||||||
|
const worldX = (mx - panRef.current.x) / zoomRef.current;
|
||||||
|
const worldY = (my - panRef.current.y) / zoomRef.current;
|
||||||
|
const newPan = { x: mx - worldX * newZoom, y: my - worldY * newZoom };
|
||||||
|
zoomRef.current = newZoom;
|
||||||
|
panRef.current = newPan;
|
||||||
|
setZoom(newZoom);
|
||||||
|
setPan(newPan);
|
||||||
|
};
|
||||||
|
el.addEventListener('wheel', onWheel, { passive: false });
|
||||||
|
return () => el.removeEventListener('wheel', onWheel);
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Recalculate wire positions after web components initialize their pinInfo
|
// Recalculate wire positions after web components initialize their pinInfo
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
|
|
@ -536,7 +559,6 @@ export const SimulatorCanvas = () => {
|
||||||
onMouseMove={handleCanvasMouseMove}
|
onMouseMove={handleCanvasMouseMove}
|
||||||
onMouseUp={handleCanvasMouseUp}
|
onMouseUp={handleCanvasMouseUp}
|
||||||
onMouseLeave={() => { isPanningRef.current = false; setPan({ ...panRef.current }); setDraggedComponentId(null); }}
|
onMouseLeave={() => { isPanningRef.current = false; setPan({ ...panRef.current }); setDraggedComponentId(null); }}
|
||||||
onWheel={handleWheel}
|
|
||||||
onContextMenu={(e) => e.preventDefault()}
|
onContextMenu={(e) => e.preventDefault()}
|
||||||
onClick={() => setSelectedComponentId(null)}
|
onClick={() => setSelectedComponentId(null)}
|
||||||
style={{ cursor: isPanningRef.current ? 'grabbing' : wireInProgress ? 'crosshair' : 'default' }}
|
style={{ cursor: isPanningRef.current ? 'grabbing' : wireInProgress ? 'crosshair' : 'default' }}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue