feat: improve deep-selector logic for group

This commit is contained in:
chenshenhai 2023-06-11 22:54:06 +08:00
parent f4ebe720a4
commit 5b79be6f1e
6 changed files with 97 additions and 28 deletions

View file

@ -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 } });
}
}

View file

@ -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();
});

View file

@ -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 }) {

View file

@ -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];

View file

@ -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 };
}

View file

@ -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 })) {