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,
|
ObjectType,
|
||||||
tableFieldHeight,
|
tableFieldHeight,
|
||||||
tableHeaderHeight,
|
tableHeaderHeight,
|
||||||
|
gridSize,
|
||||||
|
gridCircleRadius,
|
||||||
} from "../../data/constants";
|
} from "../../data/constants";
|
||||||
import { Toast } from "@douyinfe/semi-ui";
|
import { Toast } from "@douyinfe/semi-ui";
|
||||||
import Table from "./Table";
|
import Table from "./Table";
|
||||||
@@ -272,6 +274,23 @@ export default function Canvas() {
|
|||||||
|
|
||||||
if (!e.isPrimary) return;
|
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) {
|
if (linking) {
|
||||||
setLinkingLine({
|
setLinkingLine({
|
||||||
...linkingLine,
|
...linkingLine,
|
||||||
@@ -283,11 +302,6 @@ export default function Canvas() {
|
|||||||
dragging.id !== null &&
|
dragging.id !== null &&
|
||||||
bulkSelectedElements.length
|
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) {
|
for (const element of bulkSelectedElements) {
|
||||||
if (element.type === ObjectType.TABLE) {
|
if (element.type === ObjectType.TABLE) {
|
||||||
const { x, y } = tables.find((e) => e.id === element.id);
|
const { x, y } = tables.find((e) => e.id === element.id);
|
||||||
@@ -312,8 +326,8 @@ export default function Canvas() {
|
|||||||
|
|
||||||
setDragging((prev) => ({
|
setDragging((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
prevX: currentX,
|
prevX: finalX,
|
||||||
prevY: currentY,
|
prevY: finalY,
|
||||||
}));
|
}));
|
||||||
} else if (
|
} else if (
|
||||||
panning.isPanning &&
|
panning.isPanning &&
|
||||||
@@ -339,8 +353,8 @@ export default function Canvas() {
|
|||||||
if (table.locked) return;
|
if (table.locked) return;
|
||||||
|
|
||||||
updateTable(dragging.id, {
|
updateTable(dragging.id, {
|
||||||
x: pointer.spaces.diagram.x + grabOffset.x,
|
x: finalX,
|
||||||
y: pointer.spaces.diagram.y + grabOffset.y,
|
y: finalY,
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
dragging.element === ObjectType.AREA &&
|
dragging.element === ObjectType.AREA &&
|
||||||
@@ -351,16 +365,16 @@ export default function Canvas() {
|
|||||||
if (area.locked) return;
|
if (area.locked) return;
|
||||||
|
|
||||||
updateArea(dragging.id, {
|
updateArea(dragging.id, {
|
||||||
x: pointer.spaces.diagram.x + grabOffset.x,
|
x: finalX,
|
||||||
y: pointer.spaces.diagram.y + grabOffset.y,
|
y: finalY,
|
||||||
});
|
});
|
||||||
} else if (dragging.element === ObjectType.NOTE && dragging.id !== null) {
|
} else if (dragging.element === ObjectType.NOTE && dragging.id !== null) {
|
||||||
const note = notes.find((t) => t.id === dragging.id);
|
const note = notes.find((t) => t.id === dragging.id);
|
||||||
if (note.locked) return;
|
if (note.locked) return;
|
||||||
|
|
||||||
updateNote(dragging.id, {
|
updateNote(dragging.id, {
|
||||||
x: pointer.spaces.diagram.x + grabOffset.x,
|
x: finalX,
|
||||||
y: pointer.spaces.diagram.y + grabOffset.y,
|
y: finalY,
|
||||||
});
|
});
|
||||||
} else if (areaResize.id !== -1) {
|
} else if (areaResize.id !== -1) {
|
||||||
if (areaResize.dir === "none") return;
|
if (areaResize.dir === "none") return;
|
||||||
@@ -371,28 +385,24 @@ export default function Canvas() {
|
|||||||
|
|
||||||
switch (areaResize.dir) {
|
switch (areaResize.dir) {
|
||||||
case "br":
|
case "br":
|
||||||
newDims.width = pointer.spaces.diagram.x - initCoords.x;
|
newDims.width = finalX - initCoords.x;
|
||||||
newDims.height = pointer.spaces.diagram.y - initCoords.y;
|
newDims.height = finalY - initCoords.y;
|
||||||
break;
|
break;
|
||||||
case "tl":
|
case "tl":
|
||||||
newDims.x = pointer.spaces.diagram.x;
|
newDims.x = finalX;
|
||||||
newDims.y = pointer.spaces.diagram.y;
|
newDims.y = finalY;
|
||||||
newDims.width =
|
newDims.width = initCoords.width - (finalX - initCoords.x);
|
||||||
initCoords.x + initCoords.width - pointer.spaces.diagram.x;
|
newDims.height = initCoords.height - (finalY - initCoords.y);
|
||||||
newDims.height =
|
|
||||||
initCoords.y + initCoords.height - pointer.spaces.diagram.y;
|
|
||||||
break;
|
break;
|
||||||
case "tr":
|
case "tr":
|
||||||
newDims.y = pointer.spaces.diagram.y;
|
newDims.y = finalY;
|
||||||
newDims.width = pointer.spaces.diagram.x - initCoords.x;
|
newDims.width = finalX - initCoords.x;
|
||||||
newDims.height =
|
newDims.height = initCoords.height - (finalY - initCoords.y);
|
||||||
initCoords.y + initCoords.height - pointer.spaces.diagram.y;
|
|
||||||
break;
|
break;
|
||||||
case "bl":
|
case "bl":
|
||||||
newDims.x = pointer.spaces.diagram.x;
|
newDims.x = finalX;
|
||||||
newDims.width =
|
newDims.width = initCoords.width - (finalX - initCoords.x);
|
||||||
initCoords.x + initCoords.width - pointer.spaces.diagram.x;
|
newDims.height = finalY - initCoords.y;
|
||||||
newDims.height = pointer.spaces.diagram.y - initCoords.y;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,8 +410,8 @@ export default function Canvas() {
|
|||||||
} else if (bulkSelectRectPts.show) {
|
} else if (bulkSelectRectPts.show) {
|
||||||
setBulkSelectRectPts((prev) => ({
|
setBulkSelectRectPts((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
x2: pointer.spaces.diagram.x,
|
x2: finalX,
|
||||||
y2: pointer.spaces.diagram.y,
|
y2: finalY,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -709,36 +719,6 @@ export default function Canvas() {
|
|||||||
backgroundColor: theme === "dark" ? darkBgTheme : "white",
|
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
|
<svg
|
||||||
id="diagram"
|
id="diagram"
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
@@ -748,6 +728,36 @@ export default function Canvas() {
|
|||||||
className="absolute w-full h-full touch-none"
|
className="absolute w-full h-full touch-none"
|
||||||
viewBox={`${viewBox.left} ${viewBox.top} ${viewBox.width} ${viewBox.height}`}
|
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) => (
|
{areas.map((a) => (
|
||||||
<Area
|
<Area
|
||||||
key={a.id}
|
key={a.id}
|
||||||
|
@@ -477,6 +477,8 @@ export default function ControlPanel({
|
|||||||
const fileImport = () => setModal(MODAL.IMPORT);
|
const fileImport = () => setModal(MODAL.IMPORT);
|
||||||
const viewGrid = () =>
|
const viewGrid = () =>
|
||||||
setSettings((prev) => ({ ...prev, showGrid: !prev.showGrid }));
|
setSettings((prev) => ({ ...prev, showGrid: !prev.showGrid }));
|
||||||
|
const snapToGrid = () =>
|
||||||
|
setSettings((prev) => ({ ...prev, snapToGrid: !prev.snapToGrid }));
|
||||||
const zoomIn = () =>
|
const zoomIn = () =>
|
||||||
setTransform((prev) => ({ ...prev, zoom: prev.zoom * 1.2 }));
|
setTransform((prev) => ({ ...prev, zoom: prev.zoom * 1.2 }));
|
||||||
const zoomOut = () =>
|
const zoomOut = () =>
|
||||||
@@ -1307,6 +1309,14 @@ export default function ControlPanel({
|
|||||||
function: viewGrid,
|
function: viewGrid,
|
||||||
shortcut: "Ctrl+Shift+G",
|
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: {
|
show_cardinality: {
|
||||||
state: settings.showCardinality ? (
|
state: settings.showCardinality ? (
|
||||||
<i className="bi bi-toggle-on" />
|
<i className="bi bi-toggle-on" />
|
||||||
|
@@ -4,6 +4,8 @@ import {
|
|||||||
noteWidth,
|
noteWidth,
|
||||||
noteRadius,
|
noteRadius,
|
||||||
noteFold,
|
noteFold,
|
||||||
|
gridSize,
|
||||||
|
gridCircleRadius,
|
||||||
} from "../data/constants";
|
} from "../data/constants";
|
||||||
|
|
||||||
export default function Thumbnail({ diagram, i, zoom, theme }) {
|
export default function Thumbnail({ diagram, i, zoom, theme }) {
|
||||||
@@ -15,21 +17,21 @@ export default function Thumbnail({ diagram, i, zoom, theme }) {
|
|||||||
>
|
>
|
||||||
<defs>
|
<defs>
|
||||||
<pattern
|
<pattern
|
||||||
id={"pattern-circles-" + i}
|
id={"pattern-grid-" + i}
|
||||||
x="0"
|
x={-gridCircleRadius}
|
||||||
y="0"
|
y={-gridCircleRadius}
|
||||||
width="10"
|
width={gridSize * zoom}
|
||||||
height="10"
|
height={gridSize * zoom}
|
||||||
patternUnits="userSpaceOnUse"
|
patternUnits="userSpaceOnUse"
|
||||||
patternContentUnits="userSpaceOnUse"
|
patternContentUnits="userSpaceOnUse"
|
||||||
>
|
>
|
||||||
<circle
|
<circle
|
||||||
id={"pattern-circle-" + i}
|
cx={gridCircleRadius * zoom}
|
||||||
cx="2"
|
cy={gridCircleRadius * zoom}
|
||||||
cy="2"
|
r={gridCircleRadius * zoom}
|
||||||
r="0.4"
|
|
||||||
fill="rgb(99, 152, 191)"
|
fill="rgb(99, 152, 191)"
|
||||||
></circle>
|
opacity="1"
|
||||||
|
/>
|
||||||
</pattern>
|
</pattern>
|
||||||
</defs>
|
</defs>
|
||||||
<rect
|
<rect
|
||||||
@@ -37,7 +39,7 @@ export default function Thumbnail({ diagram, i, zoom, theme }) {
|
|||||||
y="0"
|
y="0"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
fill={"url(#pattern-circles-" + i + ")"}
|
fill={"url(#pattern-grid-" + i + ")"}
|
||||||
></rect>
|
></rect>
|
||||||
<g
|
<g
|
||||||
style={{
|
style={{
|
||||||
|
@@ -5,6 +5,7 @@ const defaultSettings = {
|
|||||||
strictMode: false,
|
strictMode: false,
|
||||||
showFieldSummary: true,
|
showFieldSummary: true,
|
||||||
showGrid: true,
|
showGrid: true,
|
||||||
|
snapToGrid: false,
|
||||||
showDataTypes: true,
|
showDataTypes: true,
|
||||||
mode: "light",
|
mode: "light",
|
||||||
autosave: true,
|
autosave: true,
|
||||||
|
@@ -18,6 +18,8 @@ export const otherColor = "text-zinc-500";
|
|||||||
export const dateColor = "text-cyan-500";
|
export const dateColor = "text-cyan-500";
|
||||||
export const tableHeaderHeight = 50;
|
export const tableHeaderHeight = 50;
|
||||||
export const tableWidth = 220;
|
export const tableWidth = 220;
|
||||||
|
export const gridSize = 24;
|
||||||
|
export const gridCircleRadius = 0.85;
|
||||||
export const tableFieldHeight = 36;
|
export const tableFieldHeight = 36;
|
||||||
export const tableColorStripHeight = 7;
|
export const tableColorStripHeight = 7;
|
||||||
|
|
||||||
|
@@ -49,6 +49,7 @@ const en = {
|
|||||||
field_details: "Field details",
|
field_details: "Field details",
|
||||||
reset_view: "Reset view",
|
reset_view: "Reset view",
|
||||||
show_grid: "Show grid",
|
show_grid: "Show grid",
|
||||||
|
snap_to_grid: "Snap to grid",
|
||||||
show_datatype: "Show datatype",
|
show_datatype: "Show datatype",
|
||||||
show_cardinality: "Show cardinality",
|
show_cardinality: "Show cardinality",
|
||||||
theme: "Theme",
|
theme: "Theme",
|
||||||
|
Reference in New Issue
Block a user