cache the visible point indexes

aakansha-hide-close-linear-element-points
Aakansha Doshi 3 years ago
parent 02d5cc4174
commit ef8bcbe1f8

@ -1083,20 +1083,6 @@ class App extends React.Component<AppProps, AppState> {
this.refreshDeviceState(this.excalidrawContainerRef.current); this.refreshDeviceState(this.excalidrawContainerRef.current);
} }
if (
this.state.selectedLinearElement &&
prevState.zoom !== this.state.zoom
) {
const selectedLinearElement =
LinearElementEditor.updateVisiblePointIndexes(
this.state.selectedLinearElement,
this.state,
);
this.setState({
selectedLinearElement,
});
}
if ( if (
prevState.scrollX !== this.state.scrollX || prevState.scrollX !== this.state.scrollX ||
prevState.scrollY !== this.state.scrollY prevState.scrollY !== this.state.scrollY

@ -40,6 +40,11 @@ const editorMidPointsCache: {
zoom: number | null; zoom: number | null;
} = { version: null, points: [], zoom: null }; } = { version: null, points: [], zoom: null };
const visiblePointIndexesCache: {
points: number[];
zoom: number | null;
isEditingLinearElement: boolean;
} = { points: [], zoom: null, isEditingLinearElement: false };
export class LinearElementEditor { export class LinearElementEditor {
public readonly elementId: ExcalidrawElement["id"] & { public readonly elementId: ExcalidrawElement["id"] & {
_brand: "excalidrawLinearElementId"; _brand: "excalidrawLinearElementId";
@ -64,7 +69,7 @@ export class LinearElementEditor {
public readonly endBindingElement: ExcalidrawBindableElement | null | "keep"; public readonly endBindingElement: ExcalidrawBindableElement | null | "keep";
public readonly hoverPointIndex: number; public readonly hoverPointIndex: number;
public readonly segmentMidPointHoveredCoords: Point | null; public readonly segmentMidPointHoveredCoords: Point | null;
public readonly visiblePointIndexes: readonly number[];
constructor( constructor(
element: NonDeleted<ExcalidrawLinearElement>, element: NonDeleted<ExcalidrawLinearElement>,
scene: Scene, scene: Scene,
@ -89,11 +94,6 @@ export class LinearElementEditor {
}; };
this.hoverPointIndex = -1; this.hoverPointIndex = -1;
this.segmentMidPointHoveredCoords = null; this.segmentMidPointHoveredCoords = null;
this.visiblePointIndexes = LinearElementEditor.getVisiblePointIndexes(
element,
appState,
editingLinearElement,
);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -573,11 +573,30 @@ export class LinearElementEditor {
static getVisiblePointIndexes( static getVisiblePointIndexes(
element: NonDeleted<ExcalidrawLinearElement>, element: NonDeleted<ExcalidrawLinearElement>,
appState: AppState, appState: AppState,
editingLinearElement: boolean, ): typeof visiblePointIndexesCache["points"] {
) { const isEditingLinearElement = !!appState.editingLinearElement;
if (!element) { if (appState.editingLinearElement) {
return []; // So that when we exit the editor the points are calculated again
visiblePointIndexesCache.isEditingLinearElement = true;
return element.points.map((_, index) => index);
}
if (
visiblePointIndexesCache.points &&
visiblePointIndexesCache.zoom === appState.zoom.value &&
isEditingLinearElement === visiblePointIndexesCache.isEditingLinearElement
) {
return visiblePointIndexesCache.points;
} }
LinearElementEditor.updateVisiblePointIndexesCache(element, appState);
return visiblePointIndexesCache.points;
}
static updateVisiblePointIndexesCache(
element: NonDeleted<ExcalidrawLinearElement>,
appState: AppState,
) {
const visiblePointIndexes: number[] = []; const visiblePointIndexes: number[] = [];
let previousPoint: Point | null = null; let previousPoint: Point | null = null;
element.points.forEach((point, index) => { element.points.forEach((point, index) => {
@ -589,7 +608,7 @@ export class LinearElementEditor {
} }
const isExtremePoint = index === 0 || index === element.points.length - 1; const isExtremePoint = index === 0 || index === element.points.length - 1;
const threshold = 2 * LinearElementEditor.POINT_HANDLE_SIZE; const threshold = 2 * LinearElementEditor.POINT_HANDLE_SIZE;
if (editingLinearElement || isExtremePoint || distance >= threshold) { if (isExtremePoint || distance >= threshold) {
// hide n-1 point if distance is less than threshold // hide n-1 point if distance is less than threshold
if (isExtremePoint && distance < threshold) { if (isExtremePoint && distance < threshold) {
visiblePointIndexes.pop(); visiblePointIndexes.pop();
@ -598,27 +617,12 @@ export class LinearElementEditor {
previousPoint = point; previousPoint = point;
} }
}); });
return visiblePointIndexes; visiblePointIndexesCache.points = visiblePointIndexes;
visiblePointIndexesCache.zoom = appState.zoom.value;
visiblePointIndexesCache.isEditingLinearElement =
!!appState.editingLinearElement;
} }
static updateVisiblePointIndexes(
linearElementEditor: LinearElementEditor,
appState: AppState,
) {
const { elementId } = linearElementEditor;
const element = LinearElementEditor.getElement(elementId);
if (!element) {
return linearElementEditor;
}
return {
...linearElementEditor,
visiblePointIndexes: LinearElementEditor.getVisiblePointIndexes(
element,
appState,
false,
),
};
}
static handlePointerDown( static handlePointerDown(
event: React.PointerEvent<HTMLCanvasElement>, event: React.PointerEvent<HTMLCanvasElement>,
appState: AppState, appState: AppState,
@ -705,11 +709,6 @@ export class LinearElementEditor {
scenePointer, scenePointer,
Scene.getScene(element)!, Scene.getScene(element)!,
), ),
visiblePointIndexes: LinearElementEditor.getVisiblePointIndexes(
element,
appState,
true,
),
}; };
ret.didAddPoint = true; ret.didAddPoint = true;
@ -781,14 +780,8 @@ export class LinearElementEditor {
: { x: 0, y: 0 }, : { x: 0, y: 0 },
}; };
if (ret.didAddPoint) { if (ret.didAddPoint) {
const visiblePointIndexes = LinearElementEditor.getVisiblePointIndexes(
element,
appState,
!!appState.editingLinearElement,
);
ret.linearElementEditor = { ret.linearElementEditor = {
...ret.linearElementEditor, ...ret.linearElementEditor,
visiblePointIndexes,
}; };
} }
return ret; return ret;
@ -955,13 +948,13 @@ export class LinearElementEditor {
const pointHandles = const pointHandles =
LinearElementEditor.getPointsGlobalCoordinates(element); LinearElementEditor.getPointsGlobalCoordinates(element);
let counter = linearElementEditor.visiblePointIndexes.length; let counter = visiblePointIndexesCache.points.length;
// loop from right to left because points on the right are rendered over // loop from right to left because points on the right are rendered over
// points on the left, thus should take precedence when clicking, if they // points on the left, thus should take precedence when clicking, if they
// overlap // overlap
while (--counter >= 0) { while (--counter >= 0) {
const index = linearElementEditor.visiblePointIndexes[counter]; const index = visiblePointIndexesCache.points[counter];
const point = pointHandles[index]; const point = pointHandles[index];
if ( if (
distance2d(x, y, point[0], point[1]) * zoom.value < distance2d(x, y, point[0], point[1]) * zoom.value <

@ -205,9 +205,10 @@ const renderLinearPointHandles = (
? POINT_HANDLE_SIZE ? POINT_HANDLE_SIZE
: POINT_HANDLE_SIZE / 2; : POINT_HANDLE_SIZE / 2;
const visiblePointIndexes = const visiblePointIndexes = LinearElementEditor.getVisiblePointIndexes(
appState.editingLinearElement?.visiblePointIndexes || element,
appState.selectedLinearElement.visiblePointIndexes; appState,
);
visiblePointIndexes.forEach((index) => { visiblePointIndexes.forEach((index) => {
const isSelected = const isSelected =
!!appState.editingLinearElement?.selectedPointsIndices?.includes(index); !!appState.editingLinearElement?.selectedPointsIndices?.includes(index);
@ -447,15 +448,21 @@ export const _renderScene = ({
appState.selectedLinearElement && appState.selectedLinearElement &&
appState.selectedLinearElement.hoverPointIndex >= 0 appState.selectedLinearElement.hoverPointIndex >= 0
) { ) {
const visiblePointIndexes = const element = LinearElementEditor.getElement(
appState.editingLinearElement?.visiblePointIndexes || appState.selectedLinearElement.elementId,
appState.selectedLinearElement.visiblePointIndexes; );
if ( if (element) {
visiblePointIndexes.includes( const visiblePointIndexes = LinearElementEditor.getVisiblePointIndexes(
appState.selectedLinearElement.hoverPointIndex, element,
) appState,
) { );
renderLinearElementPointHighlight(context, appState, renderConfig); if (
visiblePointIndexes.includes(
appState.selectedLinearElement.hoverPointIndex,
)
) {
renderLinearElementPointHighlight(context, appState, renderConfig);
}
} }
} }
// Paint selected elements // Paint selected elements

Loading…
Cancel
Save