mirror of
https://github.com/idrawjs/idraw
synced 2026-05-24 10:08:34 +00:00
feat: improve deep-selector logic for group
This commit is contained in:
parent
f4ebe720a4
commit
5b79be6f1e
6 changed files with 97 additions and 28 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import type { Data, Point, Element, ElementType, ViewCalculator, ViewCalculatorOptions, ViewScaleInfo, ElementSize, ViewSizeInfo } from '@idraw/types';
|
||||
import type { Point, Data, Element, ElementType, ViewCalculator, ViewCalculatorOptions, ViewScaleInfo, ElementSize, ViewSizeInfo } from '@idraw/types';
|
||||
import { calcElementSize, isViewPointInElement, getViewPointAtElement, isElementInView } from '@idraw/util';
|
||||
|
||||
export class Calculator implements ViewCalculator {
|
||||
|
|
@ -26,13 +26,11 @@ export class Calculator implements ViewCalculator {
|
|||
});
|
||||
}
|
||||
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): { index: number; element: null | Element<ElementType> } {
|
||||
getPointElement(
|
||||
p: Point,
|
||||
opts: { data: Data; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
|
||||
): { index: number; element: null | Element<ElementType>; groupQueueIndex: number } {
|
||||
const context2d = this._opts.viewContent.boardContext;
|
||||
return getViewPointAtElement(p, {
|
||||
data,
|
||||
context2d,
|
||||
viewScaleInfo,
|
||||
viewSizeInfo
|
||||
});
|
||||
return getViewPointAtElement(p, { ...opts, ...{ context2d } });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,11 +177,11 @@ export function drawGroupsWrapper(ctx: ViewContext2D, elemList: ElementSize[]) {
|
|||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = wrapperColor;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x - bw, y - bw);
|
||||
ctx.lineTo(x + w + bw, y - bw);
|
||||
ctx.lineTo(x + w + bw, y + h + bw);
|
||||
ctx.lineTo(x - bw, y + h + bw);
|
||||
ctx.lineTo(x - bw, y - bw);
|
||||
ctx.moveTo(totalX - bw, totalY - bw);
|
||||
ctx.lineTo(totalX + w + bw, totalY - bw);
|
||||
ctx.lineTo(totalX + w + bw, totalY + h + bw);
|
||||
ctx.lineTo(totalX - bw, totalY + h + bw);
|
||||
ctx.lineTo(totalX - bw, totalY - bw);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
groupQueue: sharer.getSharedStorage(keyGroupQueue)
|
||||
});
|
||||
|
||||
console.log('pointStart target ====== ', target);
|
||||
// console.log('pointStart target ====== ', target);
|
||||
|
||||
if (sharer.getSharedStorage(keyInGroup) === true) {
|
||||
if (target.type === 'in-group-element' && target?.elements?.length > 0) {
|
||||
|
|
@ -266,7 +266,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
sharer.setSharedStorage(keyActionType, 'drag-list-end');
|
||||
needDrawFrame = true;
|
||||
} else if (data) {
|
||||
const result = calculator.getPointElement(e.point, data, sharer.getActiveScaleInfo(), sharer.getActiveViewSizeInfo());
|
||||
const result = calculator.getPointElement(e.point, { data, viewScaleInfo: sharer.getActiveScaleInfo(), viewSizeInfo: sharer.getActiveViewSizeInfo() });
|
||||
if (result.element) {
|
||||
sharer.setSharedStorage(keyActionType, 'select');
|
||||
needDrawFrame = true;
|
||||
|
|
@ -317,6 +317,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
areaSize: null,
|
||||
groupQueue: sharer.getSharedStorage(keyGroupQueue)
|
||||
});
|
||||
// console.log('doubleClick target ======= ', target);
|
||||
|
||||
if (target.type === 'in-group-element' && target.elements.length > 0) {
|
||||
sharer.setSharedStorage(keyGroupQueue, target.elements as Element<'group'>[]);
|
||||
sharer.setSharedStorage(keyInGroup, true);
|
||||
|
|
@ -329,7 +331,6 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
}
|
||||
}
|
||||
sharer.setSharedStorage(keyActionType, null);
|
||||
console.log('doubleClick target ======= ', target);
|
||||
},
|
||||
|
||||
beforeDrawFrame({ snapshot }) {
|
||||
|
|
|
|||
|
|
@ -54,23 +54,39 @@ export function getPointTarget(
|
|||
|
||||
// in-group-element
|
||||
if (groupQueue && Array.isArray(groupQueue) && groupQueue.length > 0 && data) {
|
||||
const { index, element } = calculator.getPointElement(p as Point, data, viewScaleInfo, viewSizeInfo);
|
||||
if (index >= 0 && element) {
|
||||
const { element, groupQueueIndex } = calculator.getPointElement(p as Point, { data, viewScaleInfo, viewSizeInfo, groupQueue });
|
||||
if (groupQueueIndex >= 0) {
|
||||
const newQueue: Element<'group'>[] = groupQueue.splice(0, groupQueueIndex + 1);
|
||||
target.indexes = [];
|
||||
target.elements = newQueue;
|
||||
target.uuids = [];
|
||||
target.type = 'in-group-element';
|
||||
return target;
|
||||
} else if (element) {
|
||||
const newQueue: Element<'group'>[] = [];
|
||||
for (let i = 0; i < groupQueue.length; i++) {
|
||||
const group = groupQueue[i];
|
||||
if (group.type !== 'group') {
|
||||
break;
|
||||
}
|
||||
newQueue.push(group);
|
||||
if (element.uuid === group.uuid) {
|
||||
// isElementInGroup(element, group)
|
||||
// TODO check in group
|
||||
newQueue.push(group);
|
||||
target.indexes = [];
|
||||
target.elements = newQueue;
|
||||
target.uuids = [];
|
||||
target.type = 'in-group-element';
|
||||
return target;
|
||||
} else if (Array.isArray(group.detail.children) && group.detail.children.length > 0) {
|
||||
for (let j = 0; j < group.detail.children.length; j++) {
|
||||
const child = group.detail.children[j];
|
||||
if (element.uuid === child.uuid && element.type === 'group') {
|
||||
newQueue.push(element as Element<'group'>);
|
||||
target.indexes = [];
|
||||
target.elements = newQueue;
|
||||
target.uuids = [];
|
||||
target.type = 'in-group-element';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -117,7 +133,7 @@ export function getPointTarget(
|
|||
|
||||
// over-element
|
||||
if (data) {
|
||||
const { index, element } = calculator.getPointElement(p as Point, data, viewScaleInfo, viewSizeInfo);
|
||||
const { index, element } = calculator.getPointElement(p as Point, { data, viewScaleInfo, viewSizeInfo });
|
||||
if (index >= 0 && element) {
|
||||
target.indexes = [index];
|
||||
target.elements = [element];
|
||||
|
|
|
|||
|
|
@ -38,5 +38,8 @@ export interface ViewCalculator {
|
|||
isElementInView(elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean;
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean;
|
||||
elementSize(size: ElementSize, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ElementSize;
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> };
|
||||
getPointElement(
|
||||
p: Point,
|
||||
opts: { data: Data; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo; groupQueue?: Element<'group'>[] }
|
||||
): { index: number; element: null | Element<ElementType>; groupQueueIndex: number };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ export function calcElementSize(size: ElementSize, opts: { viewScaleInfo: ViewSc
|
|||
|
||||
export function isViewPointInElement(
|
||||
p: Point,
|
||||
opts: { context2d: ViewContext2D; element: Element<ElementType>; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
|
||||
opts: { context2d: ViewContext2D; element: ElementSize; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
|
||||
): boolean {
|
||||
const { context2d: ctx, element: elem, viewScaleInfo, viewSizeInfo } = opts;
|
||||
|
||||
|
|
@ -139,13 +139,64 @@ export function getViewPointAtElement(
|
|||
data: Data;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
groupQueue?: Element<'group'>[];
|
||||
}
|
||||
): { index: number; element: null | Element<ElementType> } {
|
||||
const { context2d: ctx, data, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const result: { index: number; element: null | Element<ElementType> } = {
|
||||
): { index: number; element: null | Element<ElementType>; groupQueueIndex: number } {
|
||||
const { context2d: ctx, data, viewScaleInfo, viewSizeInfo, groupQueue } = opts;
|
||||
|
||||
const result: { index: number; element: null | Element<ElementType>; groupQueueIndex: number } = {
|
||||
index: -1,
|
||||
element: null
|
||||
element: null,
|
||||
groupQueueIndex: -1
|
||||
};
|
||||
|
||||
if (groupQueue && Array.isArray(groupQueue) && groupQueue?.length > 0) {
|
||||
// const lastGroup = groupQueue[groupQueue.length - 1];
|
||||
|
||||
for (let gIdx = groupQueue.length - 1; gIdx >= 0; gIdx--) {
|
||||
let totalX = 0;
|
||||
let totalY = 0;
|
||||
let totalAngle = 0;
|
||||
for (let i = 0; i <= gIdx; i++) {
|
||||
totalX += groupQueue[i].x;
|
||||
totalY += groupQueue[i].y;
|
||||
totalAngle += groupQueue[i].angle || 0;
|
||||
}
|
||||
|
||||
const lastGroup = groupQueue[gIdx];
|
||||
|
||||
if (lastGroup && lastGroup.type === 'group' && Array.isArray(lastGroup.detail?.children)) {
|
||||
for (let i = 0; i < lastGroup.detail.children.length; i++) {
|
||||
const child = lastGroup.detail.children[i];
|
||||
if (child) {
|
||||
const elemSize = {
|
||||
x: totalX + child.x,
|
||||
y: totalY + child.y,
|
||||
w: child.w,
|
||||
h: child.h,
|
||||
angle: totalAngle + (child.angle || 0)
|
||||
};
|
||||
if (isViewPointInElement(p, { context2d: ctx, element: elemSize, viewScaleInfo, viewSizeInfo })) {
|
||||
result.element = child;
|
||||
if (gIdx < groupQueue.length - 1 || child.type !== 'group') {
|
||||
result.groupQueueIndex = gIdx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.element) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.element) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (let i = data.elements.length - 1; i >= 0; i--) {
|
||||
const elem = data.elements[i];
|
||||
if (isViewPointInElement(p, { context2d: ctx, element: elem, viewScaleInfo, viewSizeInfo })) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue