mirror of
https://github.com/idrawjs/idraw
synced 2026-05-24 10:08:34 +00:00
feat: implement element handle methods
This commit is contained in:
parent
92909d201c
commit
e097498504
9 changed files with 283 additions and 149 deletions
|
|
@ -10,8 +10,8 @@ export { MiddlewareScaler, middlewareEventScale } from './middleware/scaler';
|
|||
export { MiddlewareRuler, middlewareEventRuler } from './middleware/ruler';
|
||||
export { MiddlewareTextEditor, middlewareEventTextEdit } from './middleware/text-editor';
|
||||
|
||||
export class Core {
|
||||
#board: Board<CoreEvent>;
|
||||
export class Core<E extends CoreEvent = CoreEvent> {
|
||||
#board: Board<E>;
|
||||
// #opts: CoreOptions;
|
||||
// #canvas: HTMLCanvasElement;
|
||||
#container: HTMLDivElement;
|
||||
|
|
@ -26,7 +26,7 @@ export class Core {
|
|||
container.appendChild(canvas);
|
||||
|
||||
const viewContent = createViewContent(canvas, { width, height, devicePixelRatio, offscreen: true });
|
||||
const board = new Board<CoreEvent>({ viewContent, container });
|
||||
const board = new Board<E>({ viewContent, container });
|
||||
const sharer = board.getSharer();
|
||||
sharer.setActiveViewSizeInfo({
|
||||
width,
|
||||
|
|
@ -81,17 +81,17 @@ export class Core {
|
|||
this.#board.clear();
|
||||
}
|
||||
|
||||
on<T extends keyof CoreEvent>(name: T, callback: (e: CoreEvent[T]) => void) {
|
||||
on<T extends keyof E>(name: T, callback: (e: E[T]) => void) {
|
||||
const eventHub = this.#board.getEventHub();
|
||||
eventHub.on(name, callback);
|
||||
}
|
||||
|
||||
off<T extends keyof CoreEvent>(name: T, callback: (e: CoreEvent[T]) => void) {
|
||||
off<T extends keyof E>(name: T, callback: (e: E[T]) => void) {
|
||||
const eventHub = this.#board.getEventHub();
|
||||
eventHub.off(name, callback);
|
||||
}
|
||||
|
||||
trigger<T extends keyof CoreEvent>(name: T, e: CoreEvent[T]) {
|
||||
trigger<T extends keyof E>(name: T, e: E[T]) {
|
||||
const eventHub = this.#board.getEventHub();
|
||||
eventHub.trigger(name, e);
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ export class Core {
|
|||
this.#board.getViewer().drawFrame();
|
||||
}
|
||||
|
||||
updateViewScale(opts: { scale: number; offsetX: number; offsetY: number }) {
|
||||
setViewScale(opts: { scale: number; offsetX: number; offsetY: number }) {
|
||||
this.#board.updateViewScaleInfo(opts);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,13 +99,27 @@ export const MiddlewareTextEditor: BoardMiddleware<Record<string, any>, CoreEven
|
|||
...element.detail
|
||||
};
|
||||
|
||||
let elemX = element.x * scale + offsetLeft;
|
||||
let elemY = element.y * scale + offsetTop;
|
||||
let elemW = element.w * scale;
|
||||
let elemH = element.h * scale;
|
||||
|
||||
if (groupQueue.length > 0) {
|
||||
elemX = element.x * scale;
|
||||
elemY = element.y * scale;
|
||||
elemW = element.w * scale;
|
||||
elemH = element.h * scale;
|
||||
}
|
||||
|
||||
textarea.style.position = 'absolute';
|
||||
textarea.style.left = `${element.x * scale}px`;
|
||||
textarea.style.top = `${element.y * scale}px`;
|
||||
textarea.style.width = `${element.w * scale}px`;
|
||||
textarea.style.height = `${element.h * scale}px`;
|
||||
textarea.style.left = `${elemX}px`;
|
||||
textarea.style.top = `${elemY}px`;
|
||||
textarea.style.width = `${elemW}px`;
|
||||
textarea.style.height = `${elemH}px`;
|
||||
textarea.style.transform = `rotate(${limitAngle(element.angle || 0)}deg)`;
|
||||
textarea.style.border = 'none';
|
||||
// textarea.style.border = 'none';
|
||||
textarea.style.boxSizing = 'border-box';
|
||||
textarea.style.border = '1px solid #1973ba';
|
||||
textarea.style.resize = 'none';
|
||||
textarea.style.overflow = 'hidden';
|
||||
textarea.style.wordBreak = 'break-all';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { middlewareEventScale, middlewareEventSelect } from '@idraw/core';
|
||||
import type { CoreEvent } from '@idraw/types';
|
||||
import type { CoreEvent, Data } from '@idraw/types';
|
||||
|
||||
export interface IDrawEventKeys {
|
||||
select: typeof middlewareEventSelect;
|
||||
|
|
@ -8,7 +8,10 @@ export interface IDrawEventKeys {
|
|||
}
|
||||
|
||||
export type IDrawEvent = CoreEvent & {
|
||||
[key: string]: any;
|
||||
change: {
|
||||
data: Data;
|
||||
type: 'update-element' | 'delete-element' | 'move-element' | 'add-element' | 'set-data' | 'other';
|
||||
};
|
||||
};
|
||||
|
||||
// TODO
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
import { Core, MiddlewareSelector, MiddlewareScroller, MiddlewareScaler, MiddlewareRuler, MiddlewareTextEditor, middlewareEventSelect } from '@idraw/core';
|
||||
import type { PointSize, IDrawOptions, Data, ViewSizeInfo, ElementType, Element, RecursivePartial, ElementPosition } from '@idraw/types';
|
||||
import type { IDrawEvent } from './event';
|
||||
import { createElement } from '@idraw/util';
|
||||
import {
|
||||
createElement,
|
||||
insertElementToListByPosition,
|
||||
updateElementInList,
|
||||
deleteElementInList,
|
||||
moveElementPosition,
|
||||
getElementPositionFromList
|
||||
} from '@idraw/util';
|
||||
|
||||
export class iDraw {
|
||||
#core: Core;
|
||||
#core: Core<IDrawEvent>;
|
||||
// private #opts: IDrawOptions;
|
||||
|
||||
constructor(mount: HTMLDivElement, opts: IDrawOptions) {
|
||||
const core = new Core(mount, opts);
|
||||
const core = new Core<IDrawEvent>(mount, opts);
|
||||
this.#core = core;
|
||||
// this.#opts = opts;
|
||||
core.use(MiddlewareScroller);
|
||||
|
|
@ -19,7 +26,9 @@ export class iDraw {
|
|||
}
|
||||
|
||||
setData(data: Data) {
|
||||
this.#core.setData(data);
|
||||
const core = this.#core;
|
||||
core.setData(data);
|
||||
core.trigger('change', { data, type: 'set-data' });
|
||||
}
|
||||
|
||||
getData(): Data | null {
|
||||
|
|
@ -30,9 +39,9 @@ export class iDraw {
|
|||
this.#core.scale(opts);
|
||||
}
|
||||
|
||||
updateViewScale(opts: { scale: number; offsetX: number; offsetY: number }) {
|
||||
setViewScale(opts: { scale: number; offsetX: number; offsetY: number }) {
|
||||
const core = this.#core;
|
||||
core.updateViewScale(opts);
|
||||
core.setViewScale(opts);
|
||||
core.refresh();
|
||||
}
|
||||
|
||||
|
|
@ -52,10 +61,18 @@ export class iDraw {
|
|||
this.#core.trigger(name, e);
|
||||
}
|
||||
|
||||
selectElement(uuid: string) {
|
||||
this.selectElements([uuid]);
|
||||
}
|
||||
|
||||
selectElements(uuids: string[]) {
|
||||
this.trigger(middlewareEventSelect, { uuids });
|
||||
}
|
||||
|
||||
selectElementByPosition(position: ElementPosition) {
|
||||
this.selectElementsByPositions([position]);
|
||||
}
|
||||
|
||||
selectElementsByPositions(positions: ElementPosition[]) {
|
||||
this.trigger(middlewareEventSelect, { positions });
|
||||
}
|
||||
|
|
@ -84,50 +101,51 @@ export class iDraw {
|
|||
);
|
||||
}
|
||||
|
||||
updateElement() {
|
||||
// TODO
|
||||
updateElement(element: Element) {
|
||||
const core = this.#core;
|
||||
const data: Data = core.getData() || { elements: [] };
|
||||
updateElementInList(element.uuid, element, data.elements);
|
||||
core.setData(data);
|
||||
core.refresh();
|
||||
core.trigger('change', { data, type: 'update-element' });
|
||||
}
|
||||
|
||||
addElement(
|
||||
element: Element,
|
||||
opts?: {
|
||||
uuid: string;
|
||||
referenceType: 'group' | 'front' | 'back';
|
||||
position: ElementPosition;
|
||||
}
|
||||
): Data {
|
||||
const core = this.#core;
|
||||
const data: Data = core.getData() || { elements: [] };
|
||||
if (!opts) {
|
||||
data.elements.push(element);
|
||||
} else {
|
||||
// TODO
|
||||
} else if (opts?.position) {
|
||||
insertElementToListByPosition(element, opts?.position, data.elements);
|
||||
}
|
||||
core.setData(data);
|
||||
core.refresh();
|
||||
core.trigger('change', { data, type: 'add-element' });
|
||||
return data;
|
||||
}
|
||||
|
||||
deleteElement(uuid: string) {
|
||||
// TODO
|
||||
const core = this.#core;
|
||||
const data: Data = core.getData() || { elements: [] };
|
||||
deleteElementInList(uuid, data.elements);
|
||||
core.setData(data);
|
||||
core.refresh();
|
||||
core.trigger('change', { data, type: 'delete-element' });
|
||||
}
|
||||
|
||||
moveElementToFront(uuid: string, referenceUUID?: string) {
|
||||
// TODO
|
||||
moveElement(uuid: string, to: ElementPosition) {
|
||||
const core = this.#core;
|
||||
const data: Data = core.getData() || { elements: [] };
|
||||
const from = getElementPositionFromList(uuid, data.elements);
|
||||
const list = moveElementPosition(data.elements, { from, to });
|
||||
data.elements = list;
|
||||
core.setData(data);
|
||||
core.refresh();
|
||||
core.trigger('change', { data, type: 'move-element' });
|
||||
}
|
||||
|
||||
moveElementToBack(uuid: string, referenceUUID?: string) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// scrollLeft() {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
// scrollTop() {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
// exportDataURL() {
|
||||
// // TODO
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,5 +105,8 @@ export {
|
|||
getDefaultElementDetailConfig,
|
||||
calcViewBoxSize,
|
||||
createElement,
|
||||
moveElementPosition
|
||||
moveElementPosition,
|
||||
insertElementToListByPosition,
|
||||
deleteElementInListByPosition,
|
||||
deleteElementInList
|
||||
} from '@idraw/util';
|
||||
|
|
|
|||
59
packages/util/__tests__/lib/element.test.ts
Normal file
59
packages/util/__tests__/lib/element.test.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { createUUID, deepClone, getElementPositionFromList } from '@idraw/util';
|
||||
import type { Elements } from '@idraw/types';
|
||||
const getElemBase = () => {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 1,
|
||||
h: 1
|
||||
};
|
||||
};
|
||||
|
||||
function generateElements(list: any[]): Elements {
|
||||
const elements: Elements = list.map((item, i) => {
|
||||
if (Array.isArray(item)) {
|
||||
return {
|
||||
...getElemBase(),
|
||||
uuid: `${i}-${createUUID()}`,
|
||||
type: 'group',
|
||||
detail: {
|
||||
children: generateElements(item)
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...getElemBase(),
|
||||
uuid: `${i}-${createUUID()}`,
|
||||
type: 'rect',
|
||||
detail: {}
|
||||
};
|
||||
}
|
||||
}) as Elements;
|
||||
return elements;
|
||||
}
|
||||
|
||||
describe('@idraw/util: element ', () => {
|
||||
// [4]
|
||||
test('getElementPositionFromList [4]', () => {
|
||||
const list: Elements = generateElements([0, [0, 1, [0, 1, 2, [0, 1, 2, 3, [0, 1, 2, 3, 4, 5], 5], 4, 5], 3, 4, 5], 2, 3, 4, 5]);
|
||||
const uuid = (list as any)[4].uuid;
|
||||
const position = getElementPositionFromList(uuid, list);
|
||||
expect(position).toStrictEqual([4]);
|
||||
});
|
||||
|
||||
// [1, 2, 3, 4, 5]
|
||||
test('getElementPositionFromList [1, 2, 3, 4, 5]', () => {
|
||||
const list: Elements = generateElements([0, [0, 1, [0, 1, 2, [0, 1, 2, 3, [0, 1, 2, 3, 4, 5], 5], 4, 5], 3, 4, 5], 2, 3, 4, 5]);
|
||||
const uuid = (list as any)[1].detail.children[2].detail.children[3].detail.children[4].detail.children[5].uuid;
|
||||
const position = getElementPositionFromList(uuid, list);
|
||||
expect(position).toStrictEqual([1, 2, 3, 4, 5]);
|
||||
});
|
||||
|
||||
// [1, 2, 3, 4]
|
||||
test('getElementPositionFromList [1, 2, 3, 4, 5]', () => {
|
||||
const list: Elements = generateElements([0, [0, 1, [0, 1, 2, [0, 1, 2, 3, [0, 1, 2, 3, 4, 5], 5], 4, 5], 3, 4, 5], 2, 3, 4, 5]);
|
||||
const uuid = (list as any)[1].detail.children[2].detail.children[3].detail.children[4].uuid;
|
||||
const position = getElementPositionFromList(uuid, list);
|
||||
expect(position).toStrictEqual([1, 2, 3, 4]);
|
||||
});
|
||||
});
|
||||
|
|
@ -34,12 +34,12 @@ export {
|
|||
findElementsFromList,
|
||||
findElementFromListByPosition,
|
||||
findElementsFromListByPositions,
|
||||
updateElementInList,
|
||||
getGroupQueueFromList,
|
||||
getElementSize,
|
||||
mergeElementAsset,
|
||||
filterElementAsset,
|
||||
isResourceElement
|
||||
isResourceElement,
|
||||
getElementPositionFromList
|
||||
} from './lib/element';
|
||||
export { checkRectIntersect } from './lib/rect';
|
||||
export {
|
||||
|
|
@ -63,4 +63,11 @@ export { formatNumber } from './lib/number';
|
|||
export { matrixToAngle, matrixToRadian } from './lib/matrix';
|
||||
export { getDefaultElementDetailConfig, getDefaultElementRectDetail } from './lib/config';
|
||||
export { calcViewBoxSize } from './lib/view-box';
|
||||
export { createElement, moveElementPosition } from './lib/handle-element';
|
||||
export {
|
||||
createElement,
|
||||
insertElementToListByPosition,
|
||||
deleteElementInListByPosition,
|
||||
deleteElementInList,
|
||||
moveElementPosition,
|
||||
updateElementInList
|
||||
} from './lib/handle-element';
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import type {
|
|||
ElementSize,
|
||||
ViewContextSize,
|
||||
ViewSizeInfo,
|
||||
RecursivePartial,
|
||||
ElementAssets,
|
||||
ElementAssetsItem,
|
||||
LoadElementType,
|
||||
|
|
@ -14,7 +13,6 @@ import type {
|
|||
} from '@idraw/types';
|
||||
import { rotateElementVertexes } from './rotate';
|
||||
import { isAssetId, createAssetId } from './uuid';
|
||||
import { istype } from './istype';
|
||||
|
||||
function getGroupUUIDs(elements: Array<Element<ElementType>>, index: string): string[] {
|
||||
const uuids: string[] = [];
|
||||
|
|
@ -237,61 +235,6 @@ export function getGroupQueueFromList(uuid: string, elements: Element<ElementTyp
|
|||
return groupQueue;
|
||||
}
|
||||
|
||||
function mergeElement<T extends Element<ElementType> = Element<ElementType>>(originElem: T, updateContent: RecursivePartial<T>): T {
|
||||
const commonKeys = Object.keys(updateContent);
|
||||
for (let i = 0; i < commonKeys.length; i++) {
|
||||
const commonKey = commonKeys[i];
|
||||
if (['x', 'y', 'w', 'h', 'angle', 'name'].includes(commonKey)) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = updateContent[commonKey];
|
||||
} else if (['detail', 'operations'].includes(commonKey)) {
|
||||
// @ts-ignore
|
||||
if (istype.json(updateContent[commonKey] as any)) {
|
||||
if (!(originElem as Object)?.hasOwnProperty(commonKey)) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = {};
|
||||
}
|
||||
// @ts-ignore
|
||||
if (istype.json(originElem[commonKey])) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = { ...originElem[commonKey], ...updateContent[commonKey] };
|
||||
}
|
||||
// @ts-ignore
|
||||
} else if (istype.array(updateContent[commonKey] as any)) {
|
||||
if (!(originElem as Object)?.hasOwnProperty(commonKey)) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = [];
|
||||
}
|
||||
// @ts-ignore
|
||||
if (istype.array(originElem[commonKey])) {
|
||||
((updateContent as any)?.[commonKey] as Array<any>)?.forEach((item, i) => {
|
||||
// @ts-ignore
|
||||
originElem[commonKey][i] = item;
|
||||
});
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = [...originElem[commonKey], ...updateContent[commonKey]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return originElem;
|
||||
}
|
||||
|
||||
export function updateElementInList(uuid: string, updateContent: RecursivePartial<Element<ElementType>>, elements: Element[]): Element | null {
|
||||
let targetElement: Element | null = null;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const elem = elements[i];
|
||||
if (elem.uuid === uuid) {
|
||||
mergeElement(elem, updateContent);
|
||||
targetElement = elem;
|
||||
break;
|
||||
} else if (elem.type === 'group') {
|
||||
targetElement = updateElementInList(uuid, updateContent, (elem as Element<'group'>)?.detail?.children || []);
|
||||
}
|
||||
}
|
||||
return targetElement;
|
||||
}
|
||||
|
||||
export function getElementSize(elem: Element): ElementSize {
|
||||
const { x, y, w, h, angle } = elem;
|
||||
const size: ElementSize = { x, y, w, h, angle };
|
||||
|
|
@ -400,52 +343,28 @@ export function findElementFromListByPosition(position: ElementPosition, list: E
|
|||
return result;
|
||||
}
|
||||
|
||||
export function insertElementToListByPosition(element: Element, position: ElementPosition, list: Element[]): boolean {
|
||||
let result = false;
|
||||
if (position.length === 1) {
|
||||
const pos = position[0];
|
||||
list.splice(pos, 0, element);
|
||||
result = true;
|
||||
} else if (position.length > 1) {
|
||||
let tempList: Element[] = list;
|
||||
for (let i = 0; i < position.length; i++) {
|
||||
const pos = position[i];
|
||||
const item = tempList[pos];
|
||||
if (i === position.length - 1) {
|
||||
const pos = position[i];
|
||||
tempList.splice(pos, 0, element);
|
||||
result = true;
|
||||
} else if (i < position.length - 1 && item.type === 'group') {
|
||||
tempList = (item as Element<'group'>).detail.children;
|
||||
} else {
|
||||
export function getElementPositionFromList(uuid: string, elements: Element<ElementType>[]): ElementPosition {
|
||||
let result: ElementPosition = [];
|
||||
let over = false;
|
||||
const _loop = (list: Element<ElementType>[]) => {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (over === true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function deleteElementInListByPosition(position: ElementPosition, list: Element[]): boolean {
|
||||
let result = false;
|
||||
if (position.length === 1) {
|
||||
const pos = position[0];
|
||||
list.splice(pos, 1);
|
||||
result = true;
|
||||
} else if (position.length > 1) {
|
||||
let tempList: Element[] = list;
|
||||
for (let i = 0; i < position.length; i++) {
|
||||
const pos = position[i];
|
||||
const item = tempList[pos];
|
||||
if (i === position.length - 1) {
|
||||
const pos = position[i];
|
||||
tempList.splice(pos, 1);
|
||||
result = true;
|
||||
} else if (i < position.length - 1 && item.type === 'group') {
|
||||
tempList = (item as Element<'group'>).detail.children;
|
||||
} else {
|
||||
result.push(i);
|
||||
const elem = list[i];
|
||||
if (elem.uuid === uuid) {
|
||||
over = true;
|
||||
break;
|
||||
} else if (elem.type === 'group') {
|
||||
_loop((elem as Element<'group'>)?.detail?.children || []);
|
||||
}
|
||||
if (over) {
|
||||
break;
|
||||
}
|
||||
result.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
_loop(elements);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import {
|
|||
getDefaultElementImageDetail,
|
||||
getDefaultElementGroupDetail
|
||||
} from './config';
|
||||
import { findElementFromListByPosition, insertElementToListByPosition, deleteElementInListByPosition } from './element';
|
||||
import { istype } from './istype';
|
||||
import { findElementFromListByPosition, getElementPositionFromList } from './element';
|
||||
|
||||
const defaultViewWidth = 200;
|
||||
const defaultViewHeight = 200;
|
||||
|
|
@ -101,6 +102,61 @@ export function createElement<T extends ElementType>(
|
|||
return elem;
|
||||
}
|
||||
|
||||
export function insertElementToListByPosition(element: Element, position: ElementPosition, list: Element[]): boolean {
|
||||
let result = false;
|
||||
if (position.length === 1) {
|
||||
const pos = position[0];
|
||||
list.splice(pos, 0, element);
|
||||
result = true;
|
||||
} else if (position.length > 1) {
|
||||
let tempList: Element[] = list;
|
||||
for (let i = 0; i < position.length; i++) {
|
||||
const pos = position[i];
|
||||
const item = tempList[pos];
|
||||
if (i === position.length - 1) {
|
||||
const pos = position[i];
|
||||
tempList.splice(pos, 0, element);
|
||||
result = true;
|
||||
} else if (i < position.length - 1 && item.type === 'group') {
|
||||
tempList = (item as Element<'group'>).detail.children;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function deleteElementInListByPosition(position: ElementPosition, list: Element[]): boolean {
|
||||
let result = false;
|
||||
if (position.length === 1) {
|
||||
const pos = position[0];
|
||||
list.splice(pos, 1);
|
||||
result = true;
|
||||
} else if (position.length > 1) {
|
||||
let tempList: Element[] = list;
|
||||
for (let i = 0; i < position.length; i++) {
|
||||
const pos = position[i];
|
||||
const item = tempList[pos];
|
||||
if (i === position.length - 1) {
|
||||
const pos = position[i];
|
||||
tempList.splice(pos, 1);
|
||||
result = true;
|
||||
} else if (i < position.length - 1 && item.type === 'group') {
|
||||
tempList = (item as Element<'group'>).detail.children;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function deleteElementInList(uuid: string, list: Element[]): boolean {
|
||||
const position = getElementPositionFromList(uuid, list);
|
||||
return deleteElementInListByPosition(position, list);
|
||||
}
|
||||
|
||||
export function moveElementPosition(
|
||||
elements: Elements,
|
||||
opts: {
|
||||
|
|
@ -159,3 +215,58 @@ export function moveElementPosition(
|
|||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
function mergeElement<T extends Element<ElementType> = Element<ElementType>>(originElem: T, updateContent: RecursivePartial<T>): T {
|
||||
const commonKeys = Object.keys(updateContent);
|
||||
for (let i = 0; i < commonKeys.length; i++) {
|
||||
const commonKey = commonKeys[i];
|
||||
if (['x', 'y', 'w', 'h', 'angle', 'name'].includes(commonKey)) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = updateContent[commonKey];
|
||||
} else if (['detail', 'operations'].includes(commonKey)) {
|
||||
// @ts-ignore
|
||||
if (istype.json(updateContent[commonKey] as any)) {
|
||||
if (!(originElem as Object)?.hasOwnProperty(commonKey)) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = {};
|
||||
}
|
||||
// @ts-ignore
|
||||
if (istype.json(originElem[commonKey])) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = { ...originElem[commonKey], ...updateContent[commonKey] };
|
||||
}
|
||||
// @ts-ignore
|
||||
} else if (istype.array(updateContent[commonKey] as any)) {
|
||||
if (!(originElem as Object)?.hasOwnProperty(commonKey)) {
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = [];
|
||||
}
|
||||
// @ts-ignore
|
||||
if (istype.array(originElem[commonKey])) {
|
||||
((updateContent as any)?.[commonKey] as Array<any>)?.forEach((item, i) => {
|
||||
// @ts-ignore
|
||||
originElem[commonKey][i] = item;
|
||||
});
|
||||
// @ts-ignore
|
||||
originElem[commonKey] = [...originElem[commonKey], ...updateContent[commonKey]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return originElem;
|
||||
}
|
||||
|
||||
export function updateElementInList(uuid: string, updateContent: RecursivePartial<Element<ElementType>>, elements: Element[]): Element | null {
|
||||
let targetElement: Element | null = null;
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const elem = elements[i];
|
||||
if (elem.uuid === uuid) {
|
||||
mergeElement(elem, updateContent);
|
||||
targetElement = elem;
|
||||
break;
|
||||
} else if (elem.type === 'group') {
|
||||
targetElement = updateElementInList(uuid, updateContent, (elem as Element<'group'>)?.detail?.children || []);
|
||||
}
|
||||
}
|
||||
return targetElement;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue