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

@ -197,12 +197,7 @@ const renderLinearPointHandles = (
context.translate(renderConfig.scrollX, renderConfig.scrollY);
context.lineWidth = 1 / renderConfig.zoom.value;
const points = LinearElementEditor.getPointsGlobalCoordinates(element);
const centerPoint = LinearElementEditor.getMidPoint(
appState.selectedLinearElement,
);
if (!centerPoint) {
return;
}
const { POINT_HANDLE_SIZE } = LinearElementEditor;
const radius = appState.editingLinearElement
? POINT_HANDLE_SIZE
@ -221,11 +216,20 @@ const renderLinearPointHandles = (
);
});
if (points.length < 3) {
if (appState.selectedLinearElement.midPointHovered) {
const centerPoint = LinearElementEditor.getMidPoint(
appState.selectedLinearElement,
)!;
//Rendering segment mid points
const midPoints = LinearElementEditor.getEditorMidPoints(
element,
appState,
).filter((midPoint) => midPoint !== null) as Point[];
midPoints.forEach((segmentMidPoint) => {
if (
appState?.selectedLinearElement?.segmentMidPointHoveredCoords &&
LinearElementEditor.arePointsEqual(
segmentMidPoint,
appState.selectedLinearElement.segmentMidPointHoveredCoords,
)
) {
// The order of renderingSingleLinearPoint and highLight points is different
// inside vs outside editor as hover states are different,
// in editor when hovered the original point is not visible as hover state fully covers it whereas outside the
@ -235,34 +239,34 @@ const renderLinearPointHandles = (
context,
appState,
renderConfig,
centerPoint,
segmentMidPoint,
radius,
false,
);
highlightPoint(centerPoint, context, renderConfig);
highlightPoint(segmentMidPoint, context, renderConfig);
} else {
highlightPoint(centerPoint, context, renderConfig);
highlightPoint(segmentMidPoint, context, renderConfig);
renderSingleLinearPoint(
context,
appState,
renderConfig,
centerPoint,
segmentMidPoint,
radius,
false,
);
}
} else {
} else if (appState.editingLinearElement || points.length === 2) {
renderSingleLinearPoint(
context,
appState,
renderConfig,
centerPoint,
segmentMidPoint,
POINT_HANDLE_SIZE / 2,
false,
true,
);
}
}
});
context.restore();
};
@ -403,6 +407,20 @@ export const _renderScene = ({
visibleElements.forEach((element) => {
try {
renderElement(element, rc, context, renderConfig);
// Getting the element using LinearElementEditor during collab mismatches version - being one head of visible elements due to
// ShapeCache returns empty hence making sure that we get the
// correct element from visible elements
if (appState.editingLinearElement?.elementId === element.id) {
if (element) {
renderLinearPointHandles(
context,
appState,
renderConfig,
element as NonDeleted<ExcalidrawLinearElement>,
);
}
}
if (!isExporting) {
renderLinkIcon(element, context, appState);
}
@ -411,15 +429,6 @@ export const _renderScene = ({
}
});
if (appState.editingLinearElement) {
const element = LinearElementEditor.getElement(
appState.editingLinearElement.elementId,
);
if (element) {
renderLinearPointHandles(context, appState, renderConfig, element);
}
}
// Paint selection element
if (appState.selectionElement) {
try {