Fix panning and dragging with zoom
This commit is contained in:
parent
cfa60763a0
commit
5661984992
@ -16,8 +16,8 @@ export default function Area(props) {
|
|||||||
y: props.areaData.y,
|
y: props.areaData.y,
|
||||||
width: props.areaData.width,
|
width: props.areaData.width,
|
||||||
height: props.areaData.height,
|
height: props.areaData.height,
|
||||||
mouseX: e.clientX,
|
mouseX: e.clientX/props.zoom,
|
||||||
mouseY: e.clientY,
|
mouseY: e.clientY/props.zoom,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import React, { useContext, useRef, useState, useEffect } from "react";
|
import React, { useContext, useRef, useState, useEffect } from "react";
|
||||||
import { useDrop } from "react-dnd";
|
|
||||||
import Table from "./table";
|
import Table from "./table";
|
||||||
import {
|
import { Cardinality, Constraint, ObjectType } from "../data/data";
|
||||||
defaultTableTheme,
|
|
||||||
Cardinality,
|
|
||||||
Constraint,
|
|
||||||
ObjectType,
|
|
||||||
} from "../data/data";
|
|
||||||
import Area from "./area";
|
import Area from "./area";
|
||||||
import Relationship from "./relationship";
|
import Relationship from "./relationship";
|
||||||
import { AreaContext, NoteContext, TableContext } from "../pages/editor";
|
import { AreaContext, NoteContext, TableContext } from "../pages/editor";
|
||||||
@ -60,22 +54,22 @@ export default function Canvas(props) {
|
|||||||
if (type === ObjectType.TABLE) {
|
if (type === ObjectType.TABLE) {
|
||||||
const table = tables.find((t) => t.id === id);
|
const table = tables.find((t) => t.id === id);
|
||||||
setOffset({
|
setOffset({
|
||||||
x: clientX - table.x,
|
x: clientX / zoom - table.x,
|
||||||
y: clientY - table.y,
|
y: clientY / zoom - table.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.TABLE, id]);
|
setDragging([ObjectType.TABLE, id]);
|
||||||
} else if (type === ObjectType.AREA) {
|
} else if (type === ObjectType.AREA) {
|
||||||
const area = areas.find((t) => t.id === id);
|
const area = areas.find((t) => t.id === id);
|
||||||
setOffset({
|
setOffset({
|
||||||
x: clientX - area.x,
|
x: clientX / zoom - area.x,
|
||||||
y: clientY - area.y,
|
y: clientY / zoom - area.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.AREA, id]);
|
setDragging([ObjectType.AREA, id]);
|
||||||
} else if (type === ObjectType.NOTE) {
|
} else if (type === ObjectType.NOTE) {
|
||||||
const note = notes.find((t) => t.id === id);
|
const note = notes.find((t) => t.id === id);
|
||||||
setOffset({
|
setOffset({
|
||||||
x: clientX - note.x,
|
x: clientX / zoom - note.x,
|
||||||
y: clientY - note.y,
|
y: clientY / zoom - note.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.NOTE, id]);
|
setDragging([ObjectType.NOTE, id]);
|
||||||
}
|
}
|
||||||
@ -89,16 +83,16 @@ export default function Canvas(props) {
|
|||||||
|
|
||||||
setLine({
|
setLine({
|
||||||
...line,
|
...line,
|
||||||
endX: e.clientX - offsetX,
|
endX: (e.clientX - offsetX) / zoom,
|
||||||
endY: e.clientY - offsetY,
|
endY: (e.clientY - offsetY) / zoom,
|
||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
panning &&
|
panning &&
|
||||||
dragging[0] === ObjectType.NONE &&
|
dragging[0] === ObjectType.NONE &&
|
||||||
areaResize.id === -1
|
areaResize.id === -1
|
||||||
) {
|
) {
|
||||||
const dx = e.clientX - panOffset.x;
|
const dx = (e.clientX - panOffset.x) / zoom;
|
||||||
const dy = e.clientY - panOffset.y;
|
const dy = (e.clientY - panOffset.y) / zoom;
|
||||||
setPanOffset({ x: e.clientX, y: e.clientY });
|
setPanOffset({ x: e.clientX, y: e.clientY });
|
||||||
|
|
||||||
setTables((prev) =>
|
setTables((prev) =>
|
||||||
@ -112,10 +106,10 @@ export default function Canvas(props) {
|
|||||||
setRelationships(
|
setRelationships(
|
||||||
relationships.map((r) => ({
|
relationships.map((r) => ({
|
||||||
...r,
|
...r,
|
||||||
startX: r.startX + dx,
|
startX: tables[r.startTableId].x + 15,
|
||||||
startY: r.startY + dy,
|
startY: tables[r.startTableId].y + r.startFieldId * 36 + 69,
|
||||||
endX: r.endX + dx,
|
endX: tables[r.endTableId].x + 15,
|
||||||
endY: r.endY + dy,
|
endY: tables[r.endTableId].y + r.endFieldId * 36 + 69,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -125,58 +119,59 @@ export default function Canvas(props) {
|
|||||||
} else if (dragging[0] === ObjectType.TABLE && dragging[1] >= 0) {
|
} else if (dragging[0] === ObjectType.TABLE && dragging[1] >= 0) {
|
||||||
const updatedTables = tables.map((t) => {
|
const updatedTables = tables.map((t) => {
|
||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging[1]) {
|
||||||
const updatedTable = {
|
return {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX - offset.x,
|
x: e.clientX / zoom - offset.x,
|
||||||
y: e.clientY - offset.y,
|
y: e.clientY / zoom - offset.y,
|
||||||
};
|
};
|
||||||
return updatedTable;
|
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
});
|
});
|
||||||
setTables(updatedTables);
|
setTables(updatedTables);
|
||||||
const updatedRelationShips = relationships.map((r) => {
|
setRelationships((prev) =>
|
||||||
if (r.startTableId === dragging[1]) {
|
prev.map((r) => {
|
||||||
return {
|
if (r.startTableId === dragging[1]) {
|
||||||
...r,
|
return {
|
||||||
startX: tables[r.startTableId].x + 15,
|
...r,
|
||||||
startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
|
startX: tables[r.startTableId].x + 15,
|
||||||
};
|
startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
|
||||||
} else if (r.endTableId === dragging[1]) {
|
};
|
||||||
return {
|
} else if (r.endTableId === dragging[1]) {
|
||||||
...r,
|
return {
|
||||||
endX: tables[r.endTableId].x + 15,
|
...r,
|
||||||
endY: tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19,
|
endX: tables[r.endTableId].x + 15,
|
||||||
};
|
endY: tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19,
|
||||||
}
|
};
|
||||||
return r;
|
}
|
||||||
});
|
return r;
|
||||||
setRelationships(updatedRelationShips);
|
})
|
||||||
|
);
|
||||||
} else if (
|
} else if (
|
||||||
dragging[0] === ObjectType.AREA &&
|
dragging[0] === ObjectType.AREA &&
|
||||||
dragging[1] >= 0 &&
|
dragging[1] >= 0 &&
|
||||||
areaResize.id === -1
|
areaResize.id === -1
|
||||||
) {
|
) {
|
||||||
const updatedAreas = areas.map((t) => {
|
setAreas((prev) =>
|
||||||
if (t.id === dragging[1]) {
|
prev.map((t) => {
|
||||||
const updatedArea = {
|
if (t.id === dragging[1]) {
|
||||||
...t,
|
const updatedArea = {
|
||||||
x: e.clientX - offset.x,
|
...t,
|
||||||
y: e.clientY - offset.y,
|
x: e.clientX / zoom - offset.x,
|
||||||
};
|
y: e.clientY / zoom - offset.y,
|
||||||
return updatedArea;
|
};
|
||||||
}
|
return updatedArea;
|
||||||
return t;
|
}
|
||||||
});
|
return t;
|
||||||
setAreas(updatedAreas);
|
})
|
||||||
|
);
|
||||||
} else if (dragging[0] === ObjectType.NOTE && dragging[1] >= 0) {
|
} else if (dragging[0] === ObjectType.NOTE && dragging[1] >= 0) {
|
||||||
setNotes((prev) =>
|
setNotes((prev) =>
|
||||||
prev.map((t) => {
|
prev.map((t) => {
|
||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging[1]) {
|
||||||
return {
|
return {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX - offset.x,
|
x: e.clientX / zoom - offset.x,
|
||||||
y: e.clientY - offset.y,
|
y: e.clientY / zoom - offset.y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
@ -189,23 +184,25 @@ export default function Canvas(props) {
|
|||||||
let newY = initCoords.y;
|
let newY = initCoords.y;
|
||||||
let newWidth = initCoords.width;
|
let newWidth = initCoords.width;
|
||||||
let newHeight = initCoords.height;
|
let newHeight = initCoords.height;
|
||||||
|
const mouseX = e.clientX / zoom;
|
||||||
|
const mouseY = e.clientY / zoom;
|
||||||
setPanning(false);
|
setPanning(false);
|
||||||
if (areaResize.dir === "br") {
|
if (areaResize.dir === "br") {
|
||||||
newWidth = initCoords.width + (e.clientX - initCoords.mouseX);
|
newWidth = initCoords.width + (mouseX - initCoords.mouseX);
|
||||||
newHeight = initCoords.height + (e.clientY - initCoords.mouseY);
|
newHeight = initCoords.height + (mouseY - initCoords.mouseY);
|
||||||
} else if (areaResize.dir === "tl") {
|
} else if (areaResize.dir === "tl") {
|
||||||
newX = initCoords.x + (e.clientX - initCoords.mouseX);
|
newX = initCoords.x + (mouseX - initCoords.mouseX);
|
||||||
newY = initCoords.y + (e.clientY - initCoords.mouseY);
|
newY = initCoords.y + (mouseY - initCoords.mouseY);
|
||||||
newWidth = initCoords.width - (e.clientX - initCoords.mouseX);
|
newWidth = initCoords.width - (mouseX - initCoords.mouseX);
|
||||||
newHeight = initCoords.height - (e.clientY - initCoords.mouseY);
|
newHeight = initCoords.height - (mouseY - initCoords.mouseY);
|
||||||
} else if (areaResize.dir === "tr") {
|
} else if (areaResize.dir === "tr") {
|
||||||
newY = initCoords.y + (e.clientY - initCoords.mouseY);
|
newY = initCoords.y + (mouseY - initCoords.mouseY);
|
||||||
newWidth = initCoords.width + (e.clientX - initCoords.mouseX);
|
newWidth = initCoords.width + (mouseX - initCoords.mouseX);
|
||||||
newHeight = initCoords.height - (e.clientY - initCoords.mouseY);
|
newHeight = initCoords.height - (mouseY - initCoords.mouseY);
|
||||||
} else if (areaResize.dir === "bl") {
|
} else if (areaResize.dir === "bl") {
|
||||||
newX = initCoords.x + (e.clientX - initCoords.mouseX);
|
newX = initCoords.x + (mouseX - initCoords.mouseX);
|
||||||
newWidth = initCoords.width - (e.clientX - initCoords.mouseX);
|
newWidth = initCoords.width - (mouseX - initCoords.mouseX);
|
||||||
newHeight = initCoords.height + (e.clientY - initCoords.mouseY);
|
newHeight = initCoords.height + (mouseY - initCoords.mouseY);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAreas((prev) =>
|
setAreas((prev) =>
|
||||||
@ -278,83 +275,12 @@ export default function Canvas(props) {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const addTable = (x, y) => {
|
|
||||||
const newTable = {
|
|
||||||
id: tables.length,
|
|
||||||
name: `table_${tables.length}`,
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
name: "id",
|
|
||||||
type: "UUID",
|
|
||||||
check: "",
|
|
||||||
default: "",
|
|
||||||
primary: true,
|
|
||||||
unique: true,
|
|
||||||
notNull: true,
|
|
||||||
increment: true,
|
|
||||||
comment: "",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
comment: "",
|
|
||||||
indices: [],
|
|
||||||
color: defaultTableTheme,
|
|
||||||
};
|
|
||||||
setTables((prev) => [...prev, newTable]);
|
|
||||||
props.setCode((prev) =>
|
|
||||||
prev === ""
|
|
||||||
? `CREATE TABLE \`${newTable.name}\`;`
|
|
||||||
: `${prev}\n\nCREATE TABLE \`${newTable.name}\`;`
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addArea = (x, y) => {
|
|
||||||
const newArea = {
|
|
||||||
id: areas.length,
|
|
||||||
name: `area_${areas.length}`,
|
|
||||||
x: x,
|
|
||||||
y: y,
|
|
||||||
width: 200,
|
|
||||||
height: 200,
|
|
||||||
color: defaultTableTheme,
|
|
||||||
};
|
|
||||||
setAreas((prev) => [...prev, newArea]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [, drop] = useDrop(
|
|
||||||
() => ({
|
|
||||||
accept: "CARD",
|
|
||||||
drop: (item, monitor) => {
|
|
||||||
const offset = monitor.getClientOffset();
|
|
||||||
const canvasRect = canvas.current.getBoundingClientRect();
|
|
||||||
const x = offset.x - canvasRect.left - 100 * 0.5;
|
|
||||||
const y = offset.y - canvasRect.top - 100 * 0.5;
|
|
||||||
switch (item.type) {
|
|
||||||
case ObjectType.TABLE:
|
|
||||||
addTable(x, y);
|
|
||||||
break;
|
|
||||||
case ObjectType.AREA:
|
|
||||||
addArea(x, y);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
collect: (monitor) => ({
|
|
||||||
isOver: !!monitor.isOver(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
[tables, areas]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleMouseWheel = (e) => {
|
const handleMouseWheel = (e) => {
|
||||||
// const zoomDirection = e.deltaY > 0 ? "out" : "in";
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.deltaY <= 0 ) {
|
if (e.deltaY <= 0) {
|
||||||
setZoom((prev) => prev * 1.1);
|
setZoom((prev) => prev * 1.05);
|
||||||
} else {
|
} else {
|
||||||
setZoom((prev) => prev / 1.1);
|
setZoom((prev) => prev / 1.05);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -369,7 +295,7 @@ export default function Canvas(props) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={drop} className="flex-grow h-full" id="canvas">
|
<div className="flex-grow h-full" id="canvas">
|
||||||
<div ref={canvas} className="w-full h-full">
|
<div ref={canvas} className="w-full h-full">
|
||||||
<svg
|
<svg
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
@ -417,6 +343,7 @@ export default function Canvas(props) {
|
|||||||
setResize={setAreaResize}
|
setResize={setAreaResize}
|
||||||
initCoords={initCoords}
|
initCoords={initCoords}
|
||||||
setInitCoords={setInitCoords}
|
setInitCoords={setInitCoords}
|
||||||
|
zoom={zoom}
|
||||||
></Area>
|
></Area>
|
||||||
))}
|
))}
|
||||||
{tables.map((table) => (
|
{tables.map((table) => (
|
||||||
|
Loading…
Reference in New Issue
Block a user