1/** 2 * Move tool â drag a layer around the canvas, with optional snap-on-Ctrl 3 * to other layers' edges/centers and to canvas edges/center. 4 * 5 * Owns its own input handlers (begin/drag/end) and reads/writes the 6 * shared `state` store directly. The factory takes a small dependency 7 * bag for things that still live in galleryEditor.js â `activeLayer`, 8 * `saveState`, `composite` â so this module doesn't have to know about 9 * the orchestrator. 10 * 11 * @param {{ 12 * activeLayer: () => {id: string, canvas: HTMLCanvasElement, locked?: boolean} | null, 13 * saveState: (label?: string) => void, 14 * composite: () => void, 15 * }} deps 16 * @returns {{ begin: (e: Event) => void, drag: (e: Event) => void, end: () => void }} 17 */ 18import { state } from '../state.js'; 19import { canvasCoords } from '../canvas-coords.js'; 20import { computeSnap as computeSnapImpl } from '../snap.js'; 21 22export function createMoveTool({ activeLayer, saveState, composite }) { 23 function computeSnap(layer, nx, ny) { 24 return computeSnapImpl(layer, nx, ny, { 25 zoom: state.zoom, 26 canvasW: state.imgWidth, 27 canvasH: state.imgHeight, 28 otherLayers: state.layers.map(l => ({ 29 visible: l.visible, 30 id: l.id, 31 canvas: l.canvas, 32 offset: state.layerOffsets.get(l.id) || { x: 0, y: 0 }, 33 })), 34 }); 35 } 36 37 return { 38 begin(e) { 39 const layer = activeLayer(); 40 if (!layer || layer.locked) return; 41 saveState(); 42 state.moving = true; 43 const coords = canvasCoords(e, state.mainCanvas); 44 const off = state.layerOffsets.get(layer.id) || { x: 0, y: 0 }; 45 state.moveStartX = coords.x; 46 state.moveStartY = coords.y; 47 state.moveLayerOffsetX = off.x; 48 state.moveLayerOffsetY = off.y; 49 }, 50 drag(e) { 51 if (!state.moving) return; 52 e.preventDefault(); 53 const layer = activeLayer(); 54 if (!layer) return; 55 const coords = canvasCoords(e, state.mainCanvas); 56 const dx = coords.x - state.moveStartX; 57 const dy = coords.y - state.moveStartY; 58 let nx = state.moveLayerOffsetX + dx; 59 let ny = state.moveLayerOffsetY + dy; 60 // Ctrl held = snap to canvas edges/center and to every other 61 // visible layer's edges/center. Opt-in to avoid a "sticky" feel 62 // during normal drags. 63 if (e.ctrlKey || e.metaKey) { 64 const snapped = computeSnap(layer, nx, ny); 65 nx = snapped.x; 66 ny = snapped.y; 67 state.activeSnapGuides = snapped.guides; 68 } else { 69 state.activeSnapGuides = null; 70 } 71 state.layerOffsets.set(layer.id, { x: nx, y: ny }); 72 composite(); 73 }, 74 end() { 75 state.moving = false; 76 state.activeSnapGuides = null; 77 }, 78 }; 79}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.