cache the visible point indexes
This commit is contained in:
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,9 +448,14 @@ 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 (element) {
|
||||||
|
const visiblePointIndexes = LinearElementEditor.getVisiblePointIndexes(
|
||||||
|
element,
|
||||||
|
appState,
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
visiblePointIndexes.includes(
|
visiblePointIndexes.includes(
|
||||||
appState.selectedLinearElement.hoverPointIndex,
|
appState.selectedLinearElement.hoverPointIndex,
|
||||||
@ -458,6 +464,7 @@ export const _renderScene = ({
|
|||||||
renderLinearElementPointHighlight(context, appState, renderConfig);
|
renderLinearElementPointHighlight(context, appState, renderConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Paint selected elements
|
// Paint selected elements
|
||||||
if (
|
if (
|
||||||
renderSelection &&
|
renderSelection &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user