mirror of
https://github.com/idrawjs/idraw
synced 2026-05-24 10:08:34 +00:00
refactor: refactor util calc
This commit is contained in:
parent
06dc95707b
commit
3aba19d564
30 changed files with 409 additions and 241 deletions
|
|
@ -259,21 +259,21 @@ export class Board {
|
|||
}
|
||||
|
||||
scale(num: number) {
|
||||
const scaleInfo = this._viewer.scale(num);
|
||||
const viewScaleInfo = this._viewer.scale(num);
|
||||
this._viewer.drawFrame();
|
||||
this._watcher.trigger('scale', scaleInfo);
|
||||
this._watcher.trigger('scale', viewScaleInfo);
|
||||
}
|
||||
|
||||
scrollX(num: number) {
|
||||
const scaleInfo = this._viewer.scrollX(num);
|
||||
const viewScaleInfo = this._viewer.scrollX(num);
|
||||
this._viewer.drawFrame();
|
||||
this._watcher.trigger('scrollX', scaleInfo);
|
||||
this._watcher.trigger('scrollX', viewScaleInfo);
|
||||
}
|
||||
|
||||
scrollY(num: number) {
|
||||
const scaleInfo = this._viewer.scrollY(num);
|
||||
const viewScaleInfo = this._viewer.scrollY(num);
|
||||
this._viewer.drawFrame();
|
||||
this._watcher.trigger('scrollY', scaleInfo);
|
||||
this._watcher.trigger('scrollY', viewScaleInfo);
|
||||
}
|
||||
|
||||
resize(newViewSize: ViewSizeInfo) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
import type { Data, Point, Element, ElementType, ViewCalculator, ViewCalculatorOptions, ViewScaleInfo, ElementSize, ViewSizeInfo } from '@idraw/types';
|
||||
import { rotateElementVertexes, checkRectIntersect } from '@idraw/util';
|
||||
import {
|
||||
rotateElementVertexes,
|
||||
checkRectIntersect,
|
||||
viewScale,
|
||||
viewScroll,
|
||||
calcElementSize,
|
||||
isViewPointInElement,
|
||||
getViewPointAtElement,
|
||||
isElementInView
|
||||
} from '@idraw/util';
|
||||
|
||||
export class Calculator implements ViewCalculator {
|
||||
private _opts: ViewCalculatorOptions;
|
||||
|
|
@ -8,50 +17,14 @@ export class Calculator implements ViewCalculator {
|
|||
this._opts = opts;
|
||||
}
|
||||
|
||||
viewScale(num: number, prevScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo {
|
||||
const scale = num;
|
||||
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = 0;
|
||||
let offsetRight = 0;
|
||||
let offsetTop = 0;
|
||||
let offsetBottom = 0;
|
||||
|
||||
if (contextWidth * scale < width) {
|
||||
offsetLeft = offsetRight = (width - contextWidth * scale) / 2;
|
||||
} else if (contextWidth * scale > width) {
|
||||
if (prevScaleInfo.offsetLeft < 0) {
|
||||
offsetLeft = (prevScaleInfo.offsetLeft / prevScaleInfo.scale) * scale;
|
||||
offsetRight = 0 - (contextWidth * scale - width - Math.abs(offsetLeft));
|
||||
}
|
||||
}
|
||||
|
||||
if (contextHeight * scale < height) {
|
||||
offsetTop = offsetBottom = (height - contextHeight * scale) / 2;
|
||||
} else if (contextHeight * scale > height) {
|
||||
if (prevScaleInfo.offsetTop < 0) {
|
||||
offsetTop = (prevScaleInfo.offsetTop / prevScaleInfo.scale) * scale;
|
||||
offsetBottom = 0 - (contextHeight * scale - height - Math.abs(offsetTop));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
scale,
|
||||
offsetTop,
|
||||
offsetLeft,
|
||||
offsetRight,
|
||||
offsetBottom
|
||||
};
|
||||
}
|
||||
|
||||
viewScroll(opts: { moveX?: number; moveY?: number }, scaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo {
|
||||
const scale = scaleInfo.scale;
|
||||
viewScroll(opts: { moveX?: number; moveY?: number }, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo {
|
||||
const scale = viewScaleInfo.scale;
|
||||
const { moveX, moveY } = opts;
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = scaleInfo.offsetLeft;
|
||||
let offsetRight = scaleInfo.offsetRight;
|
||||
let offsetTop = scaleInfo.offsetTop;
|
||||
let offsetBottom = scaleInfo.offsetBottom;
|
||||
let offsetLeft = viewScaleInfo.offsetLeft;
|
||||
let offsetRight = viewScaleInfo.offsetRight;
|
||||
let offsetTop = viewScaleInfo.offsetTop;
|
||||
let offsetBottom = viewScaleInfo.offsetBottom;
|
||||
if (moveX !== undefined && (moveX > 0 || moveX <= 0)) {
|
||||
if (contextWidth * scale < width) {
|
||||
offsetLeft = offsetRight = (width - contextWidth * scale) / 2;
|
||||
|
|
@ -99,10 +72,10 @@ export class Calculator implements ViewCalculator {
|
|||
};
|
||||
}
|
||||
|
||||
elementSize(size: ElementSize, scaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ElementSize {
|
||||
elementSize(size: ElementSize, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ElementSize {
|
||||
const { x, y, w, h, angle } = size;
|
||||
const { contextX = 0, contextY = 0 } = viewSizeInfo;
|
||||
const { scale, offsetTop, offsetLeft } = scaleInfo;
|
||||
const { scale, offsetTop, offsetLeft } = viewScaleInfo;
|
||||
|
||||
const newSize = {
|
||||
x: x * scale + offsetLeft - contextX,
|
||||
|
|
@ -113,33 +86,12 @@ export class Calculator implements ViewCalculator {
|
|||
};
|
||||
|
||||
return newSize;
|
||||
|
||||
// const { x, y, w, h, angle } = size;
|
||||
// const { scale, offsetTop, offsetLeft } = scaleInfo;
|
||||
// return {
|
||||
// x: x * scale + offsetLeft,
|
||||
// y: y * scale + offsetTop,
|
||||
// w: w * scale,
|
||||
// h: h * scale,
|
||||
// angle
|
||||
// };
|
||||
}
|
||||
|
||||
isElementInView(elem: ElementSize, scaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean {
|
||||
// const { width, height } = viewSizeInfo;
|
||||
// const { angle } = elem;
|
||||
// const { x, y, w, h } = this.elementSize(elem, scaleInfo, viewSizeInfo);
|
||||
// const ves = rotateElementVertexes({ x, y, w, h, angle });
|
||||
// for (let i = 0; i < ves.length; i++) {
|
||||
// const v = ves[i];
|
||||
// if (v.x >= 0 && v.x <= width && v.y >= 0 && v.y <= height) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
isElementInView(elem: ElementSize, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean {
|
||||
const { width, height } = viewSizeInfo;
|
||||
const { angle } = elem;
|
||||
const { x, y, w, h } = this.elementSize(elem, scaleInfo, viewSizeInfo);
|
||||
const { x, y, w, h } = this.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
const ves = rotateElementVertexes({ x, y, w, h, angle });
|
||||
const viewSize = { x: 0, y: 0, w: width, h: height };
|
||||
|
||||
|
|
@ -148,14 +100,13 @@ export class Calculator implements ViewCalculator {
|
|||
const elemEndX = Math.max(ves[0].x, ves[1].x, ves[2].x, ves[3].x);
|
||||
const elemEndY = Math.max(ves[0].y, ves[1].y, ves[2].y, ves[3].y);
|
||||
const elemSize = { x: elemStartX, y: elemStartY, w: elemEndX - elemStartX, h: elemEndY - elemStartY };
|
||||
|
||||
return checkRectIntersect(viewSize, elemSize);
|
||||
}
|
||||
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, scaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean {
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean {
|
||||
const ctx = this._opts.viewContent.boardContext;
|
||||
const { angle = 0 } = elem;
|
||||
const { x, y, w, h } = this.elementSize(elem, scaleInfo, viewSize);
|
||||
const { x, y, w, h } = this.elementSize(elem, viewScaleInfo, viewSize);
|
||||
const vertexes = rotateElementVertexes({ x, y, w, h, angle });
|
||||
if (vertexes.length >= 2) {
|
||||
ctx.beginPath();
|
||||
|
|
@ -171,14 +122,14 @@ export class Calculator implements ViewCalculator {
|
|||
return false;
|
||||
}
|
||||
|
||||
getPointElement(p: Point, data: Data, scaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> } {
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> } {
|
||||
const result: { index: number; element: null | Element<ElementType> } = {
|
||||
index: -1,
|
||||
element: null
|
||||
};
|
||||
for (let i = data.elements.length - 1; i >= 0; i--) {
|
||||
const elem = data.elements[i];
|
||||
if (this.isPointInElement(p, elem, scaleInfo, viewSize)) {
|
||||
if (this.isPointInElement(p, elem, viewScaleInfo, viewSize)) {
|
||||
result.index = i;
|
||||
result.element = elem;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ const defaultActiveStorage: ActiveStore = {
|
|||
offsetBottom: 0
|
||||
};
|
||||
|
||||
export class Sharer implements StoreSharer {
|
||||
export class Sharer implements StoreSharer<Record<string | number | symbol, any>> {
|
||||
private _activeStore: Store<ActiveStore>;
|
||||
private _sharedStore: Store<{
|
||||
[string: string]: any;
|
||||
[string: string | number | symbol]: any;
|
||||
}>;
|
||||
|
||||
constructor() {
|
||||
|
|
@ -48,11 +48,11 @@ export class Sharer implements StoreSharer {
|
|||
return this._activeStore.getSnapshot();
|
||||
}
|
||||
|
||||
getSharedStorage(key: string): any {
|
||||
getSharedStorage(key: string | number | symbol): any {
|
||||
return this._sharedStore.get(key);
|
||||
}
|
||||
|
||||
setSharedStorage(key: string, storage: any) {
|
||||
setSharedStorage(key: string | number | symbol, storage: any) {
|
||||
return this._sharedStore.set(key, storage);
|
||||
}
|
||||
|
||||
|
|
@ -63,18 +63,18 @@ export class Sharer implements StoreSharer {
|
|||
// get/set active info
|
||||
|
||||
getActiveScaleInfo(): ViewScaleInfo {
|
||||
const scaleInfo: ViewScaleInfo = {
|
||||
const viewScaleInfo: ViewScaleInfo = {
|
||||
scale: this._activeStore.get('scale'),
|
||||
offsetTop: this._activeStore.get('offsetTop'),
|
||||
offsetBottom: this._activeStore.get('offsetBottom'),
|
||||
offsetLeft: this._activeStore.get('offsetLeft'),
|
||||
offsetRight: this._activeStore.get('offsetRight')
|
||||
};
|
||||
return scaleInfo;
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
||||
setActiveScaleInfo(scaleInfo: ViewScaleInfo) {
|
||||
const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight } = scaleInfo;
|
||||
setActiveScaleInfo(viewScaleInfo: ViewScaleInfo) {
|
||||
const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight } = viewScaleInfo;
|
||||
this._activeStore.set('scale', scale);
|
||||
this._activeStore.set('offsetTop', offsetTop);
|
||||
this._activeStore.set('offsetBottom', offsetBottom);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { EventEmitter } from '@idraw/util';
|
||||
import { EventEmitter, viewScale } from '@idraw/util';
|
||||
import type { BoardViewer, BoardViewerEventMap, BoardViewerOptions, ActiveStore, BoardViewerFrameSnapshot, ViewScaleInfo, ViewSizeInfo } from '@idraw/types';
|
||||
|
||||
const { requestAnimationFrame } = window;
|
||||
|
|
@ -40,14 +40,14 @@ export class Viewer extends EventEmitter<BoardViewerEventMap> implements BoardVi
|
|||
|
||||
if (snapshot?.activeStore.data) {
|
||||
renderer.drawData(snapshot.activeStore.data, {
|
||||
scaleInfo: {
|
||||
viewScaleInfo: {
|
||||
scale,
|
||||
offsetTop,
|
||||
offsetBottom,
|
||||
offsetLeft,
|
||||
offsetRight
|
||||
},
|
||||
viewSize: {
|
||||
viewSizeInfo: {
|
||||
width,
|
||||
height,
|
||||
contextX,
|
||||
|
|
@ -90,31 +90,31 @@ export class Viewer extends EventEmitter<BoardViewerEventMap> implements BoardVi
|
|||
}
|
||||
|
||||
scale(num: number): ViewScaleInfo {
|
||||
const { sharer, renderer, calculator } = this._opts;
|
||||
const prevScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const { sharer, renderer } = this._opts;
|
||||
const prevViewScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo: ViewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const scaleInfo = calculator.viewScale(num, prevScaleInfo, viewSizeInfo);
|
||||
sharer.setActiveScaleInfo(scaleInfo);
|
||||
const viewScaleInfo = viewScale(num, { prevViewScaleInfo, viewSizeInfo });
|
||||
sharer.setActiveScaleInfo(viewScaleInfo);
|
||||
renderer.scale(num);
|
||||
return scaleInfo;
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
||||
scrollX(num: number): ViewScaleInfo {
|
||||
const { sharer, calculator } = this._opts;
|
||||
const prevScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const prevViewScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo: ViewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const scaleInfo = calculator.viewScroll({ moveX: num - (prevScaleInfo.offsetLeft || 0) }, prevScaleInfo, viewSizeInfo);
|
||||
sharer.setActiveScaleInfo(scaleInfo);
|
||||
return scaleInfo;
|
||||
const viewScaleInfo = calculator.viewScroll({ moveX: num - (prevViewScaleInfo.offsetLeft || 0) }, prevViewScaleInfo, viewSizeInfo);
|
||||
sharer.setActiveScaleInfo(viewScaleInfo);
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
||||
scrollY(num: number): ViewScaleInfo {
|
||||
const { sharer, calculator } = this._opts;
|
||||
const prevScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const prevViewScaleInfo: ViewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo: ViewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const scaleInfo = calculator.viewScroll({ moveY: num - (prevScaleInfo.offsetTop || 0) }, prevScaleInfo, viewSizeInfo);
|
||||
sharer.setActiveScaleInfo(scaleInfo);
|
||||
return scaleInfo;
|
||||
const viewScaleInfo = calculator.viewScroll({ moveY: num - (prevViewScaleInfo.offsetTop || 0) }, prevViewScaleInfo, viewSizeInfo);
|
||||
sharer.setActiveScaleInfo(viewScaleInfo);
|
||||
return viewScaleInfo;
|
||||
}
|
||||
|
||||
resize(viewSize: Partial<ViewSizeInfo> = {}): ViewSizeInfo {
|
||||
|
|
|
|||
|
|
@ -134,8 +134,8 @@ export class BoardWatcher extends EventEmitter<BoardWatcherEventMap> {
|
|||
}
|
||||
|
||||
private _isVaildPoint(p: Point): boolean {
|
||||
const viewSize = this._opts.sharer.getActiveViewSizeInfo();
|
||||
const { width, height } = viewSize;
|
||||
const viewSizeInfo = this._opts.sharer.getActiveViewSizeInfo();
|
||||
const { width, height } = viewSizeInfo;
|
||||
if (isBoardAvailableNum(p.x) && isBoardAvailableNum(p.y) && p.x <= width && p.y <= height) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,10 @@ export class Core {
|
|||
|
||||
resize(newViewSize: ViewSizeInfo) {
|
||||
const sharer = this._board.getSharer();
|
||||
const scaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewScaleInfo = sharer.getActiveScaleInfo();
|
||||
this._board.resize(newViewSize);
|
||||
// this._board.scale(scaleInfo.scale);
|
||||
// this._board.scrollX(scaleInfo.offsetLeft);
|
||||
// this._board.scrollY(scaleInfo.offsetTop);
|
||||
// this._board.scale(viewScaleInfo.scale);
|
||||
// this._board.scrollX(viewScaleInfo.offsetLeft);
|
||||
// this._board.scrollY(viewScaleInfo.offsetTop);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ export const keyActionType = Symbol(`${key}_actionType`); // 'select' | 'drag-li
|
|||
export const keyResizeType = Symbol(`${key}_resizeType`); // ResizeType | null;
|
||||
export const keyAreaStart = Symbol(`${key}_areaStart`); // Point
|
||||
export const keyAreaEnd = Symbol(`${key}_areaEnd`); // Point
|
||||
export const keyInGroupQueue = Symbol(`${key}_targetQueue`); // Element<'group'>[]
|
||||
export const keyGroupQueue = Symbol(`${key}_groupQueue`); // Element<'group'>[]
|
||||
export const keyInGroup = Symbol(`${key}_inGroup`); // Element<'group'>[]
|
||||
|
||||
// export const keyHoverElementSize = `${key}_hoverElementSize`;
|
||||
// export const keyActionType = `${key}_actionType`; // 'select' | 'drag-list' | 'drag-list-end' | 'drag' | 'hover' | 'resize' | 'area' | null = null;
|
||||
// export const keyResizeType = `${key}_resizeType`; // ResizeType | null;
|
||||
// export const keyAreaStart = `${key}_areaStart`; // Point
|
||||
// export const keyAreaEnd = `${key}_areaEnd`; // Point
|
||||
// export const keyInGroupQueue = `${key}_targetQueue`; // Element<'group'>[]
|
||||
// export const keyGroupQueue = `${key}_targetQueue`; // Element<'group'>[]
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export function drawElementListShadows(ctx: ViewContext2D, elements: Element<Ele
|
|||
const { angle = 0 } = elem;
|
||||
if (opts?.calculator) {
|
||||
const { calculator } = opts;
|
||||
const size = calculator.elementSize({ x, y, w, h }, opts.scaleInfo, opts.viewSize);
|
||||
const size = calculator.elementSize({ x, y, w, h }, opts.viewScaleInfo, opts.viewSizeInfo);
|
||||
x = size.x;
|
||||
y = size.y;
|
||||
w = size.w;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { Point, PointWatcherEvent, BoardMiddleware, Element, ElementSize, A
|
|||
import { drawPointWrapper, drawHoverWrapper, drawElementControllers, drawArea, drawListArea, drawGroupsWrapper } from './draw-wrapper';
|
||||
import { calcElementControllerStyle } from './controller';
|
||||
import { getPointTarget, resizeElement, getSelectedListArea, calcSelectedElementsArea, isElementInGroup } from './util';
|
||||
import { key, keyHoverElementSize, keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyInGroupQueue } from './config';
|
||||
import { key, keyHoverElementSize, keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyInGroup } from './config';
|
||||
|
||||
export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (opts) => {
|
||||
const { viewer, sharer, viewContent, calculator } = opts;
|
||||
|
|
@ -35,7 +35,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
};
|
||||
|
||||
const pushGroupQueue = (elem: Element<'group'>) => {
|
||||
let groupQueue = sharer.getSharedStorage(keyInGroupQueue);
|
||||
let groupQueue = sharer.getSharedStorage(keyGroupQueue);
|
||||
if (!Array.isArray(groupQueue)) {
|
||||
groupQueue = [];
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
} else if (groupQueue.length === 0) {
|
||||
groupQueue.push(elem);
|
||||
}
|
||||
sharer.setSharedStorage(keyInGroupQueue, groupQueue);
|
||||
sharer.setSharedStorage(keyGroupQueue, groupQueue);
|
||||
return groupQueue.length > 0;
|
||||
};
|
||||
|
||||
|
|
@ -58,7 +58,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
sharer.setSharedStorage(keyResizeType, null);
|
||||
sharer.setSharedStorage(keyAreaStart, null);
|
||||
sharer.setSharedStorage(keyAreaEnd, null);
|
||||
sharer.setSharedStorage(keyInGroupQueue, null);
|
||||
sharer.setSharedStorage(keyGroupQueue, null);
|
||||
sharer.setSharedStorage(keyInGroup, null);
|
||||
};
|
||||
|
||||
clear();
|
||||
|
|
@ -78,23 +79,23 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
sharer.setSharedStorage(keyHoverElementSize, null);
|
||||
} else if (data) {
|
||||
const selectedElements = getActiveElements();
|
||||
const scaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSize = sharer.getActiveViewSizeInfo();
|
||||
const viewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const target = getPointTarget(e.point, {
|
||||
ctx: helperContext,
|
||||
data,
|
||||
selectedIndexes: getIndexes(),
|
||||
selectedUUIDs: sharer.getActiveStorage('selectedUUIDs') || [],
|
||||
selectedElements: selectedElements,
|
||||
scaleInfo,
|
||||
viewSize,
|
||||
viewScaleInfo,
|
||||
viewSizeInfo,
|
||||
calculator,
|
||||
areaSize: calcSelectedElementsArea(selectedElements, {
|
||||
scaleInfo,
|
||||
viewSize,
|
||||
viewScaleInfo,
|
||||
viewSizeInfo,
|
||||
calculator
|
||||
}),
|
||||
groupQueue: [] // TODO
|
||||
groupQueue: sharer.getSharedStorage(keyGroupQueue)
|
||||
});
|
||||
if (target.type === 'over-element' && target?.elements?.length === 1) {
|
||||
const { x, y, w, h, angle } = target.elements[0];
|
||||
|
|
@ -116,8 +117,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
sharer.setSharedStorage(keyHoverElementSize, null);
|
||||
const data = sharer.getActiveStorage('data');
|
||||
const listAreaSize = calcSelectedElementsArea(getActiveElements(), {
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSizeInfo: sharer.getActiveViewSizeInfo(),
|
||||
calculator
|
||||
});
|
||||
const target = getPointTarget(e.point, {
|
||||
|
|
@ -126,13 +127,26 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
selectedIndexes: getIndexes(),
|
||||
selectedUUIDs: sharer.getActiveStorage('selectedUUIDs') || [],
|
||||
selectedElements: getActiveElements(),
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSizeInfo: sharer.getActiveViewSizeInfo(),
|
||||
calculator,
|
||||
areaSize: listAreaSize,
|
||||
groupQueue: [] // TODO
|
||||
groupQueue: sharer.getSharedStorage(keyGroupQueue)
|
||||
});
|
||||
|
||||
console.log('pointStart target ====== ', target);
|
||||
|
||||
if (sharer.getSharedStorage(keyInGroup) === true) {
|
||||
if (target.type === 'in-group-element' && target?.elements?.length > 0) {
|
||||
// TODO
|
||||
sharer.setSharedStorage(keyGroupQueue, target.elements as Element<'group'>[]);
|
||||
return;
|
||||
} else {
|
||||
sharer.setSharedStorage(keyInGroup, false);
|
||||
sharer.setSharedStorage(keyGroupQueue, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (target.type === 'list-area') {
|
||||
sharer.setSharedStorage(keyActionType, 'drag-list');
|
||||
} else if (target.type === 'over-element' && target?.uuids?.length === 1 && target?.elements?.length === 1) {
|
||||
|
|
@ -220,9 +234,9 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
const data = sharer.getActiveStorage('data');
|
||||
const resizeType = sharer.getSharedStorage(keyResizeType);
|
||||
const actionType = sharer.getSharedStorage(keyActionType);
|
||||
const scaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSize = sharer.getActiveViewSizeInfo();
|
||||
const { offsetLeft, offsetTop } = scaleInfo;
|
||||
const viewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSizeInfo = sharer.getActiveViewSizeInfo();
|
||||
const { offsetLeft, offsetTop } = viewScaleInfo;
|
||||
let needDrawFrame = false;
|
||||
|
||||
if (actionType === 'resize' && resizeType) {
|
||||
|
|
@ -237,8 +251,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
start,
|
||||
end,
|
||||
calculator,
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo()
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSizeInfo: sharer.getActiveViewSizeInfo()
|
||||
});
|
||||
|
||||
if (uuids.length > 0) {
|
||||
|
|
@ -270,7 +284,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
return;
|
||||
}
|
||||
if (data && Array.isArray(data?.elements) && (['drag', 'drag-list'] as ActionType[]).includes(actionType)) {
|
||||
const viewInfo = calcElementsViewInfo(data.elements, viewSize, { extend: true });
|
||||
const viewInfo = calcElementsViewInfo(data.elements, viewSizeInfo, { extend: true });
|
||||
sharer.setActiveStorage('contextX', viewInfo.contextSize.contextX);
|
||||
sharer.setActiveStorage('contextY', viewInfo.contextSize.contextY);
|
||||
sharer.setActiveStorage('contextHeight', viewInfo.contextSize.contextHeight);
|
||||
|
|
@ -290,8 +304,6 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
},
|
||||
|
||||
doubleClick(e: PointWatcherEvent) {
|
||||
// console.log('doubleClick =====', e);
|
||||
const groupQueue = sharer.getSharedStorage(keyInGroupQueue);
|
||||
const data = sharer.getActiveStorage('data');
|
||||
const target = getPointTarget(e.point, {
|
||||
ctx: helperContext,
|
||||
|
|
@ -299,14 +311,18 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
selectedIndexes: getIndexes(),
|
||||
selectedUUIDs: sharer.getActiveStorage('selectedUUIDs') || [],
|
||||
selectedElements: getActiveElements(),
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSizeInfo: sharer.getActiveViewSizeInfo(),
|
||||
calculator,
|
||||
areaSize: null,
|
||||
groupQueue: [] // TODO
|
||||
groupQueue: sharer.getSharedStorage(keyGroupQueue)
|
||||
});
|
||||
if (target.elements.length === 1 && target.elements[0]?.type === 'group') {
|
||||
if (target.type === 'in-group-element' && target.elements.length > 0) {
|
||||
sharer.setSharedStorage(keyGroupQueue, target.elements as Element<'group'>[]);
|
||||
sharer.setSharedStorage(keyInGroup, true);
|
||||
} else if (target.elements.length === 1 && target.elements[0]?.type === 'group') {
|
||||
const pushResult = pushGroupQueue(target.elements[0] as Element<'group'>);
|
||||
sharer.setSharedStorage(keyInGroup, pushResult);
|
||||
if (pushResult === true) {
|
||||
viewer.drawFrame();
|
||||
return;
|
||||
|
|
@ -334,8 +350,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
contextWidth,
|
||||
devicePixelRatio
|
||||
} = activeStore;
|
||||
const scaleInfo = { scale, offsetLeft, offsetTop, offsetRight, offsetBottom };
|
||||
const viewSize = { width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio };
|
||||
const viewScaleInfo = { scale, offsetLeft, offsetTop, offsetRight, offsetBottom };
|
||||
const viewSizeInfo = { width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio };
|
||||
// const elem = data?.elements?.[selectedIndexes?.[0] as number];
|
||||
const selectedElements = getSelectedElements(data, selectedUUIDs);
|
||||
const elem = selectedElements[0];
|
||||
|
|
@ -343,21 +359,22 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
const actionType: ActionType = sharedStore[keyActionType] as ActionType;
|
||||
const areaStart: Point | null = sharedStore[keyAreaStart];
|
||||
const areaEnd: Point | null = sharedStore[keyAreaEnd];
|
||||
const groupQueue: Element<'group'>[] | null = sharedStore[keyInGroupQueue];
|
||||
const inGroup: boolean | null = sharedStore[keyInGroup];
|
||||
const groupQueue: Element<'group'>[] | null = sharedStore[keyGroupQueue];
|
||||
|
||||
if (groupQueue && groupQueue?.length > 0) {
|
||||
if (inGroup && groupQueue && groupQueue?.length > 0) {
|
||||
// in group
|
||||
drawGroupsWrapper(helperContext, groupQueue);
|
||||
} else {
|
||||
// in root
|
||||
const drawOpts = { calculator, scaleInfo, viewSize };
|
||||
const drawOpts = { calculator, viewScaleInfo, viewSizeInfo };
|
||||
if (hoverElement && actionType !== 'drag') {
|
||||
const hoverElemSize = calculator.elementSize(hoverElement, scaleInfo, viewSize);
|
||||
const hoverElemSize = calculator.elementSize(hoverElement, viewScaleInfo, viewSizeInfo);
|
||||
drawHoverWrapper(helperContext, hoverElemSize);
|
||||
}
|
||||
|
||||
if (elem && (['select', 'drag', 'resize'] as ActionType[]).includes(actionType)) {
|
||||
const selectedElemSize = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const selectedElemSize = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
const sizeControllers = calcElementControllerStyle(selectedElemSize);
|
||||
drawPointWrapper(helperContext, selectedElemSize);
|
||||
drawElementControllers(helperContext, selectedElemSize, { ...drawOpts, sizeControllers });
|
||||
|
|
@ -365,8 +382,8 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
|
|||
drawArea(helperContext, { start: areaStart, end: areaEnd });
|
||||
} else if ((['drag-list', 'drag-list-end'] as ActionType[]).includes(actionType)) {
|
||||
const listAreaSize = calcSelectedElementsArea(getActiveElements(), {
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSizeInfo: sharer.getActiveViewSizeInfo(),
|
||||
calculator
|
||||
});
|
||||
if (listAreaSize) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { keyHoverElementSize, keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyInGroupQueue } from './config';
|
||||
import { keyHoverElementSize, keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyInGroup } from './config';
|
||||
|
||||
import {
|
||||
Data,
|
||||
|
|
@ -40,7 +40,7 @@ export type ElementSizeController = Record<string, ControllerStyle>;
|
|||
|
||||
export type ResizeType = 'resize-left' | 'resize-right' | 'resize-top' | 'resize-bottom';
|
||||
|
||||
export type PointTargetType = null | 'list-area' | 'over-element' | ResizeType;
|
||||
export type PointTargetType = null | ResizeType | 'list-area' | 'over-element' | 'in-group-element';
|
||||
|
||||
export interface PointTarget {
|
||||
type: PointTargetType;
|
||||
|
|
@ -55,9 +55,10 @@ export type ActionType = 'select' | 'drag-list' | 'drag-list-end' | 'drag' | 'ho
|
|||
|
||||
export type DeepSelectorSharedStorage = {
|
||||
[keyHoverElementSize]: ElementSize | null;
|
||||
[keyActionType]: ActionType;
|
||||
[keyActionType]: ActionType | null;
|
||||
[keyResizeType]: ResizeType | null;
|
||||
[keyAreaStart]: Point | null;
|
||||
[keyAreaEnd]: Point | null;
|
||||
[keyInGroupQueue]: Element<'group'>[] | null;
|
||||
[keyGroupQueue]: Element<'group'>[] | null;
|
||||
[keyInGroup]: boolean | null;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@ export function getPointTarget(
|
|||
selectedUUIDs: Array<string>;
|
||||
selectedElements?: Element<ElementType>[];
|
||||
areaSize?: AreaSize | null;
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
calculator: ViewCalculator;
|
||||
groupQueue: Element<'group'>[];
|
||||
groupQueue: Element<'group'>[] | null;
|
||||
}
|
||||
): PointTarget {
|
||||
const target: PointTarget = {
|
||||
|
|
@ -50,7 +50,31 @@ export function getPointTarget(
|
|||
indexes: [],
|
||||
uuids: []
|
||||
};
|
||||
const { ctx, data, calculator, selectedElements, selectedIndexes, selectedUUIDs, scaleInfo, viewSize, areaSize } = opts;
|
||||
const { ctx, data, calculator, selectedElements, selectedIndexes, selectedUUIDs, viewScaleInfo, viewSizeInfo, areaSize, groupQueue } = opts;
|
||||
|
||||
// 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 newQueue: Element<'group'>[] = [];
|
||||
for (let i = 0; i < groupQueue.length; i++) {
|
||||
const group = groupQueue[i];
|
||||
if (group.type !== 'group') {
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// list area
|
||||
if (areaSize && Array.isArray(selectedElements) && selectedElements?.length > 1 && Array.isArray(selectedIndexes) && selectedIndexes?.length > 1) {
|
||||
|
|
@ -66,7 +90,7 @@ export function getPointTarget(
|
|||
|
||||
// resize
|
||||
if (selectedElements?.length === 1) {
|
||||
const elemSize = calculator.elementSize(selectedElements[0], scaleInfo, viewSize);
|
||||
const elemSize = calculator.elementSize(selectedElements[0], viewScaleInfo, viewSizeInfo);
|
||||
const ctrls = calcElementControllerStyle(elemSize);
|
||||
rotateElement(ctx, elemSize, () => {
|
||||
const ctrlKeys = Object.keys(ctrls);
|
||||
|
|
@ -93,7 +117,7 @@ export function getPointTarget(
|
|||
|
||||
// over-element
|
||||
if (data) {
|
||||
const { index, element } = calculator.getPointElement(p as Point, data, scaleInfo, viewSize);
|
||||
const { index, element } = calculator.getPointElement(p as Point, data, viewScaleInfo, viewSizeInfo);
|
||||
if (index >= 0 && element) {
|
||||
target.indexes = [index];
|
||||
target.elements = [element];
|
||||
|
|
@ -383,14 +407,14 @@ export function getSelectedListArea(
|
|||
opts: {
|
||||
start: Point;
|
||||
end: Point;
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
calculator: ViewCalculator;
|
||||
}
|
||||
): { indexes: number[]; uuids: string[] } {
|
||||
const indexes: number[] = [];
|
||||
const uuids: string[] = [];
|
||||
const { calculator, scaleInfo, viewSize, start, end } = opts;
|
||||
const { calculator, viewScaleInfo, viewSizeInfo, start, end } = opts;
|
||||
|
||||
if (!(Array.isArray(data.elements) && start && end)) {
|
||||
return { indexes, uuids };
|
||||
|
|
@ -401,7 +425,7 @@ export function getSelectedListArea(
|
|||
const endY = Math.max(start.y, end.y);
|
||||
|
||||
data.elements.forEach((elem, idx) => {
|
||||
const elemSize = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const elemSize = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
|
||||
const center = calcElementCenter(elemSize);
|
||||
if (center.x >= startX && center.x <= endX && center.y >= startY && center.y <= endY) {
|
||||
|
|
@ -426,8 +450,8 @@ export function getSelectedListArea(
|
|||
export function calcSelectedElementsArea(
|
||||
elements: Element<ElementType>[],
|
||||
opts: {
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
calculator: ViewCalculator;
|
||||
}
|
||||
): AreaSize | null {
|
||||
|
|
@ -435,11 +459,11 @@ export function calcSelectedElementsArea(
|
|||
return null;
|
||||
}
|
||||
const area: AreaSize = { x: 0, y: 0, w: 0, h: 0 };
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
let prevElemSize: ElementSize | null = null;
|
||||
|
||||
elements.forEach((elem) => {
|
||||
const elemSize = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const elemSize = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
|
||||
if (elemSize.angle && (elemSize.angle > 0 || elemSize.angle < 0)) {
|
||||
const ves = rotateElementVertexes(elemSize);
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ export function isPointInScrollbar(helperContext: ViewContext2D, p: Point, sizeI
|
|||
return thumbType;
|
||||
}
|
||||
|
||||
export function calcScrollerInfo(scaleInfo: ViewScaleInfo, sizeInfo: ViewSizeInfo) {
|
||||
export function calcScrollerInfo(viewScaleInfo: ViewScaleInfo, sizeInfo: ViewSizeInfo) {
|
||||
const { width, height } = sizeInfo;
|
||||
const { offsetTop, offsetBottom, offsetLeft, offsetRight } = scaleInfo;
|
||||
const { offsetTop, offsetBottom, offsetLeft, offsetRight } = viewScaleInfo;
|
||||
const sliderMinSize = scrollerLineWidth * 2.5;
|
||||
const lineSize = scrollerLineWidth;
|
||||
let xSize = 0;
|
||||
|
|
@ -138,11 +138,11 @@ function drawScrollerThumb(
|
|||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawScrollerInfo(helperContext: ViewContext2D, opts: { scaleInfo: ViewScaleInfo; sizeInfo: ViewSizeInfo }) {
|
||||
function drawScrollerInfo(helperContext: ViewContext2D, opts: { viewScaleInfo: ViewScaleInfo; sizeInfo: ViewSizeInfo }) {
|
||||
const ctx = helperContext;
|
||||
const { scaleInfo, sizeInfo } = opts;
|
||||
const { viewScaleInfo, sizeInfo } = opts;
|
||||
const { width, height } = sizeInfo;
|
||||
const wrapper = calcScrollerInfo(scaleInfo, sizeInfo);
|
||||
const wrapper = calcScrollerInfo(viewScaleInfo, sizeInfo);
|
||||
if (wrapper.xSize > 0) {
|
||||
if (scrollConfig.showBackground === true) {
|
||||
ctx.globalAlpha = scrollerAlpha;
|
||||
|
|
@ -191,6 +191,6 @@ function drawScrollerInfo(helperContext: ViewContext2D, opts: { scaleInfo: ViewS
|
|||
export function drawScroller(ctx: ViewContext2D, opts: { snapshot: BoardViewerFrameSnapshot }) {
|
||||
const { snapshot } = opts;
|
||||
const sizeInfo = getViewSizeInfoFromSnapshot(snapshot);
|
||||
const scaleInfo = getViewScaleInfoFromSnapshot(snapshot);
|
||||
drawScrollerInfo(ctx, { sizeInfo, scaleInfo });
|
||||
const viewScaleInfo = getViewScaleInfoFromSnapshot(snapshot);
|
||||
drawScrollerInfo(ctx, { sizeInfo, viewScaleInfo });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export function drawElementListShadows(ctx: ViewContext2D, elements: Element<Ele
|
|||
const { angle = 0 } = elem;
|
||||
if (opts?.calculator) {
|
||||
const { calculator } = opts;
|
||||
const size = calculator.elementSize({ x, y, w, h }, opts.scaleInfo, opts.viewSize);
|
||||
const size = calculator.elementSize({ x, y, w, h }, opts.viewScaleInfo, opts.viewSizeInfo);
|
||||
x = size.x;
|
||||
y = size.y;
|
||||
w = size.w;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
sharer.setSharedStorage(keyHoverElementSize, null);
|
||||
} else if (data) {
|
||||
const selectedElements = getActiveElements();
|
||||
const scaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSize = sharer.getActiveViewSizeInfo();
|
||||
const target = getPointTarget(e.point, {
|
||||
ctx: helperContext,
|
||||
|
|
@ -73,11 +73,11 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
selectedIndexes: getIndexes(),
|
||||
selectedUUIDs: sharer.getActiveStorage('selectedUUIDs') || [],
|
||||
selectedElements: selectedElements,
|
||||
scaleInfo,
|
||||
viewScaleInfo,
|
||||
viewSize,
|
||||
calculator,
|
||||
areaSize: calcSelectedElementsArea(selectedElements, {
|
||||
scaleInfo,
|
||||
viewScaleInfo,
|
||||
viewSize,
|
||||
calculator
|
||||
})
|
||||
|
|
@ -102,7 +102,7 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
sharer.setSharedStorage(keyHoverElementSize, null);
|
||||
const data = sharer.getActiveStorage('data');
|
||||
const listAreaSize = calcSelectedElementsArea(getActiveElements(), {
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
calculator
|
||||
});
|
||||
|
|
@ -112,7 +112,7 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
selectedIndexes: getIndexes(),
|
||||
selectedUUIDs: sharer.getActiveStorage('selectedUUIDs') || [],
|
||||
selectedElements: getActiveElements(),
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
calculator,
|
||||
areaSize: listAreaSize
|
||||
|
|
@ -205,9 +205,9 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
const data = sharer.getActiveStorage('data');
|
||||
const resizeType = sharer.getSharedStorage(keyResizeType);
|
||||
const actionType = sharer.getSharedStorage(keyActionType);
|
||||
const scaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewScaleInfo = sharer.getActiveScaleInfo();
|
||||
const viewSize = sharer.getActiveViewSizeInfo();
|
||||
const { scale, offsetLeft, offsetTop } = scaleInfo;
|
||||
const { scale, offsetLeft, offsetTop } = viewScaleInfo;
|
||||
const { width, height, contextHeight, contextWidth, contextX, contextY } = viewSize;
|
||||
let needDrawFrame = false;
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
start,
|
||||
end,
|
||||
calculator,
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo()
|
||||
});
|
||||
|
||||
|
|
@ -291,8 +291,8 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
contextWidth,
|
||||
devicePixelRatio
|
||||
} = activeStore;
|
||||
const scaleInfo = { scale, offsetLeft, offsetTop, offsetRight, offsetBottom };
|
||||
const viewSize = { width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio };
|
||||
const viewScaleInfo = { scale, offsetLeft, offsetTop, offsetRight, offsetBottom };
|
||||
const viewSizeInfo = { width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio };
|
||||
// const elem = data?.elements?.[selectedIndexes?.[0] as number];
|
||||
const selectedElements = getSelectedElements(data, selectedUUIDs);
|
||||
const elem = selectedElements[0];
|
||||
|
|
@ -301,14 +301,14 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
const areaStart: Point | null = sharedStore[keyAreaStart];
|
||||
const areaEnd: Point | null = sharedStore[keyAreaEnd];
|
||||
|
||||
const drawOpts = { calculator, scaleInfo, viewSize };
|
||||
const drawOpts = { calculator, viewScaleInfo, viewSizeInfo };
|
||||
if (hoverElement && actionType !== 'drag') {
|
||||
const hoverElemSize = calculator.elementSize(hoverElement, scaleInfo, viewSize);
|
||||
const hoverElemSize = calculator.elementSize(hoverElement, viewScaleInfo, viewSizeInfo);
|
||||
drawHoverWrapper(helperContext, hoverElemSize);
|
||||
}
|
||||
|
||||
if (elem && ['select', 'drag', 'resize'].includes(actionType)) {
|
||||
const selectedElemSize = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const selectedElemSize = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
const sizeControllers = calcElementControllerStyle(selectedElemSize);
|
||||
drawPointWrapper(helperContext, selectedElemSize);
|
||||
drawElementControllers(helperContext, selectedElemSize, { ...drawOpts, sizeControllers });
|
||||
|
|
@ -316,7 +316,7 @@ export const MiddlewareSelector: BoardMiddleware = (opts) => {
|
|||
drawArea(helperContext, { start: areaStart, end: areaEnd });
|
||||
} else if (['drag-list', 'drag-list-end'].includes(actionType)) {
|
||||
const listAreaSize = calcSelectedElementsArea(getActiveElements(), {
|
||||
scaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewScaleInfo: sharer.getActiveScaleInfo(),
|
||||
viewSize: sharer.getActiveViewSizeInfo(),
|
||||
calculator
|
||||
});
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export function getPointTarget(
|
|||
selectedUUIDs: Array<string>;
|
||||
selectedElements?: Element<ElementType>[];
|
||||
areaSize?: AreaSize | null;
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
calculator: ViewCalculator;
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ export function getPointTarget(
|
|||
indexes: [],
|
||||
uuids: []
|
||||
};
|
||||
const { ctx, data, calculator, selectedElements, selectedIndexes, selectedUUIDs, scaleInfo, viewSize, areaSize } = opts;
|
||||
const { ctx, data, calculator, selectedElements, selectedIndexes, selectedUUIDs, viewScaleInfo, viewSize, areaSize } = opts;
|
||||
|
||||
// list area
|
||||
if (areaSize && Array.isArray(selectedElements) && selectedElements?.length > 1 && Array.isArray(selectedIndexes) && selectedIndexes?.length > 1) {
|
||||
|
|
@ -65,7 +65,7 @@ export function getPointTarget(
|
|||
|
||||
// resize
|
||||
if (selectedElements?.length === 1) {
|
||||
const elemSize = calculator.elementSize(selectedElements[0], scaleInfo, viewSize);
|
||||
const elemSize = calculator.elementSize(selectedElements[0], viewScaleInfo, viewSize);
|
||||
const ctrls = calcElementControllerStyle(elemSize);
|
||||
rotateElement(ctx, elemSize, () => {
|
||||
const ctrlKeys = Object.keys(ctrls);
|
||||
|
|
@ -92,7 +92,7 @@ export function getPointTarget(
|
|||
|
||||
// over-element
|
||||
if (data) {
|
||||
const { index, element } = calculator.getPointElement(p as Point, data, scaleInfo, viewSize);
|
||||
const { index, element } = calculator.getPointElement(p as Point, data, viewScaleInfo, viewSize);
|
||||
if (index >= 0 && element) {
|
||||
target.indexes = [index];
|
||||
target.elements = [element];
|
||||
|
|
@ -382,14 +382,14 @@ export function getSelectedListArea(
|
|||
opts: {
|
||||
start: Point;
|
||||
end: Point;
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
calculator: ViewCalculator;
|
||||
}
|
||||
): { indexes: number[]; uuids: string[] } {
|
||||
const indexes: number[] = [];
|
||||
const uuids: string[] = [];
|
||||
const { calculator, scaleInfo, viewSize, start, end } = opts;
|
||||
const { calculator, viewScaleInfo, viewSize, start, end } = opts;
|
||||
|
||||
if (!(Array.isArray(data.elements) && start && end)) {
|
||||
return { indexes, uuids };
|
||||
|
|
@ -400,7 +400,7 @@ export function getSelectedListArea(
|
|||
const endY = Math.max(start.y, end.y);
|
||||
|
||||
data.elements.forEach((elem, idx) => {
|
||||
const elemSize = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const elemSize = calculator.elementSize(elem, viewScaleInfo, viewSize);
|
||||
|
||||
const center = calcElementCenter(elemSize);
|
||||
if (center.x >= startX && center.x <= endX && center.y >= startY && center.y <= endY) {
|
||||
|
|
@ -425,7 +425,7 @@ export function getSelectedListArea(
|
|||
export function calcSelectedElementsArea(
|
||||
elements: Element<ElementType>[],
|
||||
opts: {
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
calculator: ViewCalculator;
|
||||
}
|
||||
|
|
@ -434,11 +434,11 @@ export function calcSelectedElementsArea(
|
|||
return null;
|
||||
}
|
||||
const area: AreaSize = { x: 0, y: 0, w: 0, h: 0 };
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { calculator, viewScaleInfo, viewSize } = opts;
|
||||
let prevElemSize: ElementSize | null = null;
|
||||
|
||||
elements.forEach((elem) => {
|
||||
const elemSize = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const elemSize = calculator.elementSize(elem, viewScaleInfo, viewSize);
|
||||
|
||||
if (elemSize.angle && (elemSize.angle > 0 || elemSize.angle < 0)) {
|
||||
const ves = rotateElementVertexes(elemSize);
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import { rotateElement } from '@idraw/util';
|
|||
export function drawCircle(ctx: ViewContext2D, elem: Element<'circle'>, opts: RendererDrawElementOptions) {
|
||||
const { desc, angle } = elem;
|
||||
const { bgColor = '#000000', borderColor = '#000000', borderWidth = 0 } = desc;
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
// const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight } = scaleInfo;
|
||||
const { x, y, w, h } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h }, scaleInfo, viewSize);
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
// const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight } = viewScaleInfo;
|
||||
const { x, y, w, h } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h }, viewScaleInfo, viewSizeInfo);
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
const a = w / 2;
|
||||
const b = h / 2;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export function drawElementList(ctx: ViewContext2D, elements: Data['elements'],
|
|||
for (let i = 0; i < elements.length; i++) {
|
||||
const elem = elements[i];
|
||||
// TODO
|
||||
if (!opts.calculator.isElementInView(elem, opts.scaleInfo, opts.viewSize)) {
|
||||
if (!opts.calculator.isElementInView(elem, opts.viewScaleInfo, opts.viewSizeInfo)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ export function drawElement(ctx: ViewContext2D, elem: Element<ElementType>, opts
|
|||
}
|
||||
|
||||
export function drawGroup(ctx: ViewContext2D, elem: Element<'group'>, opts: RendererDrawElementOptions) {
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h, angle: elem.angle }, scaleInfo, viewSize);
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize({ x: elem.x, y: elem.y, w: elem.w, h: elem.h, angle: elem.angle }, viewScaleInfo, viewSizeInfo);
|
||||
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
drawBox(ctx, { ...elem, ...{ x, y, w, h, angle } }, elem?.desc?.bgColor);
|
||||
|
|
@ -83,7 +83,7 @@ export function drawGroup(ctx: ViewContext2D, elem: Element<'group'>, opts: Rend
|
|||
y: newParentSize.y + child.y
|
||||
}
|
||||
};
|
||||
if (!calculator.isElementInView(child, opts.scaleInfo, opts.viewSize)) {
|
||||
if (!calculator.isElementInView(child, opts.viewScaleInfo, opts.viewSizeInfo)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { rotateElement } from '@idraw/util';
|
|||
|
||||
export function drawHTML(ctx: ViewContext2D, elem: Element<'html'>, opts: RendererDrawElementOptions) {
|
||||
const content = opts.loader.getContent(elem.uuid);
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
if (!content) {
|
||||
opts.loader.load(elem as Element<'html'>);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { rotateElement } from '@idraw/util';
|
|||
|
||||
export function drawImage(ctx: ViewContext2D, elem: Element<'image'>, opts: RendererDrawElementOptions) {
|
||||
const content = opts.loader.getContent(elem.uuid);
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
if (!content) {
|
||||
opts.loader.load(elem as Element<'image'>);
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import { rotateElement } from '@idraw/util';
|
|||
|
||||
export function drawRect(ctx: ViewContext2D, elem: Element<'rect'>, opts: RendererDrawElementOptions) {
|
||||
// const { desc } = elem;
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
let r: number = (elem.desc.borderRadius || 0) * scaleInfo.scale;
|
||||
let r: number = (elem.desc.borderRadius || 0) * viewScaleInfo.scale;
|
||||
r = Math.min(r, w / 2, h / 2);
|
||||
if (w < r * 2 || h < r * 2) {
|
||||
r = 0;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { rotateElement } from '@idraw/util';
|
|||
|
||||
export function drawSVG(ctx: ViewContext2D, elem: Element<'svg'>, opts: RendererDrawElementOptions) {
|
||||
const content = opts.loader.getContent(elem.uuid);
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
if (!content) {
|
||||
opts.loader.load(elem as Element<'svg'>);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import { is, isColorStr } from '@idraw/util';
|
|||
import { drawBox } from './base';
|
||||
|
||||
export function drawText(ctx: ViewContext2D, elem: Element<'text'>, opts: RendererDrawElementOptions) {
|
||||
const { calculator, scaleInfo, viewSize } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, scaleInfo, viewSize);
|
||||
const { calculator, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const { x, y, w, h, angle } = calculator.elementSize(elem, viewScaleInfo, viewSizeInfo);
|
||||
rotateElement(ctx, { x, y, w, h, angle }, () => {
|
||||
drawBox(ctx, { ...elem, ...{ x, y, w, h, angle } }, elem.desc.bgColor || 'transparent');
|
||||
const desc: Element<'text'>['desc'] = {
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ export class Renderer extends EventEmitter<RendererEventMap> implements BoardRen
|
|||
const parentElementSize = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: opts.viewSize.width,
|
||||
h: opts.viewSize.height
|
||||
w: opts.viewSizeInfo.width,
|
||||
h: opts.viewSizeInfo.height
|
||||
};
|
||||
drawElementList(viewContext, data.elements, {
|
||||
loader,
|
||||
|
|
@ -60,14 +60,14 @@ export class Renderer extends EventEmitter<RendererEventMap> implements BoardRen
|
|||
sharer.getActiveStoreSnapshot();
|
||||
if (data) {
|
||||
this.drawData(data, {
|
||||
scaleInfo: {
|
||||
viewScaleInfo: {
|
||||
scale: num,
|
||||
offsetTop,
|
||||
offsetBottom,
|
||||
offsetLeft,
|
||||
offsetRight
|
||||
},
|
||||
viewSize: {
|
||||
viewSizeInfo: {
|
||||
width,
|
||||
height,
|
||||
contextX,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export type BoardWatherScrollYEvent = ViewScaleInfo;
|
|||
|
||||
export type BoardWatherResizeEvent = ViewSizeInfo;
|
||||
|
||||
export interface BoardWatcherEventMap<S extends Record<any | symbol, any>> {
|
||||
export interface BoardWatcherEventMap<S extends Record<any | symbol, any> = any> {
|
||||
hover: BoardWatcherPointEvent;
|
||||
pointStart: BoardWatcherPointEvent;
|
||||
pointMove: BoardWatcherPointEvent;
|
||||
|
|
@ -49,7 +49,7 @@ export interface BoardWatcherEventMap<S extends Record<any | symbol, any>> {
|
|||
|
||||
export type BoardMode = 'SELECT' | 'SCROLL' | 'RULE' | 'CONNECT' | 'PENCIL' | 'PEN' | string;
|
||||
|
||||
export interface BoardMiddlewareObject<S extends Record<any | symbol, any>> {
|
||||
export interface BoardMiddlewareObject<S extends Record<any | symbol, any> = any> {
|
||||
mode: BoardMode;
|
||||
isDefault?: boolean;
|
||||
created?: () => void;
|
||||
|
|
@ -86,7 +86,7 @@ export interface BoardOptions {
|
|||
viewContent: ViewContent;
|
||||
}
|
||||
|
||||
export interface BoardViewerFrameSnapshot<S extends Record<any | symbol, any>> {
|
||||
export interface BoardViewerFrameSnapshot<S extends Record<any | symbol, any> = any> {
|
||||
activeStore: ActiveStore;
|
||||
sharedStore: S;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ export interface RendererLoader extends UtilEventEmitter<LoaderEventMap> {
|
|||
}
|
||||
|
||||
export interface RendererDrawOptions {
|
||||
viewSize: ViewSizeInfo;
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
}
|
||||
|
||||
export interface RendererDrawElementOptions extends RendererDrawOptions {
|
||||
loader: RendererLoader;
|
||||
calculator: ViewCalculator;
|
||||
scaleInfo: ViewScaleInfo;
|
||||
viewSize: ViewSizeInfo;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
parentElementSize: ElementSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@ export type ActiveStore = ViewSizeInfo &
|
|||
selectedUUIDs: string[];
|
||||
};
|
||||
|
||||
export interface StoreSharer<S extends Record<any, any>> {
|
||||
export interface StoreSharer<S extends Record<any, any> = any> {
|
||||
getActiveStorage<T extends keyof ActiveStore>(key: T): ActiveStore[T];
|
||||
setActiveStorage<T extends keyof ActiveStore>(key: T, storage: ActiveStore[T]): void;
|
||||
getActiveStoreSnapshot(): ActiveStore;
|
||||
getSharedStorage<K extends keyof S>(key: K): S[K];
|
||||
setSharedStorage<K extends keyof S>(key: K, storage: S[K]): void;
|
||||
getSharedStorage<K extends keyof S = string>(key: K): S[K];
|
||||
setSharedStorage<K extends keyof S = string>(key: K, storage: S[K]): void;
|
||||
getSharedStoreSnapshot(): Record<string, any>;
|
||||
|
||||
getActiveScaleInfo(): ViewScaleInfo;
|
||||
setActiveScaleInfo(scaleInfo: ViewScaleInfo): void;
|
||||
setActiveScaleInfo(viewScaleInfo: ViewScaleInfo): void;
|
||||
setActiveViewSizeInfo(size: ViewSizeInfo): void;
|
||||
getActiveViewSizeInfo(): ViewSizeInfo;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,13 +35,10 @@ export interface ViewCalculatorOptions {
|
|||
}
|
||||
|
||||
export interface ViewCalculator {
|
||||
viewScale(num: number, prevScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): ViewScaleInfo;
|
||||
isElementInView(elem: Element<ElementType>, scaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): boolean;
|
||||
isPointInElement(p: Point, elem: Element<ElementType>, scaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): boolean;
|
||||
elementSize(size: ElementSize, scaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ElementSize;
|
||||
viewScroll(opts: { moveX?: number; moveY?: number }, scaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo;
|
||||
getPointElement(p: Point, data: Data, scaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> };
|
||||
// rotateElementSize(elemSize: ElementSize): PointSize[];
|
||||
// pointToViewPoint( p: Point): Point;
|
||||
// TODO
|
||||
// viewScale(num: number, prevScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): ViewScaleInfo;
|
||||
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;
|
||||
viewScroll(opts: { moveX?: number; moveY?: number }, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo;
|
||||
getPointElement(p: Point, data: Data, viewScaleInfo: ViewScaleInfo, viewSize: ViewSizeInfo): { index: number; element: null | Element<ElementType> };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,3 +23,4 @@ export {
|
|||
calcElementsViewInfo
|
||||
} from './lib/element';
|
||||
export { checkRectIntersect } from './lib/rect';
|
||||
export { viewScale, viewScroll, calcElementSize, isViewPointInElement, getViewPointAtElement, isElementInView } from './lib/view-calc';
|
||||
|
|
|
|||
176
packages/util/src/lib/view-calc.ts
Normal file
176
packages/util/src/lib/view-calc.ts
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
import { Point, Data, ViewScaleInfo, ViewSizeInfo, Element, ElementType, ElementSize } from '@idraw/types';
|
||||
import { rotateElementVertexes } from './rotate';
|
||||
import { Context2D } from './context2d';
|
||||
import { checkRectIntersect } from './rect';
|
||||
|
||||
export function viewScale(num: number, opts: { prevViewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ViewScaleInfo {
|
||||
const scale = num;
|
||||
const { prevViewScaleInfo, viewSizeInfo } = opts;
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = 0;
|
||||
let offsetRight = 0;
|
||||
let offsetTop = 0;
|
||||
let offsetBottom = 0;
|
||||
|
||||
if (contextWidth * scale < width) {
|
||||
offsetLeft = offsetRight = (width - contextWidth * scale) / 2;
|
||||
} else if (contextWidth * scale > width) {
|
||||
if (prevViewScaleInfo.offsetLeft < 0) {
|
||||
offsetLeft = (prevViewScaleInfo.offsetLeft / prevViewScaleInfo.scale) * scale;
|
||||
offsetRight = 0 - (contextWidth * scale - width - Math.abs(offsetLeft));
|
||||
}
|
||||
}
|
||||
|
||||
if (contextHeight * scale < height) {
|
||||
offsetTop = offsetBottom = (height - contextHeight * scale) / 2;
|
||||
} else if (contextHeight * scale > height) {
|
||||
if (prevViewScaleInfo.offsetTop < 0) {
|
||||
offsetTop = (prevViewScaleInfo.offsetTop / prevViewScaleInfo.scale) * scale;
|
||||
offsetBottom = 0 - (contextHeight * scale - height - Math.abs(offsetTop));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
scale,
|
||||
offsetTop,
|
||||
offsetLeft,
|
||||
offsetRight,
|
||||
offsetBottom
|
||||
};
|
||||
}
|
||||
|
||||
export function viewScroll(opts: { moveX?: number; moveY?: number }, viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeInfo): ViewScaleInfo {
|
||||
const scale = viewScaleInfo.scale;
|
||||
const { moveX, moveY } = opts;
|
||||
const { width, height, contextWidth, contextHeight } = viewSizeInfo;
|
||||
let offsetLeft = viewScaleInfo.offsetLeft;
|
||||
let offsetRight = viewScaleInfo.offsetRight;
|
||||
let offsetTop = viewScaleInfo.offsetTop;
|
||||
let offsetBottom = viewScaleInfo.offsetBottom;
|
||||
if (moveX !== undefined && (moveX > 0 || moveX <= 0)) {
|
||||
if (contextWidth * scale < width) {
|
||||
offsetLeft = offsetRight = (width - contextWidth * scale) / 2;
|
||||
} else if (contextWidth * scale > width) {
|
||||
if (offsetLeft + moveX >= 0) {
|
||||
offsetLeft = 0;
|
||||
offsetRight = width - contextWidth * scale;
|
||||
} else if (offsetLeft + moveX < width - contextWidth * scale) {
|
||||
offsetLeft = width - contextWidth * scale;
|
||||
offsetRight = 0;
|
||||
} else {
|
||||
offsetLeft += moveX;
|
||||
offsetRight = width - contextWidth * scale - offsetLeft;
|
||||
}
|
||||
} else {
|
||||
offsetLeft = offsetRight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (moveY !== undefined && (moveY > 0 || moveY <= 0)) {
|
||||
if (contextHeight * scale < height) {
|
||||
offsetTop = offsetBottom = (height - contextHeight * scale) / 2;
|
||||
} else if (contextHeight * scale > height) {
|
||||
if (offsetTop + moveY >= 0) {
|
||||
offsetTop = 0;
|
||||
offsetBottom = height - contextHeight * scale;
|
||||
} else if (offsetTop + moveY < height - contextHeight * scale) {
|
||||
offsetTop = height - contextHeight * scale;
|
||||
offsetBottom = 0;
|
||||
} else {
|
||||
offsetTop += moveY;
|
||||
offsetBottom = height - contextHeight * scale - offsetTop;
|
||||
}
|
||||
} else {
|
||||
offsetTop = offsetBottom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
scale,
|
||||
offsetTop,
|
||||
offsetLeft,
|
||||
offsetRight,
|
||||
offsetBottom
|
||||
};
|
||||
}
|
||||
|
||||
export function calcElementSize(size: ElementSize, opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ElementSize {
|
||||
const { viewScaleInfo, viewSizeInfo } = opts;
|
||||
const { x, y, w, h, angle } = size;
|
||||
const { contextX = 0, contextY = 0 } = viewSizeInfo;
|
||||
const { scale, offsetTop, offsetLeft } = viewScaleInfo;
|
||||
|
||||
const newSize = {
|
||||
x: x * scale + offsetLeft - contextX,
|
||||
y: y * scale + offsetTop - contextY,
|
||||
w: w * scale,
|
||||
h: h * scale,
|
||||
angle
|
||||
};
|
||||
|
||||
return newSize;
|
||||
}
|
||||
|
||||
export function isViewPointInElement(
|
||||
p: Point,
|
||||
opts: { context2d: Context2D; element: Element<ElementType>; viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }
|
||||
): boolean {
|
||||
const { context2d: ctx, element: elem, viewScaleInfo, viewSizeInfo } = opts;
|
||||
|
||||
const { angle = 0 } = elem;
|
||||
const { x, y, w, h } = calcElementSize(elem, { viewScaleInfo, viewSizeInfo });
|
||||
const vertexes = rotateElementVertexes({ x, y, w, h, angle });
|
||||
if (vertexes.length >= 2) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vertexes[0].x, vertexes[0].y);
|
||||
for (let i = 1; i < vertexes.length; i++) {
|
||||
ctx.lineTo(vertexes[i].x, vertexes[i].y);
|
||||
}
|
||||
ctx.closePath();
|
||||
}
|
||||
if (ctx.isPointInPath(p.x, p.y)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getViewPointAtElement(
|
||||
p: Point,
|
||||
opts: {
|
||||
context2d: Context2D;
|
||||
data: Data;
|
||||
viewScaleInfo: ViewScaleInfo;
|
||||
viewSizeInfo: ViewSizeInfo;
|
||||
}
|
||||
): { index: number; element: null | Element<ElementType> } {
|
||||
const { context2d: ctx, data, viewScaleInfo, viewSizeInfo } = opts;
|
||||
const result: { index: number; element: null | Element<ElementType> } = {
|
||||
index: -1,
|
||||
element: null
|
||||
};
|
||||
for (let i = data.elements.length - 1; i >= 0; i--) {
|
||||
const elem = data.elements[i];
|
||||
if (isViewPointInElement(p, { context2d: ctx, element: elem, viewScaleInfo, viewSizeInfo })) {
|
||||
result.index = i;
|
||||
result.element = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isElementInView(elem: ElementSize, opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): boolean {
|
||||
const { viewSizeInfo, viewScaleInfo } = opts;
|
||||
const { width, height } = viewSizeInfo;
|
||||
const { angle } = elem;
|
||||
const { x, y, w, h } = calcElementSize(elem, { viewScaleInfo, viewSizeInfo });
|
||||
const ves = rotateElementVertexes({ x, y, w, h, angle });
|
||||
const viewSize = { x: 0, y: 0, w: width, h: height };
|
||||
|
||||
const elemStartX = Math.min(ves[0].x, ves[1].x, ves[2].x, ves[3].x);
|
||||
const elemStartY = Math.min(ves[0].y, ves[1].y, ves[2].y, ves[3].y);
|
||||
const elemEndX = Math.max(ves[0].x, ves[1].x, ves[2].x, ves[3].x);
|
||||
const elemEndY = Math.max(ves[0].y, ves[1].y, ves[2].y, ves[3].y);
|
||||
const elemSize = { x: elemStartX, y: elemStartY, w: elemEndX - elemStartX, h: elemEndY - elemStartY };
|
||||
return checkRectIntersect(viewSize, elemSize);
|
||||
}
|
||||
Loading…
Reference in a new issue