grid support (1st iteration)#1788
Conversation
|
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/excalidraw/excalidraw/6op6v08x7 |
|
Cool. I thought it's gonna be much harder than this!
|
|
And, creating new elements too. |
| } else { | ||
| dragOffsetXY = getDragOffsetXY([hitElement], x, y); | ||
| } | ||
| } |
There was a problem hiding this comment.
Not 100% sure if this covers all the cases, especially with grouping.
src/math.ts
Outdated
| return false; | ||
| }; | ||
|
|
||
| export const pointOnGrids = ( |
There was a problem hiding this comment.
can suggest a better name?
|
I would like to have a context menu to enable/disable grid and configure the grid size ( |
| context.stroke(); | ||
| } | ||
| context.strokeStyle = origStrokeStyle; | ||
| }; |
There was a problem hiding this comment.
you can increase the grid render performance by doing a single stroke. Fewer drawing operation the better, every time. (on large screen goes from 0.25ms to 0.05ms) May not be noticeable but every ns counts when drawing :)
context.beginPath();
for (let x = offsetX; x < offsetX + width + gridSize; x += gridSize) {
context.moveTo(x, offsetY - gridSize);
context.lineTo(x, offsetY + height + gridSize);
}
for (let y = offsetY; y < offsetY + height + gridSize; y += gridSize) {
context.moveTo(offsetX - gridSize, y);
context.lineTo(offsetX + width + gridSize, y);
}
context.stroke();Btw, since grid never changes per se, we should consider some way of not having to render it every time.
There was a problem hiding this comment.
Maybe I can revisit #780 which I closed because the multiplayer didn't play well with that heuristic. Maybe it can be worked around, dunno.
There was a problem hiding this comment.
Another crazy idea is to use webgl, which I've experimented in excalidraw-layers. I'm not suggesting it for the current excalidraw, but it might be interesting in general to explore utilizing webgl for 2D.
| F_KEY_CODE: 70, | ||
| ALT_KEY_CODE: 18, | ||
| Z_KEY_CODE: 90, | ||
| GRID_KEY_CODE: 222, |
There was a problem hiding this comment.
Not sure about this. 39 didn't work on macos.
We'll want submenus sooner or later, anyway. But maybe stick with single grid size for this PR and add the granular support later. |
|
I love this! |
|
Would you help with the snapshot tests? Don't know why it fails other than |
|
There's one failing case that seems like a regression (but I couldn't figure out what exactly that regression is, playing with the preview): ● duplicate element on move when ALT is clicked › rectangle
expect(received).toEqual(expected) // deep equality
- Expected
+ Received
Array [
- 30,
- 20,
+ 0,
+ 40,
]
89 |
90 | // previous element should stay intact
> 91 | expect([h.elements[0].x, h.elements[0].y]).toEqual([30, 20]);
| ^
92 | expect([h.elements[1].x, h.elements[1].y]).toEqual([-10, 60]);
93 |
94 | h.elements.forEach((element) => expect(element).toMatchSnapshot());
at Object.<anonymous> (src/tests/move.test.tsx:91:48)And some of the snapshots are failing on similar significant changes to |
|
Ok, I'm not sure if this is the exact regression, but here's one: when you drag an element and press |
I don't know which is better. Notice the background color is not in sync.
On second thought, I can imagine this would happen. So, my suggestion is to keep it separate for now. |
| const [gridX, gridY] = getGridPoint( | ||
| x, | ||
| y, | ||
| this.state.elementType === "draw" ? null : this.state.gridSize, |
There was a problem hiding this comment.
I don't think this is very good in readability. Feel free to refactor...
There was a problem hiding this comment.
It's fine. Will be removed when we add support for all types later, anyway.
|
Looks great! One last thing, I'd store |
|
Ad the shortcut. Can you try if I'd really love to get my hands on Mac (keyboard) so I can do proper debugging. |
|
(Never used figma...) Should we go with this? diff --git a/src/components/App.tsx b/src/components/App.tsx
index dba59fd..27e18b4 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -1184,7 +1184,7 @@ class App extends React.Component<any, AppState> {
this.toggleZenMode();
}
- if (event[KEYS.CTRL_OR_CMD] && event.keyCode === KEYS.GRID_KEY_CODE) {
+ if (event[KEYS.CTRL_OR_CMD] && event.key === KEYS.GRID_KEY) {
this.toggleGridMode();
}
diff --git a/src/keys.ts b/src/keys.ts
index 10e82bc..d31d0d5 100644
--- a/src/keys.ts
+++ b/src/keys.ts
@@ -16,7 +16,7 @@ export const KEYS = {
F_KEY_CODE: 70,
ALT_KEY_CODE: 18,
Z_KEY_CODE: 90,
- GRID_KEY_CODE: 222,
+ GRID_KEY: "'",
G_KEY_CODE: 71,
} as const;
|
|
I dunno TBH. Per discussion on chat, if we go with What others do:
So probably leave it as you had it previously? |
|
OK, as there doesn't seem to be a perfect solution, let's leave it. |
|
Actually, |
|
That said, some users wouldn't be able to use this feature until we added it to UI somewhere. I'm wondering if we should add it to contextmenu right now, even if we later decide to move it elsewhere. |
|
For me as a user, I'd be happy to have context menu anyway (not only about grid), even if we had another config UI. |
|
Yea, let's do it. |

Fixes #521
Thanks to the refactored resize functions, it was pretty easy to add grids for resizing a single element. (Drawing grids was harder.)
TODOs:
For follow-up PRs: see #1810