Zoom buttons
This commit is contained in:
parent
5661984992
commit
94df100726
@ -3,7 +3,12 @@ import Table from "./table";
|
|||||||
import { Cardinality, Constraint, ObjectType } from "../data/data";
|
import { 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,
|
||||||
|
SettingsContext,
|
||||||
|
TableContext,
|
||||||
|
} from "../pages/editor";
|
||||||
import Note from "./note";
|
import Note from "./note";
|
||||||
|
|
||||||
export default function Canvas(props) {
|
export default function Canvas(props) {
|
||||||
@ -11,6 +16,7 @@ export default function Canvas(props) {
|
|||||||
useContext(TableContext);
|
useContext(TableContext);
|
||||||
const { areas, setAreas } = useContext(AreaContext);
|
const { areas, setAreas } = useContext(AreaContext);
|
||||||
const { notes, setNotes } = useContext(NoteContext);
|
const { notes, setNotes } = useContext(NoteContext);
|
||||||
|
const { settings, setSettings } = useContext(SettingsContext);
|
||||||
const [dragging, setDragging] = useState([ObjectType.NONE, -1]);
|
const [dragging, setDragging] = useState([ObjectType.NONE, -1]);
|
||||||
const [linking, setLinking] = useState(false);
|
const [linking, setLinking] = useState(false);
|
||||||
const [line, setLine] = useState({
|
const [line, setLine] = useState({
|
||||||
@ -45,7 +51,6 @@ export default function Canvas(props) {
|
|||||||
mouseY: 0,
|
mouseY: 0,
|
||||||
});
|
});
|
||||||
const [cursor, setCursor] = useState("default");
|
const [cursor, setCursor] = useState("default");
|
||||||
const [zoom, setZoom] = useState(1);
|
|
||||||
|
|
||||||
const canvas = useRef(null);
|
const canvas = useRef(null);
|
||||||
|
|
||||||
@ -54,22 +59,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 / zoom - table.x,
|
x: clientX / settings.zoom - table.x,
|
||||||
y: clientY / zoom - table.y,
|
y: clientY / settings.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 / zoom - area.x,
|
x: clientX / settings.zoom - area.x,
|
||||||
y: clientY / zoom - area.y,
|
y: clientY / settings.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 / zoom - note.x,
|
x: clientX / settings.zoom - note.x,
|
||||||
y: clientY / zoom - note.y,
|
y: clientY / settings.zoom - note.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.NOTE, id]);
|
setDragging([ObjectType.NOTE, id]);
|
||||||
}
|
}
|
||||||
@ -83,16 +88,16 @@ export default function Canvas(props) {
|
|||||||
|
|
||||||
setLine({
|
setLine({
|
||||||
...line,
|
...line,
|
||||||
endX: (e.clientX - offsetX) / zoom,
|
endX: (e.clientX - offsetX) / settings.zoom,
|
||||||
endY: (e.clientY - offsetY) / zoom,
|
endY: (e.clientY - offsetY) / settings.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) / zoom;
|
const dx = (e.clientX - panOffset.x) / settings.zoom;
|
||||||
const dy = (e.clientY - panOffset.y) / zoom;
|
const dy = (e.clientY - panOffset.y) / settings.zoom;
|
||||||
setPanOffset({ x: e.clientX, y: e.clientY });
|
setPanOffset({ x: e.clientX, y: e.clientY });
|
||||||
|
|
||||||
setTables((prev) =>
|
setTables((prev) =>
|
||||||
@ -121,8 +126,8 @@ export default function Canvas(props) {
|
|||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging[1]) {
|
||||||
return {
|
return {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX / zoom - offset.x,
|
x: e.clientX / settings.zoom - offset.x,
|
||||||
y: e.clientY / zoom - offset.y,
|
y: e.clientY / settings.zoom - offset.y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
@ -156,8 +161,8 @@ export default function Canvas(props) {
|
|||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging[1]) {
|
||||||
const updatedArea = {
|
const updatedArea = {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX / zoom - offset.x,
|
x: e.clientX / settings.zoom - offset.x,
|
||||||
y: e.clientY / zoom - offset.y,
|
y: e.clientY / settings.zoom - offset.y,
|
||||||
};
|
};
|
||||||
return updatedArea;
|
return updatedArea;
|
||||||
}
|
}
|
||||||
@ -170,8 +175,8 @@ export default function Canvas(props) {
|
|||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging[1]) {
|
||||||
return {
|
return {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX / zoom - offset.x,
|
x: e.clientX / settings.zoom - offset.x,
|
||||||
y: e.clientY / zoom - offset.y,
|
y: e.clientY / settings.zoom - offset.y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
@ -184,8 +189,8 @@ 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 mouseX = e.clientX / settings.zoom;
|
||||||
const mouseY = e.clientY / zoom;
|
const mouseY = e.clientY / settings.zoom;
|
||||||
setPanning(false);
|
setPanning(false);
|
||||||
if (areaResize.dir === "br") {
|
if (areaResize.dir === "br") {
|
||||||
newWidth = initCoords.width + (mouseX - initCoords.mouseX);
|
newWidth = initCoords.width + (mouseX - initCoords.mouseX);
|
||||||
@ -278,9 +283,9 @@ export default function Canvas(props) {
|
|||||||
const handleMouseWheel = (e) => {
|
const handleMouseWheel = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.deltaY <= 0) {
|
if (e.deltaY <= 0) {
|
||||||
setZoom((prev) => prev * 1.05);
|
setSettings((prev) => ({ ...prev, zoom: prev.zoom * 1.05 }));
|
||||||
} else {
|
} else {
|
||||||
setZoom((prev) => prev / 1.05);
|
setSettings((prev) => ({ ...prev, zoom: prev.zoom / 1.05 }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -292,7 +297,7 @@ export default function Canvas(props) {
|
|||||||
return () => {
|
return () => {
|
||||||
canvasElement.removeEventListener("wheel", handleMouseWheel);
|
canvasElement.removeEventListener("wheel", handleMouseWheel);
|
||||||
};
|
};
|
||||||
}, []);
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-grow h-full" id="canvas">
|
<div className="flex-grow h-full" id="canvas">
|
||||||
@ -332,7 +337,12 @@ export default function Canvas(props) {
|
|||||||
height="100%"
|
height="100%"
|
||||||
fill="url(#pattern-circles)"
|
fill="url(#pattern-circles)"
|
||||||
></rect>
|
></rect>
|
||||||
<g style={{ transform: `scale(${zoom})`, transformOrigin: "0 0" }}>
|
<g
|
||||||
|
style={{
|
||||||
|
transform: `scale(${settings.zoom})`,
|
||||||
|
transformOrigin: "0 0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{areas.map((a) => (
|
{areas.map((a) => (
|
||||||
<Area
|
<Area
|
||||||
key={a.id}
|
key={a.id}
|
||||||
@ -343,7 +353,7 @@ export default function Canvas(props) {
|
|||||||
setResize={setAreaResize}
|
setResize={setAreaResize}
|
||||||
initCoords={initCoords}
|
initCoords={initCoords}
|
||||||
setInitCoords={setInitCoords}
|
setInitCoords={setInitCoords}
|
||||||
zoom={zoom}
|
zoom={settings.zoom}
|
||||||
></Area>
|
></Area>
|
||||||
))}
|
))}
|
||||||
{tables.map((table) => (
|
{tables.map((table) => (
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Divider,
|
Divider,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Form,
|
InputNumber,
|
||||||
Image,
|
Image,
|
||||||
Modal,
|
Modal,
|
||||||
Spin,
|
Spin,
|
||||||
@ -72,7 +72,7 @@ export default function ControlPanel(props) {
|
|||||||
});
|
});
|
||||||
const [data, setData] = useState(null);
|
const [data, setData] = useState(null);
|
||||||
const { layout, setLayout } = useContext(LayoutContext);
|
const { layout, setLayout } = useContext(LayoutContext);
|
||||||
const { setSettings } = useContext(SettingsContext);
|
const { settings, setSettings } = useContext(SettingsContext);
|
||||||
const { relationships, tables, setTables, setRelationships } =
|
const { relationships, tables, setTables, setRelationships } =
|
||||||
useContext(TableContext);
|
useContext(TableContext);
|
||||||
const { notes, setNotes } = useContext(NoteContext);
|
const { notes, setNotes } = useContext(NoteContext);
|
||||||
@ -316,11 +316,13 @@ export default function ControlPanel(props) {
|
|||||||
},
|
},
|
||||||
"Zoom in": {
|
"Zoom in": {
|
||||||
children: [],
|
children: [],
|
||||||
function: () => {},
|
function: () =>
|
||||||
|
setSettings((prev) => ({ ...prev, zoom: prev.zoom * 1.2 })),
|
||||||
},
|
},
|
||||||
"Zoom out": {
|
"Zoom out": {
|
||||||
children: [],
|
children: [],
|
||||||
function: () => {},
|
function: () =>
|
||||||
|
setSettings((prev) => ({ ...prev, zoom: prev.zoom / 1.2 })),
|
||||||
},
|
},
|
||||||
Fullscreen: {
|
Fullscreen: {
|
||||||
children: [],
|
children: [],
|
||||||
@ -395,35 +397,37 @@ export default function ControlPanel(props) {
|
|||||||
<Dropdown.Menu>
|
<Dropdown.Menu>
|
||||||
<Dropdown.Item>Fit window</Dropdown.Item>
|
<Dropdown.Item>Fit window</Dropdown.Item>
|
||||||
<Dropdown.Divider />
|
<Dropdown.Divider />
|
||||||
{[
|
{[0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0].map((e, i) => (
|
||||||
"25%",
|
<Dropdown.Item
|
||||||
"50%",
|
key={i}
|
||||||
"75%",
|
onClick={() => {
|
||||||
"100%",
|
setSettings((prev) => ({ ...prev, zoom: e }));
|
||||||
"125%",
|
}}
|
||||||
"150%",
|
>
|
||||||
"200%",
|
{Math.floor(e * 100)}%
|
||||||
"300%",
|
</Dropdown.Item>
|
||||||
].map((e, i) => (
|
|
||||||
<Dropdown.Item key={i}>{e}</Dropdown.Item>
|
|
||||||
))}
|
))}
|
||||||
<Dropdown.Divider />
|
<Dropdown.Divider />
|
||||||
<Dropdown.Item>
|
<Dropdown.Item>
|
||||||
<Form>
|
<InputNumber
|
||||||
<Form.InputNumber
|
field="zoom"
|
||||||
field="zoom"
|
label="Custom zoom"
|
||||||
label="Custom zoom"
|
placeholder="Zoom"
|
||||||
placeholder="Zoom"
|
suffix={<div className="p-1">%</div>}
|
||||||
suffix={<div className="p-1">%</div>}
|
onChange={(v) =>
|
||||||
/>
|
setSettings((prev) => ({
|
||||||
</Form>
|
...prev,
|
||||||
|
zoom: parseFloat(v) * 0.01,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
</Dropdown.Menu>
|
</Dropdown.Menu>
|
||||||
}
|
}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
>
|
>
|
||||||
<div className="py-1 px-2 hover:bg-slate-200 rounded flex items-center justify-center">
|
<div className="py-1 px-2 hover:bg-slate-200 rounded flex items-center justify-center">
|
||||||
<div>zoom</div>
|
<div className="w-[40px]">{Math.floor(settings.zoom * 100)}%</div>
|
||||||
<div>
|
<div>
|
||||||
<IconCaretdown />
|
<IconCaretdown />
|
||||||
</div>
|
</div>
|
||||||
@ -432,12 +436,18 @@ export default function ControlPanel(props) {
|
|||||||
<button
|
<button
|
||||||
className="py-1 px-2 hover:bg-slate-200 rounded text-lg"
|
className="py-1 px-2 hover:bg-slate-200 rounded text-lg"
|
||||||
title="Zoom in"
|
title="Zoom in"
|
||||||
|
onClick={() =>
|
||||||
|
setSettings((prev) => ({ ...prev, zoom: prev.zoom * 1.2 }))
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-magnifying-glass-plus"></i>
|
<i className="fa-solid fa-magnifying-glass-plus"></i>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="py-1 px-2 hover:bg-slate-200 rounded text-lg"
|
className="py-1 px-2 hover:bg-slate-200 rounded text-lg"
|
||||||
title="Zoom out"
|
title="Zoom out"
|
||||||
|
onClick={() =>
|
||||||
|
setSettings((prev) => ({ ...prev, zoom: prev.zoom / 1.2 }))
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<i className="fa-solid fa-magnifying-glass-minus"></i>
|
<i className="fa-solid fa-magnifying-glass-minus"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -39,6 +39,7 @@ export default function Editor(props) {
|
|||||||
const [settings, setSettings] = useState({
|
const [settings, setSettings] = useState({
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
showFieldSummary: true,
|
showFieldSummary: true,
|
||||||
|
zoom: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const dragHandler = (e) => {
|
const dragHandler = (e) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user