Skip to content

Commit fc5c39e

Browse files
committed
feat: improve coordinate handling
TODO: improve on this message
1 parent 04e80fd commit fc5c39e

13 files changed

+546
-203
lines changed

package-lock.json

Lines changed: 22 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"@uiw/react-codemirror": "^4.21.25",
2020
"@vercel/analytics": "^1.2.2",
2121
"axios": "^1.6.2",
22+
"classnames": "^2.5.1",
2223
"dexie": "^3.2.4",
2324
"dexie-react-hooks": "^1.1.7",
2425
"file-saver": "^2.0.5",
@@ -35,7 +36,8 @@
3536
"react-hotkeys-hook": "^4.4.1",
3637
"react-i18next": "^14.1.1",
3738
"react-router-dom": "^6.21.0",
38-
"url": "^0.11.1"
39+
"url": "^0.11.1",
40+
"usehooks-ts": "^3.1.0"
3941
},
4042
"devDependencies": {
4143
"@types/react": "^18.2.43",

src/@types/index.d.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// @ts-check
2+
3+
import { Dispatch, SetStateAction } from "react";
4+
import { Action, ObjectType } from "../data/constants";
5+
6+
type CursorStyle = "default" | "grabbing";
7+
8+
declare global {
9+
namespace DrawDB {
10+
export interface Vector2d {
11+
x: number;
12+
y: number;
13+
}
14+
15+
export interface UndoRedoItem {
16+
action: (typeof Action)[keyof typeof Action];
17+
element: (typeof ObjectType)[keyof typeof ObjectType];
18+
undo: any;
19+
redo: any;
20+
message: string;
21+
}
22+
23+
export interface UndoRedoContext {
24+
undoStack: UndoRedoItem[];
25+
setUndoStack: React.Dispatch<React.SetStateAction<UndoRedoItem[]>>;
26+
redoStack: UndoRedoItem[];
27+
setRedoStack: React.Dispatch<React.SetStateAction<UndoRedoItem[]>>;
28+
}
29+
30+
export interface TransformContext {
31+
transform: {
32+
pan: Vector2d;
33+
zoom: number;
34+
};
35+
setTransform: Dispatch<SetStateAction<TransformContext["transform"]>>;
36+
}
37+
38+
export interface SettingsContext {
39+
settings: {
40+
strictMode: boolean;
41+
showFieldSummary: boolean;
42+
showGrid: boolean;
43+
mode: "light" | "dark";
44+
autosave: boolean;
45+
panning: boolean;
46+
showCardinality: boolean;
47+
tableWidth: number;
48+
showDebugCoordinates: boolean;
49+
};
50+
setSettings: Dispatch<SetStateAction<SettingsContext["settings"]>>;
51+
}
52+
53+
export interface CanvasContext {
54+
canvas: {
55+
screenSize: Vector2d;
56+
viewBox: DOMRect;
57+
};
58+
coords: {
59+
toDiagramSpace(coords: Vector2d): Vector2d;
60+
toDiagramSpace(coords: Pick<Vector2d, "x">): Pick<Vector2d, "x">;
61+
toDiagramSpace(coords: Pick<Vector2d, "y">): Pick<Vector2d, "y">;
62+
toScreenSpace(coords: Vector2d): Vector2d;
63+
toScreenSpace(coords: Pick<Vector2d, "x">): Pick<Vector2d, "x">;
64+
toScreenSpace(coords: Pick<Vector2d, "y">): Pick<Vector2d, "y">;
65+
};
66+
pointer: {
67+
spaces: {
68+
screen: DrawDB.Vector2d;
69+
diagram: DrawDB.Vector2d;
70+
};
71+
style: CursorStyle;
72+
setStyle: Dispatch<SetStateAction<CursorStyle>>;
73+
};
74+
}
75+
}
76+
}

src/components/EditorCanvas/Area.jsx

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from "react";
1+
import { useContext, useRef, useState } from "react";
22
import { Button, Popover, Input } from "@douyinfe/semi-ui";
33
import { IconEdit, IconDeleteStroked } from "@douyinfe/semi-icons";
44
import {
@@ -15,16 +15,27 @@ import {
1515
useSelect,
1616
useAreas,
1717
useSaveState,
18-
useTransform,
1918
} from "../../hooks";
2019
import ColorPalette from "../ColorPicker";
2120
import { useTranslation } from "react-i18next";
21+
import { useHover } from "usehooks-ts";
22+
import { CanvasContext } from "../../context/CanvasContext";
2223

23-
export default function Area({ data, onPointerDown, setResize, setInitCoords }) {
24-
const [hovered, setHovered] = useState(false);
24+
export default function Area({
25+
data,
26+
onPointerDown,
27+
setResize,
28+
setInitCoords,
29+
}) {
30+
const ref = useRef(null);
31+
const isHovered = useHover(ref);
32+
const {
33+
pointer: {
34+
spaces: { diagram: pointer },
35+
},
36+
} = useContext(CanvasContext);
2537
const { layout } = useLayout();
2638
const { settings } = useSettings();
27-
const { transform } = useTransform();
2839
const { setSaveState } = useSaveState();
2940
const { selectedElement, setSelectedElement } = useSelect();
3041

@@ -35,8 +46,8 @@ export default function Area({ data, onPointerDown, setResize, setInitCoords })
3546
y: data.y,
3647
width: data.width,
3748
height: data.height,
38-
pointerX: e.clientX / transform.zoom,
39-
pointerY: e.clientY / transform.zoom,
49+
pointerX: pointer.x,
50+
pointerY: pointer.y,
4051
});
4152
};
4253

@@ -84,10 +95,7 @@ export default function Area({ data, onPointerDown, setResize, setInitCoords })
8495
selectedElement.open;
8596

8697
return (
87-
<g
88-
onPointerEnter={(e) => e.isPrimary && setHovered(true)}
89-
onPointerLeave={(e) => e.isPrimary &&setHovered(false)}
90-
>
98+
<g ref={ref}>
9199
<foreignObject
92100
key={data.id}
93101
x={data.x}
@@ -98,7 +106,7 @@ export default function Area({ data, onPointerDown, setResize, setInitCoords })
98106
>
99107
<div
100108
className={`border-2 ${
101-
hovered
109+
isHovered
102110
? "border-dashed border-blue-500"
103111
: selectedElement.element === ObjectType.AREA &&
104112
selectedElement.id === data.id
@@ -114,7 +122,7 @@ export default function Area({ data, onPointerDown, setResize, setInitCoords })
114122
<div className="text-color select-none overflow-hidden text-ellipsis">
115123
{data.name}
116124
</div>
117-
{(hovered || (areaIsSelected() && !layout.sidebar)) && (
125+
{(isHovered || (areaIsSelected() && !layout.sidebar)) && (
118126
<Popover
119127
visible={areaIsSelected() && !layout.sidebar}
120128
onClickOutSide={onClickOutSide}
@@ -139,7 +147,7 @@ export default function Area({ data, onPointerDown, setResize, setInitCoords })
139147
</div>
140148
</div>
141149
</foreignObject>
142-
{hovered && (
150+
{isHovered && (
143151
<>
144152
<circle
145153
cx={data.x}

0 commit comments

Comments
 (0)