feat: support segment midpoints in line editor (#5641)

* feat: support segment midpoints in line editor

* fix tests

* midpoints working in bezier curve

* midpoint working with non zero roughness

* calculate beizer curve control points for points >2

* unnecessary rerender

* don't show phantom points inside editor for short segments

* don't show phantom points for small curves

* improve the algo for plotting midpoints on bezier curve by taking arc lengths and doing binary search

* fix tests finally

* fix naming

* cache editor midpoints

* clear midpoint cache when undo

* fix caching

* calculate index properly when not all segments have midpoints

* make sure correct element version is fetched from cache

* chore

* fix

* direct comparison for equal points

* create arePointsEqual util

* upate name

* don't update cache except inside getter

* don't compute midpoints outside editor unless 2pointer lines

* update cache to object and burst when Zoom updated as well

* early return if midpoints not present outside editor

* don't early return

* cleanup

* Add specs

* fix
This commit is contained in:
Aakansha Doshi 2022-09-14 19:55:54 +05:30 committed by GitHub
parent c5869979c8
commit 0d1058a596
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 666 additions and 113 deletions

View file

@ -2718,18 +2718,23 @@ class App extends React.Component<AppProps, AppState> {
event,
scenePointerX,
scenePointerY,
this.state.editingLinearElement,
this.state.gridSize,
this.state,
);
if (editingLinearElement !== this.state.editingLinearElement) {
if (
editingLinearElement &&
editingLinearElement !== this.state.editingLinearElement
) {
// Since we are reading from previous state which is not possible with
// automatic batching in React 18 hence using flush sync to synchronously
// update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.
flushSync(() => {
this.setState({ editingLinearElement });
this.setState({
editingLinearElement,
});
});
}
if (editingLinearElement.lastUncommittedPoint != null) {
if (editingLinearElement?.lastUncommittedPoint != null) {
this.maybeSuggestBindingAtCursor(scenePointer);
} else {
this.setState({ suggestedBindings: [] });
@ -3058,7 +3063,7 @@ class App extends React.Component<AppProps, AppState> {
}
if (this.state.selectedLinearElement) {
let hoverPointIndex = -1;
let midPointHovered = false;
let segmentMidPointHoveredCoords = null;
if (
isHittingElementNotConsideringBoundingBox(element, this.state, [
scenePointerX,
@ -3071,13 +3076,14 @@ class App extends React.Component<AppProps, AppState> {
scenePointerX,
scenePointerY,
);
midPointHovered = LinearElementEditor.isHittingMidPoint(
linearElementEditor,
{ x: scenePointerX, y: scenePointerY },
this.state,
);
segmentMidPointHoveredCoords =
LinearElementEditor.getSegmentMidpointHitCoords(
linearElementEditor,
{ x: scenePointerX, y: scenePointerY },
this.state,
);
if (hoverPointIndex >= 0 || midPointHovered) {
if (hoverPointIndex >= 0 || segmentMidPointHoveredCoords) {
setCursor(this.canvas, CURSOR_TYPE.POINTER);
} else {
setCursor(this.canvas, CURSOR_TYPE.MOVE);
@ -3106,12 +3112,15 @@ class App extends React.Component<AppProps, AppState> {
}
if (
this.state.selectedLinearElement.midPointHovered !== midPointHovered
!LinearElementEditor.arePointsEqual(
this.state.selectedLinearElement.segmentMidPointHoveredCoords,
segmentMidPointHoveredCoords,
)
) {
this.setState({
selectedLinearElement: {
...this.state.selectedLinearElement,
midPointHovered,
segmentMidPointHoveredCoords,
},
});
}