mirror of
https://github.com/drawdb-io/drawdb.git
synced 2025-07-18 10:11:24 +00:00
Change to square grid which moves when panning, add snap to grid functionality (#492)
* change to square grid which moves when panning, add snap to grid functionality * change grid back to circles, minor improvments * add new constants
This commit is contained in:
@@ -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 && (
|
||||
<svg className="absolute w-full h-full">
|
||||
<defs>
|
||||
<pattern
|
||||
id="pattern-circles"
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
patternUnits="userSpaceOnUse"
|
||||
patternContentUnits="userSpaceOnUse"
|
||||
>
|
||||
<circle
|
||||
id="pattern-circle"
|
||||
cx="4"
|
||||
cy="4"
|
||||
r="0.85"
|
||||
fill="rgb(99, 152, 191)"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill="url(#pattern-circles)"
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
<svg
|
||||
id="diagram"
|
||||
ref={canvasRef}
|
||||
@@ -748,6 +728,36 @@ export default function Canvas() {
|
||||
className="absolute w-full h-full touch-none"
|
||||
viewBox={`${viewBox.left} ${viewBox.top} ${viewBox.width} ${viewBox.height}`}
|
||||
>
|
||||
{settings.showGrid && (
|
||||
<>
|
||||
<defs>
|
||||
<pattern
|
||||
id="pattern-grid"
|
||||
x={-gridCircleRadius}
|
||||
y={-gridCircleRadius}
|
||||
width={gridSize}
|
||||
height={gridSize}
|
||||
patternUnits="userSpaceOnUse"
|
||||
patternContentUnits="userSpaceOnUse"
|
||||
>
|
||||
<circle
|
||||
cx={gridCircleRadius}
|
||||
cy={gridCircleRadius}
|
||||
r={gridCircleRadius}
|
||||
fill="rgb(99, 152, 191)"
|
||||
opacity="1"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect
|
||||
x={viewBox.left}
|
||||
y={viewBox.top}
|
||||
width={viewBox.width}
|
||||
height={viewBox.height}
|
||||
fill="url(#pattern-grid)"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{areas.map((a) => (
|
||||
<Area
|
||||
key={a.id}
|
||||
|
@@ -477,6 +477,8 @@ export default function ControlPanel({
|
||||
const fileImport = () => 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 ? (
|
||||
<i className="bi bi-toggle-on" />
|
||||
) : (
|
||||
<i className="bi bi-toggle-off" />
|
||||
),
|
||||
function: snapToGrid,
|
||||
},
|
||||
show_cardinality: {
|
||||
state: settings.showCardinality ? (
|
||||
<i className="bi bi-toggle-on" />
|
||||
|
@@ -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 }) {
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id={"pattern-circles-" + i}
|
||||
x="0"
|
||||
y="0"
|
||||
width="10"
|
||||
height="10"
|
||||
id={"pattern-grid-" + i}
|
||||
x={-gridCircleRadius}
|
||||
y={-gridCircleRadius}
|
||||
width={gridSize * zoom}
|
||||
height={gridSize * zoom}
|
||||
patternUnits="userSpaceOnUse"
|
||||
patternContentUnits="userSpaceOnUse"
|
||||
>
|
||||
<circle
|
||||
id={"pattern-circle-" + i}
|
||||
cx="2"
|
||||
cy="2"
|
||||
r="0.4"
|
||||
cx={gridCircleRadius * zoom}
|
||||
cy={gridCircleRadius * zoom}
|
||||
r={gridCircleRadius * zoom}
|
||||
fill="rgb(99, 152, 191)"
|
||||
></circle>
|
||||
opacity="1"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect
|
||||
@@ -37,7 +39,7 @@ export default function Thumbnail({ diagram, i, zoom, theme }) {
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%"
|
||||
fill={"url(#pattern-circles-" + i + ")"}
|
||||
fill={"url(#pattern-grid-" + i + ")"}
|
||||
></rect>
|
||||
<g
|
||||
style={{
|
||||
|
@@ -5,6 +5,7 @@ const defaultSettings = {
|
||||
strictMode: false,
|
||||
showFieldSummary: true,
|
||||
showGrid: true,
|
||||
snapToGrid: false,
|
||||
showDataTypes: true,
|
||||
mode: "light",
|
||||
autosave: true,
|
||||
|
@@ -18,6 +18,8 @@ export const otherColor = "text-zinc-500";
|
||||
export const dateColor = "text-cyan-500";
|
||||
export const tableHeaderHeight = 50;
|
||||
export const tableWidth = 220;
|
||||
export const gridSize = 24;
|
||||
export const gridCircleRadius = 0.85;
|
||||
export const tableFieldHeight = 36;
|
||||
export const tableColorStripHeight = 7;
|
||||
|
||||
|
@@ -49,6 +49,7 @@ const en = {
|
||||
field_details: "Field details",
|
||||
reset_view: "Reset view",
|
||||
show_grid: "Show grid",
|
||||
snap_to_grid: "Snap to grid",
|
||||
show_datatype: "Show datatype",
|
||||
show_cardinality: "Show cardinality",
|
||||
theme: "Theme",
|
||||
|
Reference in New Issue
Block a user