lasso tests

This commit is contained in:
Ryan Di 2025-03-03 11:18:14 +11:00
parent 5d8fd603bb
commit 99c573e88e
4 changed files with 1870 additions and 56 deletions

View file

@ -52,68 +52,73 @@ export class LassoTrail extends AnimatedTrail {
this.intersectedElements.clear(); this.intersectedElements.clear();
this.enclosedElements.clear(); this.enclosedElements.clear();
this.worker = new Worker(new URL("./worker.ts", import.meta.url), { try {
type: "module", this.worker = new Worker(new URL("./worker.ts", import.meta.url), {
}); type: "module",
});
this.worker.onmessage = (event: MessageEvent<LassoWorkerOutput>) => { this.worker.onmessage = (event: MessageEvent<LassoWorkerOutput>) => {
const { selectedElementIds } = event.data; const { selectedElementIds } = event.data;
this.selectElementsFromIds(selectedElementIds);
};
this.app.setState((prevState) => { this.worker.onerror = (error) => {
const nextSelectedElementIds = selectedElementIds.reduce((acc, id) => { console.error("Worker error:", error);
acc[id] = true; };
return acc; } catch (error) {
}, {} as Record<ExcalidrawElement["id"], true>); console.error("Failed to start worker", error);
}
}
for (const [id] of Object.entries(nextSelectedElementIds)) { selectElementsFromIds = (ids: string[]) => {
const element = this.app.scene.getNonDeletedElement(id); this.app.setState((prevState) => {
if (element && isFrameLikeElement(element)) { const nextSelectedElementIds = ids.reduce((acc, id) => {
const elementsInFrame = getFrameChildren( acc[id] = true;
this.app.scene.getNonDeletedElementsMap(), return acc;
element.id, }, {} as Record<ExcalidrawElement["id"], true>);
);
for (const child of elementsInFrame) { for (const [id] of Object.entries(nextSelectedElementIds)) {
delete nextSelectedElementIds[child.id]; const element = this.app.scene.getNonDeletedElement(id);
} if (element && isFrameLikeElement(element)) {
const elementsInFrame = getFrameChildren(
this.app.scene.getNonDeletedElementsMap(),
element.id,
);
for (const child of elementsInFrame) {
delete nextSelectedElementIds[child.id];
} }
} }
}
const nextSelection = selectGroupsForSelectedElements( const nextSelection = selectGroupsForSelectedElements(
{ {
editingGroupId: prevState.editingGroupId, editingGroupId: prevState.editingGroupId,
selectedElementIds: nextSelectedElementIds, selectedElementIds: nextSelectedElementIds,
}, },
this.app.scene.getNonDeletedElements(), this.app.scene.getNonDeletedElements(),
prevState, prevState,
this.app, this.app,
); );
const selectedIds = [...Object.keys(nextSelection.selectedElementIds)]; const selectedIds = [...Object.keys(nextSelection.selectedElementIds)];
const selectedGroupIds = [ const selectedGroupIds = [...Object.keys(nextSelection.selectedGroupIds)];
...Object.keys(nextSelection.selectedGroupIds),
];
return { return {
selectedElementIds: nextSelection.selectedElementIds, selectedElementIds: nextSelection.selectedElementIds,
selectedGroupIds: nextSelection.selectedGroupIds, selectedGroupIds: nextSelection.selectedGroupIds,
selectedLinearElement: selectedLinearElement:
selectedIds.length === 1 && selectedIds.length === 1 &&
!selectedGroupIds.length && !selectedGroupIds.length &&
isLinearElement(this.app.scene.getNonDeletedElement(selectedIds[0])) isLinearElement(this.app.scene.getNonDeletedElement(selectedIds[0]))
? new LinearElementEditor( ? new LinearElementEditor(
this.app.scene.getNonDeletedElement( this.app.scene.getNonDeletedElement(
selectedIds[0], selectedIds[0],
) as NonDeleted<ExcalidrawLinearElement>, ) as NonDeleted<ExcalidrawLinearElement>,
) )
: null, : null,
}; };
}); });
}; };
this.worker.onerror = (error) => {
console.error("Worker error:", error);
};
}
addPointToPath = (x: number, y: number) => { addPointToPath = (x: number, y: number) => {
super.addPointToPath(x, y); super.addPointToPath(x, y);

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ export type LassoWorkerInput = {
elementsSegments: ElementsSegmentsMap; elementsSegments: ElementsSegmentsMap;
intersectedElements: Set<ExcalidrawElement["id"]>; intersectedElements: Set<ExcalidrawElement["id"]>;
enclosedElements: Set<ExcalidrawElement["id"]>; enclosedElements: Set<ExcalidrawElement["id"]>;
simplifyDistance: number; simplifyDistance?: number;
}; };
export type LassoWorkerOutput = { export type LassoWorkerOutput = {

View file

@ -86,7 +86,10 @@ export const updateSelection = (input: LassoWorkerInput): LassoWorkerOutput => {
simplifyDistance, simplifyDistance,
} = input; } = input;
// simplify the path to reduce the number of points // simplify the path to reduce the number of points
const path = simplify(lassoPath, simplifyDistance) as GlobalPoint[]; let path: GlobalPoint[] = lassoPath;
if (simplifyDistance) {
path = simplify(lassoPath, simplifyDistance) as GlobalPoint[];
}
// close the path to form a polygon for enclosure check // close the path to form a polygon for enclosure check
const closedPath = polygonFromPoints(path); const closedPath = polygonFromPoints(path);
// as the path might not enclose a shape anymore, clear before checking // as the path might not enclose a shape anymore, clear before checking