diff --git a/src/components/Builder/Builder.jsx b/src/components/Builder/Builder.jsx index 85e4982..2556783 100644 --- a/src/components/Builder/Builder.jsx +++ b/src/components/Builder/Builder.jsx @@ -113,7 +113,7 @@ export const Builder = ({ editor }) => { imageUrl, function (img) { img.set({ - left: 0, //Note that this starting pos is behind the sidebar + left: 240, //Note that this starting pos is behind the sidebar top: 0, scaleX: scaleFactor, scaleY: scaleFactor, diff --git a/src/components/DockBuilder/DockBuilder.jsx b/src/components/DockBuilder/DockBuilder.jsx index 41b08e7..ad6146f 100644 --- a/src/components/DockBuilder/DockBuilder.jsx +++ b/src/components/DockBuilder/DockBuilder.jsx @@ -414,14 +414,96 @@ export const DockBuilder = () => { }; function edgeDetectionAndSnap(options) { - if (this.isZoomed) { + if (editorMemo.getZoom() !== 1) { return; } // TODO: Edge detection and snap to object within snap range - // TODO: Detect if the object is within the snap range of the selected object - // TODO: detect if the selected object contains dockData and dockData contains itemName of DockPanelCategories.Accessories || DockPanelCategories.BoatLift2 || DockPanelCategories.BoatLift4 - // TODO: handle rotation of 0, 90, 180, 270 degrees + const selectedObj = options.target; + if (!selectedObj.dockData) return; + + // TODO: Detect if the selected object is in the allowed categories + const snapCategories = [ + DockPanelCategories.Accessories, + DockPanelCategories.BoatLift2, + DockPanelCategories.BoatLift4, + ]; + + if (!snapCategories.includes(selectedObj.dockData.itemName)) return; + + let closestSnapPoint = null; + let minDistance = edgeSnapThreshold; + + editorMemo.forEachObject((obj) => { + if (obj === selectedObj || !obj.dockData) return; + + // TODO: Only consider objects in the allowed categories + if (!snapCategories.includes(obj.dockData.itemName)) return; + + // TODO: handle rotation of 0, 90, 180, 270 degrees + const rotation = obj.angle % 360; + const isRotated = rotation !== 0 && rotation !== 180; + + const objCenter = obj.getCenterPoint(); + const selectedCenter = selectedObj.getCenterPoint(); + + // Calculate potential snap points + const snapPoints = []; + + // Center point + snapPoints.push(objCenter); + + // Edge points + if (!isRotated || rotation === 0 || rotation === 180) { + // Horizontal edges + snapPoints.push( + new fabric.Point(objCenter.x, obj.getBoundingRect().top) + ); + snapPoints.push( + new fabric.Point( + objCenter.x, + obj.getBoundingRect().top + obj.getBoundingRect().height + ) + ); + } + + if (!isRotated || rotation === 90 || rotation === 270) { + // Vertical edges + snapPoints.push( + new fabric.Point(obj.getBoundingRect().left, objCenter.y) + ); + snapPoints.push( + new fabric.Point( + obj.getBoundingRect().left + obj.getBoundingRect().width, + objCenter.y + ) + ); + } + + // Find closest snap point + snapPoints.forEach((point) => { + const distance = Math.sqrt( + Math.pow(selectedCenter.x - point.x, 2) + + Math.pow(selectedCenter.y - point.y, 2) + ); + + if (distance < minDistance) { + minDistance = distance; + closestSnapPoint = point; + } + }); + }); + + // Snap to closest point if found + if (closestSnapPoint) { + const selectedCenter = selectedObj.getCenterPoint(); + selectedObj.set({ + left: selectedObj.left + (closestSnapPoint.x - selectedCenter.x), + top: selectedObj.top + (closestSnapPoint.y - selectedCenter.y), + }); + selectedObj.setCoords(); + editorMemo.renderAll(); + } editorMemo.defaultCursor = "default"; prevPointer = null;