diff --git a/src/components/EditorCanvas/Canvas.jsx b/src/components/EditorCanvas/Canvas.jsx index c7603b3..fb45870 100644 --- a/src/components/EditorCanvas/Canvas.jsx +++ b/src/components/EditorCanvas/Canvas.jsx @@ -7,6 +7,8 @@ import { ObjectType, tableFieldHeight, tableHeaderHeight, + gridSize, + gridCircleRadius, } from "../../data/constants"; import { Toast } from "@douyinfe/semi-ui"; import Table from "./Table"; @@ -272,6 +274,23 @@ export default function Canvas() { if (!e.isPrimary) return; + const isDragging = + dragging.element !== ObjectType.NONE && dragging.id !== null; + + const currentX = pointer.spaces.diagram.x + (isDragging ? grabOffset.x : 0); + const currentY = pointer.spaces.diagram.y + (isDragging ? grabOffset.y : 0); + + let finalX = currentX; + let finalY = currentY; + + if (settings.snapToGrid) { + finalX = Math.round(currentX / gridSize) * gridSize; + finalY = Math.round(currentY / gridSize) * gridSize; + } + + const deltaX = finalX - dragging.prevX; + const deltaY = finalY - dragging.prevY; + if (linking) { setLinkingLine({ ...linkingLine, @@ -283,11 +302,6 @@ export default function Canvas() { dragging.id !== null && bulkSelectedElements.length ) { - const currentX = pointer.spaces.diagram.x + grabOffset.x; - const currentY = pointer.spaces.diagram.y + grabOffset.y; - const deltaX = currentX - dragging.prevX; - const deltaY = currentY - dragging.prevY; - for (const element of bulkSelectedElements) { if (element.type === ObjectType.TABLE) { const { x, y } = tables.find((e) => e.id === element.id); @@ -312,8 +326,8 @@ export default function Canvas() { setDragging((prev) => ({ ...prev, - prevX: currentX, - prevY: currentY, + prevX: finalX, + prevY: finalY, })); } else if ( panning.isPanning && @@ -339,8 +353,8 @@ export default function Canvas() { if (table.locked) return; updateTable(dragging.id, { - x: pointer.spaces.diagram.x + grabOffset.x, - y: pointer.spaces.diagram.y + grabOffset.y, + x: finalX, + y: finalY, }); } else if ( dragging.element === ObjectType.AREA && @@ -351,16 +365,16 @@ export default function Canvas() { if (area.locked) return; updateArea(dragging.id, { - x: pointer.spaces.diagram.x + grabOffset.x, - y: pointer.spaces.diagram.y + grabOffset.y, + x: finalX, + y: finalY, }); } else if (dragging.element === ObjectType.NOTE && dragging.id !== null) { const note = notes.find((t) => t.id === dragging.id); if (note.locked) return; updateNote(dragging.id, { - x: pointer.spaces.diagram.x + grabOffset.x, - y: pointer.spaces.diagram.y + grabOffset.y, + x: finalX, + y: finalY, }); } else if (areaResize.id !== -1) { if (areaResize.dir === "none") return; @@ -371,28 +385,24 @@ export default function Canvas() { switch (areaResize.dir) { case "br": - newDims.width = pointer.spaces.diagram.x - initCoords.x; - newDims.height = pointer.spaces.diagram.y - initCoords.y; + newDims.width = finalX - initCoords.x; + newDims.height = finalY - initCoords.y; break; case "tl": - newDims.x = pointer.spaces.diagram.x; - newDims.y = pointer.spaces.diagram.y; - newDims.width = - initCoords.x + initCoords.width - pointer.spaces.diagram.x; - newDims.height = - initCoords.y + initCoords.height - pointer.spaces.diagram.y; + newDims.x = finalX; + newDims.y = finalY; + newDims.width = initCoords.width - (finalX - initCoords.x); + newDims.height = initCoords.height - (finalY - initCoords.y); break; case "tr": - newDims.y = pointer.spaces.diagram.y; - newDims.width = pointer.spaces.diagram.x - initCoords.x; - newDims.height = - initCoords.y + initCoords.height - pointer.spaces.diagram.y; + newDims.y = finalY; + newDims.width = finalX - initCoords.x; + newDims.height = initCoords.height - (finalY - initCoords.y); break; case "bl": - newDims.x = pointer.spaces.diagram.x; - newDims.width = - initCoords.x + initCoords.width - pointer.spaces.diagram.x; - newDims.height = pointer.spaces.diagram.y - initCoords.y; + newDims.x = finalX; + newDims.width = initCoords.width - (finalX - initCoords.x); + newDims.height = finalY - initCoords.y; break; } @@ -400,8 +410,8 @@ export default function Canvas() { } else if (bulkSelectRectPts.show) { setBulkSelectRectPts((prev) => ({ ...prev, - x2: pointer.spaces.diagram.x, - y2: pointer.spaces.diagram.y, + x2: finalX, + y2: finalY, })); } }; @@ -709,36 +719,6 @@ export default function Canvas() { backgroundColor: theme === "dark" ? darkBgTheme : "white", }} > - {settings.showGrid && ( - - - - - - - - - )} + {settings.showGrid && ( + <> + + + + + + + + )} {areas.map((a) => ( setModal(MODAL.IMPORT); const viewGrid = () => setSettings((prev) => ({ ...prev, showGrid: !prev.showGrid })); + const snapToGrid = () => + setSettings((prev) => ({ ...prev, snapToGrid: !prev.snapToGrid })); const zoomIn = () => setTransform((prev) => ({ ...prev, zoom: prev.zoom * 1.2 })); const zoomOut = () => @@ -1307,6 +1309,14 @@ export default function ControlPanel({ function: viewGrid, shortcut: "Ctrl+Shift+G", }, + snap_to_grid: { + state: settings.snapToGrid ? ( + + ) : ( + + ), + function: snapToGrid, + }, show_cardinality: { state: settings.showCardinality ? ( diff --git a/src/components/Thumbnail.jsx b/src/components/Thumbnail.jsx index e70ed6f..b95b676 100644 --- a/src/components/Thumbnail.jsx +++ b/src/components/Thumbnail.jsx @@ -4,6 +4,8 @@ import { noteWidth, noteRadius, noteFold, + gridSize, + gridCircleRadius, } from "../data/constants"; export default function Thumbnail({ diagram, i, zoom, theme }) { @@ -15,21 +17,21 @@ export default function Thumbnail({ diagram, i, zoom, theme }) { > + opacity="1" + />