refactor: refactor selector middleware

This commit is contained in:
chenshenhai 2023-09-16 17:25:39 +08:00
parent eef66ff7c4
commit 5e5b4ffc92
18 changed files with 859 additions and 221 deletions

View file

@ -5,8 +5,6 @@ const defaultActiveStorage: ActiveStore = {
width: 0,
height: 0,
devicePixelRatio: 1,
contextX: 0,
contextY: 0,
contextWidth: 0,
contextHeight: 0,
data: null,
@ -84,8 +82,6 @@ export class Sharer implements StoreSharer<Record<string | number | symbol, any>
this._activeStore.set('width', size.width);
this._activeStore.set('height', size.height);
this._activeStore.set('devicePixelRatio', size.devicePixelRatio);
this._activeStore.set('contextX', size.contextX);
this._activeStore.set('contextY', size.contextY);
this._activeStore.set('contextWidth', size.contextWidth);
this._activeStore.set('contextHeight', size.contextHeight);
}
@ -95,8 +91,6 @@ export class Sharer implements StoreSharer<Record<string | number | symbol, any>
width: this._activeStore.get('width'),
height: this._activeStore.get('height'),
devicePixelRatio: this._activeStore.get('devicePixelRatio'),
contextX: this._activeStore.get('contextX'),
contextY: this._activeStore.get('contextY'),
contextWidth: this._activeStore.get('contextWidth'),
contextHeight: this._activeStore.get('contextHeight')
};

View file

@ -43,8 +43,7 @@ export class Viewer extends EventEmitter<BoardViewerEventMap> implements BoardVi
const { renderer, viewContent, beforeDrawFrame, afterDrawFrame } = this._opts;
if (snapshot) {
const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio } =
snapshot.activeStore;
const { scale, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextHeight, contextWidth, devicePixelRatio } = snapshot.activeStore;
const { viewContext, helperContext, boardContext } = viewContent;
if (snapshot?.activeStore.data) {
@ -59,8 +58,6 @@ export class Viewer extends EventEmitter<BoardViewerEventMap> implements BoardVi
viewSizeInfo: {
width,
height,
contextX,
contextY,
contextHeight,
contextWidth,
devicePixelRatio

View file

@ -29,8 +29,6 @@ export class Core {
width,
height,
devicePixelRatio,
contextX: 0,
contextY: 0,
contextWidth: width,
contextHeight: height
});

View file

@ -99,17 +99,13 @@ export const MiddlewareScroller: BoardMiddleware = (opts) => {
}
},
pointEnd: (e: PointWatcherEvent) => {
// const { point } = e;
// if (activeThumbType === 'X' || activeThumbType === 'Y') {
// if (activeThumbType === 'X') {
// scrollX(point);
// } else if (activeThumbType === 'Y') {
// scrollY(point);
// }
// activeThumbType = null;
// return false;
// }
const activeThumbType = sharer.getSharedStorage(keyActiveThumbType);
clear();
if (activeThumbType === 'X' || activeThumbType === 'Y') {
viewer.scroll({ moveX: 0, moveY: 0 });
viewer.drawFrame();
return false;
}
},
beforeDrawFrame({ snapshot }) {
const { xThumbRect, yThumbRect } = drawScroller(helperContext, { snapshot });

View file

@ -78,7 +78,7 @@ function calcScrollerInfo(viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeIn
}
ySize = Math.max(sliderMinSize, height - (Math.abs(offsetTop) + Math.abs(offsetBottom)));
if (ySize >= height) {
ySize = width;
ySize = height;
}
const xStart = lineSize / 2;
@ -95,7 +95,7 @@ function calcScrollerInfo(viewScaleInfo: ViewScaleInfo, viewSizeInfo: ViewSizeIn
}
const yStart = lineSize / 2;
const yEnd = width - xSize - lineSize;
const yEnd = height - ySize - lineSize;
let translateY = yStart;
if (offsetTop > 0) {
translateY = yStart;

View file

@ -55,7 +55,7 @@ export function drawSelectedElementControllersVertexes(
if (!controller) {
return;
}
const { elementWrapper, left, right, top, bottom } = controller;
const { elementWrapper, left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight } = controller;
// const wrapperColor = 'red'; // TODO
const wrapperOpts = { borderColor: wrapperColor, borderWidth: 1, bgColor: 'transparent', lineDash: [] };
const ctrlOpts = { ...wrapperOpts, borderWidth: resizeControllerBorderWidth, bgColor: '#FFFFFF' };
@ -65,6 +65,10 @@ export function drawSelectedElementControllersVertexes(
drawVertexes(ctx, calcViewVertexes(right.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(top.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(bottom.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(topLeft.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(topRight.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(bottomLeft.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(bottomRight.vertexes, opts), ctrlOpts);
}
export function drawElementListShadows(ctx: ViewContext2D, elements: Element<ElementType>[], opts?: Omit<RendererDrawElementOptions, 'loader'>) {

View file

@ -321,8 +321,7 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
resizeStart = rotatePointInGroup(start, pointGroupQueue);
resizeEnd = rotatePointInGroup(end, pointGroupQueue);
}
const resizedElemSize = resizeElement(elems[0], { scale, start: resizeStart, end: resizeEnd, resizeType });
// const resizedElemSize = resizeElement(elems[0], { scale, start, end, resizeType });
const resizedElemSize = resizeElement(elems[0], { scale, start: resizeStart, end: resizeEnd, resizeType, sharer });
elems[0].x = resizedElemSize.x;
elems[0].y = resizedElemSize.y;
elems[0].w = resizedElemSize.w;
@ -396,8 +395,6 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
}
if (data && Array.isArray(data?.elements) && (['drag', 'drag-list'] as ActionType[]).includes(actionType)) {
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);
sharer.setActiveStorage('contextWidth', viewInfo.contextSize.contextWidth);
// TODO
@ -432,11 +429,10 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
beforeDrawFrame({ snapshot }) {
const { activeStore, sharedStore } = snapshot;
const { scale, offsetLeft, offsetTop, offsetRight, offsetBottom, width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio } =
activeStore;
const { scale, offsetLeft, offsetTop, offsetRight, offsetBottom, width, height, contextHeight, contextWidth, devicePixelRatio } = activeStore;
const viewScaleInfo = { scale, offsetLeft, offsetTop, offsetRight, offsetBottom };
const viewSizeInfo = { width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio };
const viewSizeInfo = { width, height, contextHeight, contextWidth, devicePixelRatio };
const selectedElements = sharedStore[keySelectedElementList];
const elem = selectedElements[0];
const hoverElement: ElementSize = sharedStore[keyHoverElement] as ElementSize;
@ -478,6 +474,39 @@ export const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage> = (o
}
}
}
// // TODO mock data
// const sharer = opts.sharer;
// const elemCenter: any = sharer.getSharedStorage('TODO_elemCenter');
// const startVertical = sharer.getSharedStorage('TODO_startVertical');
// const endVertical: any = sharer.getSharedStorage('TODO_endVertical');
// const startHorizontal = sharer.getSharedStorage('TODO_startHorizontal');
// const endHorizontal: any = sharer.getSharedStorage('TODO_endHorizontal');
// const end0: any = sharer.getSharedStorage('TODO_end0');
// if (elemCenter && end0) {
// helperContext.beginPath();
// helperContext.moveTo(elemCenter.x, elemCenter.y);
// helperContext.lineTo(end0.x, end0.y);
// helperContext.closePath();
// helperContext.strokeStyle = 'black';
// helperContext.stroke();
// }
// if (elemCenter && endVertical) {
// helperContext.beginPath();
// helperContext.moveTo(elemCenter.x, elemCenter.y);
// helperContext.lineTo(endVertical.x, endVertical.y);
// helperContext.closePath();
// helperContext.strokeStyle = 'red';
// helperContext.stroke();
// }
// if (elemCenter && endHorizontal) {
// helperContext.beginPath();
// helperContext.moveTo(elemCenter.x, elemCenter.y);
// helperContext.lineTo(endHorizontal.x, endHorizontal.y);
// helperContext.closePath();
// helperContext.strokeStyle = 'blue';
// helperContext.stroke();
// }
}
};
};

View file

@ -52,7 +52,15 @@ export type ControllerStyle = ElementSize & {
export type SelectedElementSizeController = Record<string, ControllerStyle>;
export type ResizeType = 'resize-left' | 'resize-right' | 'resize-top' | 'resize-bottom';
export type ResizeType =
| 'resize-left'
| 'resize-right'
| 'resize-top'
| 'resize-bottom'
| 'resize-top-left'
| 'resize-top-right'
| 'resize-bottom-left'
| 'resize-bottom-right';
export type PointTargetType = null | ResizeType | 'list-area' | 'over-element';

View file

@ -4,9 +4,12 @@ import {
calcElementVertexesInGroup,
calcElementQueueVertexesQueueInGroup,
calcViewPointSize,
rotatePointInGroup
rotatePointInGroup,
rotatePoint,
parseAngleToRadian,
limitAngle
} from '@idraw/util';
import type { ViewRectVertexes, ElementSizeController } from '@idraw/types';
import type { ViewRectVertexes, ElementSizeController, StoreSharer } from '@idraw/types';
import type {
Data,
Element,
@ -100,8 +103,8 @@ export function getPointTarget(
// resize
if (selectedElementController) {
const { left, right, top, bottom } = selectedElementController;
const ctrls = [left, right, top, bottom];
const { left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight } = selectedElementController;
const ctrls = [left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight];
for (let i = 0; i < ctrls.length; i++) {
const ctrl = ctrls[i];
if (isPointInViewActiveVertexes(p, { ctx, vertexes: ctrl.vertexes, viewSizeInfo, viewScaleInfo })) {
@ -121,6 +124,9 @@ export function getPointTarget(
if (lastGroup?.detail?.children && Array.isArray(lastGroup?.detail?.children)) {
for (let i = lastGroup.detail.children.length - 1; i >= 0; i--) {
const child = lastGroup.detail.children[i];
// if (child?.operations?.invisible === true) {
// continue;
// }
const vertexes = calcElementVertexesInGroup(child, { groupQueue });
if (vertexes && isPointInViewActiveVertexes(p, { ctx, vertexes, viewScaleInfo, viewSizeInfo })) {
target.type = 'over-element';
@ -146,7 +152,7 @@ export function getPointTarget(
// over-element
if (data) {
const { index, element } = calculator.getPointElement(p as Point, { data, viewScaleInfo, viewSizeInfo });
if (index >= 0 && element) {
if (index >= 0 && element && element?.operations?.invisible !== true) {
target.elements = [element];
target.type = 'over-element';
return target;
@ -163,16 +169,66 @@ export function resizeElement(
end: PointSize;
resizeType: ResizeType;
scale: number;
sharer: StoreSharer; // TODO
}
): ElementSize {
let { x, y, w, h, angle = 0 } = elem;
if (angle < 0) {
angle = Math.max(0, 360 + angle);
}
const elemCenter = calcElementCenter({ x, y, w, h, angle });
// const centerX = elemCenter.x;
// const centerY = elemCenter.y;
angle = angle > 0 ? angle : Math.max(0, angle + 360);
angle = limitAngle(angle);
const radian = parseAngleToRadian(angle);
const { start, end, resizeType, scale } = opts;
let start0: PointSize = { ...start };
let end0: PointSize = { ...end };
let startHorizontal0 = { x: start0.x, y: elemCenter.y };
let endHorizontal0 = { x: end0.x, y: elemCenter.y };
let startHorizontal = { ...startHorizontal0 };
let endHorizontal = { ...endHorizontal0 };
let startVertical0 = { x: elemCenter.x, y: start0.y };
let endVertical0 = { x: elemCenter.x, y: end0.y };
let startVertical = { ...startVertical0 };
let endVertical = { ...endVertical0 };
let moveHorizontalX = (endHorizontal.x - startHorizontal.x) / scale;
let moveHorizontalY = (endHorizontal.y - startHorizontal.y) / scale;
let moveHorizontalDist = calcMoveDist(moveHorizontalX, moveHorizontalY);
let centerMoveHorizontalDist = 0;
let moveVerticalX = (endVertical.x - startVertical.x) / scale;
let moveVerticalY = (endVertical.y - startVertical.y) / scale;
let moveVerticalDist = calcMoveDist(moveVerticalX, moveVerticalY);
let centerMoveVerticalDist = 0;
if (angle > 0 || angle < 0) {
start0 = rotatePoint(elemCenter, start, 0 - radian);
end0 = rotatePoint(elemCenter, end, 0 - radian);
startHorizontal0 = { x: start0.x, y: elemCenter.y };
endHorizontal0 = { x: end0.x, y: elemCenter.y };
startHorizontal = rotatePoint(elemCenter, startHorizontal0, radian);
endHorizontal = rotatePoint(elemCenter, endHorizontal0, radian);
startVertical0 = { x: elemCenter.x, y: start0.y };
endVertical0 = { x: elemCenter.x, y: end0.y };
startVertical = rotatePoint(elemCenter, startVertical0, radian);
endVertical = rotatePoint(elemCenter, endVertical0, radian);
moveHorizontalX = (endHorizontal.x - startHorizontal.x) / scale;
moveHorizontalY = (endHorizontal.y - startHorizontal.y) / scale;
moveHorizontalDist = calcMoveDist(moveHorizontalX, moveHorizontalY);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
centerMoveHorizontalDist = moveHorizontalDist / 2;
moveVerticalX = (endVertical.x - startVertical.x) / scale;
moveVerticalY = (endVertical.y - startVertical.y) / scale;
moveVerticalDist = calcMoveDist(moveVerticalX, moveVerticalY);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
centerMoveVerticalDist = moveVerticalDist / 2;
}
let moveX = (end.x - start.x) / scale;
let moveY = (end.y - start.y) / scale;
@ -184,7 +240,7 @@ export function resizeElement(
switch (resizeType) {
case 'resize-top': {
if (elem.angle === 0) {
if (angle === 0) {
if (h - moveY > 0) {
y += moveY;
h -= moveY;
@ -193,58 +249,47 @@ export function resizeElement(
w -= (moveY / elem.h) * elem.w;
}
}
} else if (elem.angle !== undefined && (elem.angle > 0 || elem.angle < 0)) {
const angle = elem.angle > 0 ? elem.angle : Math.max(0, elem.angle + 360);
let moveDist = calcMoveDist(moveX, moveY);
let centerX = x + elem.w / 2;
let centerY = y + elem.h / 2;
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
moveDist = 0 - changeMoveDistDirect(moveDist, moveY);
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.sin(radian);
centerY = centerY - centerMoveDist * Math.cos(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
centerY = centerY - centerMoveVerticalDist * Math.cos(radian);
} else if (angle < 180) {
moveDist = changeMoveDistDirect(moveDist, moveX);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 90);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.cos(radian);
centerY = centerY + centerMoveVerticalDist * Math.sin(radian);
} else if (angle < 270) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle - 180);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.sin(radian);
centerY = centerY + centerMoveDist * Math.cos(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
} else if (angle < 360) {
moveDist = 0 - changeMoveDistDirect(moveDist, moveX);
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 270);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.cos(radian);
centerY = centerY - centerMoveDist * Math.sin(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.cos(radian);
centerY = centerY - centerMoveVerticalDist * Math.sin(radian);
}
if (h + moveDist > 0) {
if (h + moveVerticalDist > 0) {
if (elem.operations?.limitRatio === true) {
w = w + (moveDist / elem.h) * elem.w;
w = w + (moveVerticalDist / elem.h) * elem.w;
}
h = h + moveDist;
h = h + moveVerticalDist;
x = centerX - w / 2;
y = centerY - h / 2;
}
} else {
if (h - moveY > 0) {
y += moveY;
h -= moveY;
if (elem.operations?.limitRatio === true) {
x -= moveX / 2;
w += moveX;
}
}
}
break;
}
case 'resize-bottom': {
if (elem.angle === 0) {
if (angle === 0) {
if (elem.h + moveY > 0) {
h += moveY;
if (elem.operations?.limitRatio === true) {
@ -252,57 +297,47 @@ export function resizeElement(
w += (moveY / elem.h) * elem.w;
}
}
} else if (elem.angle !== undefined && (elem.angle > 0 || elem.angle < 0)) {
const angle = elem.angle > 0 ? elem.angle : Math.max(0, elem.angle + 360);
let moveDist = calcMoveDist(moveX, moveY);
let centerX = x + elem.w / 2;
let centerY = y + elem.h / 2;
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.sin(radian);
centerY = centerY + centerMoveDist * Math.cos(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
} else if (angle < 180) {
moveDist = 0 - changeMoveDistDirect(moveDist, moveX);
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 90);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.cos(radian);
centerY = centerY - centerMoveDist * Math.sin(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.cos(radian);
centerY = centerY - centerMoveVerticalDist * Math.sin(radian);
} else if (angle < 270) {
moveDist = changeMoveDistDirect(moveDist, moveX);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 180);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.sin(radian);
centerY = centerY - centerMoveDist * Math.cos(radian);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
centerY = centerY - centerMoveVerticalDist * Math.cos(radian);
} else if (angle < 360) {
moveDist = changeMoveDistDirect(moveDist, moveX);
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 270);
const centerMoveDist = moveDist / 2;
const centerMoveDist = moveVerticalDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
}
if (h + moveDist > 0) {
if (h + moveVerticalDist > 0) {
if (elem.operations?.limitRatio === true) {
w = w + (moveDist / elem.h) * elem.w;
w = w + (moveVerticalDist / elem.h) * elem.w;
}
h = h + moveDist;
h = h + moveVerticalDist;
x = centerX - w / 2;
y = centerY - h / 2;
}
} else {
if (elem.h + moveY > 0) {
h += moveY;
if (elem.operations?.limitRatio === true) {
x -= ((moveY / elem.h) * elem.w) / 2;
w += (moveY / elem.h) * elem.w;
}
}
}
break;
}
case 'resize-left': {
if (angle === 0 || !angle) {
if (angle === 0) {
if (elem.w - moveX > 0) {
x += moveX;
w -= moveX;
@ -311,58 +346,47 @@ export function resizeElement(
y += ((moveX / elem.w) * elem.h) / 2;
}
}
} else if (elem.angle !== undefined && (elem.angle > 0 || elem.angle < 0)) {
const angle = elem.angle > 0 ? elem.angle : Math.max(0, elem.angle + 360);
let moveDist = calcMoveDist(moveX, moveY);
let centerX = x + elem.w / 2;
let centerY = y + elem.h / 2;
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
moveDist = 0 - changeMoveDistDirect(moveDist, moveX);
moveHorizontalDist = 0 - changeMoveDistDirect(moveHorizontalDist, moveHorizontalX);
const radian = parseRadian(angle);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.cos(radian);
centerY = centerY - centerMoveDist * Math.sin(radian);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 180) {
moveDist = changeMoveDistDirect(moveDist, moveX);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalX);
const radian = parseRadian(angle - 90);
const centerMoveDist = moveDist / 2;
const centerMoveDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveDist * Math.sin(radian);
centerY = centerY - centerMoveDist * Math.cos(radian);
} else if (angle < 270) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle - 180);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 360) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle - 270);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.sin(radian);
centerY = centerY + centerMoveDist * Math.cos(radian);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
}
if (w + moveDist > 0) {
if (w + moveHorizontalDist > 0) {
if (elem.operations?.limitRatio === true) {
h = h + (moveDist / elem.w) * elem.h;
h = h + (moveHorizontalDist / elem.w) * elem.h;
}
w = w + moveDist;
w = w + moveHorizontalDist;
x = centerX - w / 2;
y = centerY - h / 2;
}
} else {
if (elem.w - moveX > 0) {
x += moveX;
w -= moveX;
if (elem.operations?.limitRatio === true) {
h -= (moveX / elem.w) * elem.h;
y += ((moveX / elem.w) * elem.h) / 2;
}
}
}
break;
}
case 'resize-right': {
if (angle === 0 || !angle) {
if (angle === 0) {
if (elem.w + moveX > 0) {
w += moveX;
if (elem.operations?.limitRatio === true) {
@ -370,53 +394,419 @@ export function resizeElement(
h += (moveX * elem.h) / elem.w;
}
}
} else if (elem.angle !== undefined && (elem.angle > 0 || elem.angle < 0)) {
const angle = elem.angle > 0 ? elem.angle : Math.max(0, elem.angle + 360);
let moveDist = calcMoveDist(moveX, moveY);
let centerX = x + elem.w / 2;
let centerY = y + elem.h / 2;
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
} else if (angle < 180) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveY);
const radian = parseRadian(angle - 90);
const centerMoveDist = moveDist / 2;
centerX = centerX - centerMoveDist * Math.sin(radian);
centerY = centerY + centerMoveDist * Math.cos(radian);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
} else if (angle < 270) {
moveDist = changeMoveDistDirect(moveDist, moveY);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveY);
const radian = parseRadian(angle - 180);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
moveDist = 0 - moveDist;
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
moveHorizontalDist = 0 - moveHorizontalDist;
} else if (angle < 360) {
moveDist = changeMoveDistDirect(moveDist, moveX);
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveX);
const radian = parseRadian(angle - 270);
const centerMoveDist = moveDist / 2;
centerX = centerX + centerMoveDist * Math.sin(radian);
centerY = centerY - centerMoveDist * Math.cos(radian);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY - centerMoveHorizontalDist * Math.cos(radian);
}
if (w + moveDist > 0) {
if (w + moveHorizontalDist > 0) {
if (elem.operations?.limitRatio === true) {
h = h + (moveDist / elem.w) * elem.h;
h = h + (moveHorizontalDist / elem.w) * elem.h;
}
w = w + moveDist;
w = w + moveHorizontalDist;
x = centerX - w / 2;
y = centerY - h / 2;
}
} else {
if (elem.w + moveX > 0) {
w += moveX;
if (elem.operations?.limitRatio === true) {
h += (moveX * elem.h) / elem.w;
y -= (moveX * elem.h) / elem.w / 2;
}
break;
}
case 'resize-top-left': {
if (angle === 0) {
if (elem.w - moveX > 0) {
x += moveX;
w -= moveX;
}
if (h - moveY > 0) {
y += moveY;
h -= moveY;
}
if (elem.operations?.limitRatio === true) {
// TODO
}
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
{
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
centerY = centerY - centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = 0 - changeMoveDistDirect(moveHorizontalDist, moveHorizontalX);
const radian = parseRadian(angle);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
}
} else if (angle < 180) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.cos(radian);
centerY = centerY + centerMoveVerticalDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalX);
const radian = parseRadian(angle - 90);
const centerMoveDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveDist * Math.sin(radian);
centerY = centerY - centerMoveDist * Math.cos(radian);
}
} else if (angle < 270) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle - 180);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
}
} else if (angle < 360) {
{
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 270);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.cos(radian);
centerY = centerY - centerMoveVerticalDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle - 270);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
}
}
if (h + moveVerticalDist > 0) {
if (elem.operations?.limitRatio === true) {
w = w + (moveVerticalDist / elem.h) * elem.w;
}
h = h + moveVerticalDist;
}
if (w + moveHorizontalDist > 0) {
if (elem.operations?.limitRatio === true) {
h = h + (moveHorizontalDist / elem.w) * elem.h;
}
w = w + moveHorizontalDist;
}
x = centerX - w / 2;
y = centerY - h / 2;
}
break;
}
case 'resize-top-right': {
if (angle === 0) {
if (elem.w + moveX > 0) {
w += moveX;
}
if (h - moveY > 0) {
y += moveY;
h -= moveY;
}
if (elem.operations?.limitRatio === true) {
// TODO
}
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
{
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
centerY = centerY - centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
}
} else if (angle < 180) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.cos(radian);
centerY = centerY + centerMoveVerticalDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveY);
const radian = parseRadian(angle - 90);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
}
} else if (angle < 270) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveY);
const radian = parseRadian(angle - 180);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
moveHorizontalDist = 0 - moveHorizontalDist;
}
} else if (angle < 360) {
{
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 270);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.cos(radian);
centerY = centerY - centerMoveVerticalDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveX);
const radian = parseRadian(angle - 270);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY - centerMoveHorizontalDist * Math.cos(radian);
}
}
if (h + moveVerticalDist > 0) {
if (elem.operations?.limitRatio === true) {
w = w + (moveVerticalDist / elem.h) * elem.w;
}
h = h + moveVerticalDist;
}
if (w + moveHorizontalDist > 0) {
if (elem.operations?.limitRatio === true) {
h = h + (moveHorizontalDist / elem.w) * elem.h;
}
w = w + moveHorizontalDist;
}
x = centerX - w / 2;
y = centerY - h / 2;
}
break;
}
case 'resize-bottom-left': {
if (angle === 0) {
if (elem.h + moveY > 0) {
h += moveY;
}
if (elem.w - moveX > 0) {
x += moveX;
w -= moveX;
}
if (elem.operations?.limitRatio === true) {
// TODO
}
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = 0 - changeMoveDistDirect(moveHorizontalDist, moveHorizontalX);
const radian = parseRadian(angle);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY - centerMoveHorizontalDist * Math.sin(radian);
}
} else if (angle < 180) {
{
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.cos(radian);
centerY = centerY - centerMoveVerticalDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalX);
const radian = parseRadian(angle - 90);
const centerMoveDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveDist * Math.sin(radian);
centerY = centerY - centerMoveDist * Math.cos(radian);
}
} else if (angle < 270) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
centerY = centerY - centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle - 180);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
}
} else if (angle < 360) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 270);
const centerMoveDist = moveVerticalDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle - 270);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
}
}
if (h + moveVerticalDist > 0) {
if (elem.operations?.limitRatio === true) {
// TODO
}
h = h + moveVerticalDist;
}
if (w + moveHorizontalDist > 0) {
if (elem.operations?.limitRatio === true) {
// TODO
}
w = w + moveHorizontalDist;
}
x = centerX - w / 2;
y = centerY - h / 2;
}
break;
}
case 'resize-bottom-right': {
if (angle === 0) {
if (elem.h + moveY > 0) {
h += moveY;
}
if (elem.w + moveX > 0) {
w += moveX;
}
if (elem.operations?.limitRatio === true) {
// TODO
}
} else if (angle > 0 || angle < 0) {
let centerX = elemCenter.x;
let centerY = elemCenter.y;
if (angle < 90) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalY);
const radian = parseRadian(angle);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.sin(radian);
centerY = centerY + centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveHorizontalY);
const radian = parseRadian(angle);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
}
} else if (angle < 180) {
{
moveVerticalDist = 0 - changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 90);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX - centerMoveVerticalDist * Math.cos(radian);
centerY = centerY - centerMoveVerticalDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveY);
const radian = parseRadian(angle - 90);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX - centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY + centerMoveHorizontalDist * Math.cos(radian);
}
} else if (angle < 270) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 180);
const centerMoveVerticalDist = moveVerticalDist / 2;
centerX = centerX + centerMoveVerticalDist * Math.sin(radian);
centerY = centerY - centerMoveVerticalDist * Math.cos(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveY);
const radian = parseRadian(angle - 180);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.cos(radian);
centerY = centerY + centerMoveHorizontalDist * Math.sin(radian);
moveHorizontalDist = 0 - moveHorizontalDist;
}
} else if (angle < 360) {
{
moveVerticalDist = changeMoveDistDirect(moveVerticalDist, moveVerticalX);
const radian = parseRadian(angle - 270);
const centerMoveDist = moveVerticalDist / 2;
centerX = centerX + centerMoveDist * Math.cos(radian);
centerY = centerY + centerMoveDist * Math.sin(radian);
}
{
moveHorizontalDist = changeMoveDistDirect(moveHorizontalDist, moveX);
const radian = parseRadian(angle - 270);
const centerMoveHorizontalDist = moveHorizontalDist / 2;
centerX = centerX + centerMoveHorizontalDist * Math.sin(radian);
centerY = centerY - centerMoveHorizontalDist * Math.cos(radian);
}
}
if (h + moveVerticalDist > 0) {
if (elem.operations?.limitRatio === true) {
// TODO
}
h = h + moveVerticalDist;
}
if (w + moveHorizontalDist > 0) {
if (elem.operations?.limitRatio === true) {
// TODO
}
w = w + moveHorizontalDist;
}
x = centerX - w / 2;
y = centerY - h / 2;
}
break;
}
@ -425,6 +815,16 @@ export function resizeElement(
}
}
// // TODO mock data
// const sharer = opts.sharer;
// sharer.setSharedStorage('TODO_elemCenter', elemCenter);
// sharer.setSharedStorage('TODO_startVertical', startVertical);
// sharer.setSharedStorage('TODO_endVertical', endVertical);
// sharer.setSharedStorage('TODO_startHorizontal', startHorizontal);
// sharer.setSharedStorage('TODO_endHorizontal', endHorizontal);
// sharer.setSharedStorage('TODO_start0', startHorizontal);
// sharer.setSharedStorage('TODO_end0', end);
return { x, y, w, h, angle: elem.angle };
}

View file

@ -57,7 +57,7 @@ export class Renderer extends EventEmitter<RendererEventMap> implements BoardRen
scale(num: number) {
const { sharer } = this._opts;
const { data, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextX, contextY, contextHeight, contextWidth, devicePixelRatio } =
const { data, offsetTop, offsetBottom, offsetLeft, offsetRight, width, height, contextHeight, contextWidth, devicePixelRatio } =
sharer.getActiveStoreSnapshot();
if (data) {
this.drawData(data, {
@ -71,8 +71,6 @@ export class Renderer extends EventEmitter<RendererEventMap> implements BoardRen
viewSizeInfo: {
width,
height,
contextX,
contextY,
contextHeight,
contextWidth,
devicePixelRatio

View file

@ -1,6 +1,6 @@
import { ViewRectVertexes } from './view';
export type ElementSizeControllerType = 'left' | 'right' | 'top' | 'bottom';
export type ElementSizeControllerType = 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
export interface ElementSizeControllerItem {
type: ElementSizeControllerType;
@ -9,8 +9,12 @@ export interface ElementSizeControllerItem {
export interface ElementSizeController {
elementWrapper: ViewRectVertexes;
left: ElementSizeControllerItem;
right: ElementSizeControllerItem;
top: ElementSizeControllerItem;
bottom: ElementSizeControllerItem;
left: ElementSizeControllerItem;
right: ElementSizeControllerItem;
topLeft: ElementSizeControllerItem;
topRight: ElementSizeControllerItem;
bottomLeft: ElementSizeControllerItem;
bottomRight: ElementSizeControllerItem;
}

View file

@ -12,8 +12,6 @@ export interface ViewScaleInfo {
}
export interface ViewContextSize {
contextX: number;
contextY: number;
contextWidth: number;
contextHeight: number;
}

View file

@ -0,0 +1,214 @@
import { rotatePoint, parseAngleToRadian } from '@idraw/util';
describe('@idraw/util: rotate', () => {
test('rotatePoint', () => {
const center = { x: 100, y: 100 };
const start = { x: 200, y: 100 };
const end = rotatePoint(center, start, Math.PI / 2);
expect(end).toStrictEqual({ x: 100, y: 200 });
});
test('rotatePoint [0,90]deg, 0-30-60-90', () => {
const r = 100;
const center = { x: 0, y: 0 };
const start0 = { x: r, y: 0 };
const deg30 = 30;
const radian = parseAngleToRadian(deg30);
// 0-30
const start1 = rotatePoint(center, start0, radian);
expect(start1.x).toBeCloseTo(r * Math.cos(radian));
expect(start1.y).toBeCloseTo(r * Math.sin(radian));
// 30-60
const start2 = rotatePoint(center, start1, radian);
expect(start2.x).toBeCloseTo(r * Math.sin(radian));
expect(start2.y).toBeCloseTo(r * Math.cos(radian));
// 60-90
const start3 = rotatePoint(center, start2, radian);
expect(start3.x).toBeCloseTo(0);
expect(start3.y).toBeCloseTo(r);
});
test('rotatePoint [0,90]deg, 30-45-60-45-30', () => {
const center = { x: 0, y: 0 };
const deg15 = 15;
const radian15 = parseAngleToRadian(deg15);
const radian30 = radian15 * 2;
const r = 100;
// 30-45
const start0 = { x: r * Math.cos(radian30), y: r * Math.sin(radian30) };
const start1 = rotatePoint(center, start0, radian15);
expect(start1.x).toBeCloseTo(r * Math.cos(radian15 * 3));
expect(start1.y).toBeCloseTo(r * Math.sin(radian15 * 3));
// 45-60
const start2 = rotatePoint(center, start1, radian15);
expect(start2.x).toBeCloseTo(r * Math.sin(radian30));
expect(start2.y).toBeCloseTo(r * Math.cos(radian30));
// 60-45
const start3 = rotatePoint(center, start2, 0 - radian15);
expect(start3.x).toBeCloseTo(start1.x);
expect(start3.y).toBeCloseTo(start1.y);
// 45-30
const start4 = rotatePoint(center, start3, 0 - radian15);
expect(start4.x).toBeCloseTo(start0.x);
expect(start4.y).toBeCloseTo(start0.y);
});
test('rotatePoint [90,180]deg, 90-120-150-180', () => {
const r = 100;
const center = { x: 0, y: 0 };
const start0 = { x: 0, y: r };
const deg30 = 30;
const radian = parseAngleToRadian(deg30);
// 90-120
const start1 = rotatePoint(center, start0, radian);
expect(start1.x).toBeCloseTo(-r * Math.sin(radian));
expect(start1.y).toBeCloseTo(r * Math.cos(radian));
// 120-150
const start2 = rotatePoint(center, start1, radian);
expect(start2.x).toBeCloseTo(-r * Math.cos(radian));
expect(start2.y).toBeCloseTo(r * Math.sin(radian));
// 150-180
const start3 = rotatePoint(center, start2, radian);
expect(start3.x).toBeCloseTo(-r);
expect(start3.y).toBeCloseTo(0);
});
test('rotatePoint [90,180]deg, 120-135-150-135-120', () => {
const center = { x: 0, y: 0 };
const deg15 = 15;
const radian15 = parseAngleToRadian(deg15);
const radian30 = radian15 * 2;
const r = 100;
// 120-135
const start0 = { x: -r * Math.sin(radian30), y: r * Math.cos(radian30) };
const start1 = rotatePoint(center, start0, radian15);
expect(start1.x).toBeCloseTo(-r * Math.cos(radian15 * 3));
expect(start1.y).toBeCloseTo(r * Math.sin(radian15 * 3));
// 135-150
const start2 = rotatePoint(center, start1, radian15);
expect(start2.x).toBeCloseTo(-r * Math.cos(radian30));
expect(start2.y).toBeCloseTo(r * Math.sin(radian30));
// 150-135
const start3 = rotatePoint(center, start2, 0 - radian15);
expect(start3.x).toBeCloseTo(start1.x);
expect(start3.y).toBeCloseTo(start1.y);
// 135-120
const start4 = rotatePoint(center, start3, 0 - radian15);
expect(start4.x).toBeCloseTo(start0.x);
expect(start4.y).toBeCloseTo(start0.y);
});
test('rotatePoint [180,270]deg, 180-210-240-270', () => {
const r = 100;
const center = { x: 0, y: 0 };
const start0 = { x: -r, y: 0 };
const deg30 = 30;
const radian = parseAngleToRadian(deg30);
// 180-210
const start1 = rotatePoint(center, start0, radian);
expect(start1.x).toBeCloseTo(-r * Math.cos(radian));
expect(start1.y).toBeCloseTo(-r * Math.sin(radian));
// 210-240
const start2 = rotatePoint(center, start1, radian);
expect(start2.x).toBeCloseTo(-r * Math.sin(radian));
expect(start2.y).toBeCloseTo(-r * Math.cos(radian));
// 240-270
const start3 = rotatePoint(center, start2, radian);
expect(start3.x).toBeCloseTo(0);
expect(start3.y).toBeCloseTo(-r);
});
test('rotatePoint [180,270]deg, 210-225-240-225-210', () => {
const center = { x: 0, y: 0 };
const deg15 = 15;
const radian15 = parseAngleToRadian(deg15);
const radian30 = radian15 * 2;
const r = 100;
// 210-225
const start0 = { x: -r * Math.cos(radian30), y: -r * Math.sin(radian30) };
const start1 = rotatePoint(center, start0, radian15);
expect(start1.x).toBeCloseTo(-r * Math.sin(radian15 * 3));
expect(start1.y).toBeCloseTo(-r * Math.cos(radian15 * 3));
// 225-240
const start2 = rotatePoint(center, start1, radian15);
expect(start2.x).toBeCloseTo(-r * Math.sin(radian30));
expect(start2.y).toBeCloseTo(-r * Math.cos(radian30));
// 240-225
const start3 = rotatePoint(center, start2, 0 - radian15);
expect(start3.x).toBeCloseTo(start1.x);
expect(start3.y).toBeCloseTo(start1.y);
// 225-210
const start4 = rotatePoint(center, start3, 0 - radian15);
expect(start4.x).toBeCloseTo(start0.x);
expect(start4.y).toBeCloseTo(start0.y);
});
test('rotatePoint [270,360]deg, 180-210-240-270', () => {
const r = 100;
const center = { x: 0, y: 0 };
const start0 = { x: 0, y: -r };
const deg30 = 30;
const radian = parseAngleToRadian(deg30);
// 270-300
const start1 = rotatePoint(center, start0, radian);
expect(start1.x).toBeCloseTo(r * Math.sin(radian));
expect(start1.y).toBeCloseTo(-r * Math.cos(radian));
// 300-330
const start2 = rotatePoint(center, start1, radian);
expect(start2.x).toBeCloseTo(r * Math.cos(radian));
expect(start2.y).toBeCloseTo(-r * Math.sin(radian));
// 330-360
const start3 = rotatePoint(center, start2, radian);
expect(start3.x).toBeCloseTo(r);
expect(start3.y).toBeCloseTo(0);
});
test('rotatePoint [270,360]deg, 300-315-330-315-300', () => {
const center = { x: 0, y: 0 };
const deg15 = 15;
const radian15 = parseAngleToRadian(deg15);
const radian30 = radian15 * 2;
const r = 100;
// 300-315
const start0 = { x: r * Math.sin(radian30), y: -r * Math.cos(radian30) };
const start1 = rotatePoint(center, start0, radian15);
expect(start1.x).toBeCloseTo(r * Math.cos(radian15 * 3));
expect(start1.y).toBeCloseTo(-r * Math.sin(radian15 * 3));
// 315-330
const start2 = rotatePoint(center, start1, radian15);
expect(start2.x).toBeCloseTo(r * Math.cos(radian30));
expect(start2.y).toBeCloseTo(-r * Math.sin(radian30));
// 330-315
const start3 = rotatePoint(center, start2, 0 - radian15);
expect(start3.x).toBeCloseTo(start1.x);
expect(start3.y).toBeCloseTo(start1.y);
// 315-300
const start4 = rotatePoint(center, start3, 0 - radian15);
expect(start4.x).toBeCloseTo(start0.x);
expect(start4.y).toBeCloseTo(start0.y);
});
});

View file

@ -21,7 +21,8 @@ export {
getElementRotateVertexes,
calcElementCenter,
calcElementCenterFromVertexes,
rotatePointInGroup
rotatePointInGroup,
limitAngle
} from './lib/rotate';
export { getSelectedElementUUIDs, validateElements, calcElementsContextSize, calcElementsViewInfo, getElemenetsAssetIds } from './lib/element';
export { checkRectIntersect } from './lib/rect';

View file

@ -53,10 +53,19 @@ export function calcElementSizeController(
const bottomCenter = getCenterFromTwoPoints(vertexes[2], vertexes[3]);
const leftCenter = getCenterFromTwoPoints(vertexes[3], vertexes[0]);
const topLeftCenter = vertexes[0];
const topRightCenter = vertexes[1];
const bottomRightCenter = vertexes[2];
const bottomLeftCenter = vertexes[3];
const topSize = createControllerElementSizeFromCenter(topCenter, { size: ctrlSize, angle: totalAngle });
const rightSize = createControllerElementSizeFromCenter(rightCenter, { size: ctrlSize, angle: totalAngle });
const bottomSize = createControllerElementSizeFromCenter(bottomCenter, { size: ctrlSize, angle: totalAngle });
const leftSize = createControllerElementSizeFromCenter(leftCenter, { size: ctrlSize, angle: totalAngle });
const topLeftSize = createControllerElementSizeFromCenter(topLeftCenter, { size: ctrlSize, angle: totalAngle });
const topRightSize = createControllerElementSizeFromCenter(topRightCenter, { size: ctrlSize, angle: totalAngle });
const bottomLeftSize = createControllerElementSizeFromCenter(bottomLeftCenter, { size: ctrlSize, angle: totalAngle });
const bottomRightSize = createControllerElementSizeFromCenter(bottomRightCenter, { size: ctrlSize, angle: totalAngle });
const sizeController: ElementSizeController = {
elementWrapper: vertexes,
@ -75,6 +84,22 @@ export function calcElementSizeController(
bottom: {
type: 'bottom',
vertexes: calcElementVertexes(bottomSize)
},
topLeft: {
type: 'top-left',
vertexes: calcElementVertexes(topLeftSize)
},
topRight: {
type: 'top-right',
vertexes: calcElementVertexes(topRightSize)
},
bottomLeft: {
type: 'bottom-left',
vertexes: calcElementVertexes(bottomLeftSize)
},
bottomRight: {
type: 'bottom-right',
vertexes: calcElementVertexes(bottomRightSize)
}
};
return sizeController;

View file

@ -173,8 +173,6 @@ export function calcElementsContextSize(
}
const ctxSize: ViewContextSize = {
contextX: area.x,
contextY: area.y,
contextWidth: area.w,
contextHeight: area.h
};
@ -198,42 +196,14 @@ export function calcElementsViewInfo(
}
): {
contextSize: ViewContextSize;
changeContextLeft: number;
changeContextRight: number;
changeContextTop: number;
changeContextBottom: number;
} {
const contextSize = calcElementsContextSize(elements, { viewWidth: prevViewSize.width, viewHeight: prevViewSize.height, extend: options?.extend });
if (options?.extend === true) {
contextSize.contextX = Math.min(0, contextSize.contextX, prevViewSize.contextX);
contextSize.contextY = Math.min(0, contextSize.contextY, prevViewSize.contextY);
contextSize.contextWidth = Math.max(contextSize.contextWidth, prevViewSize.contextWidth);
contextSize.contextHeight = Math.max(contextSize.contextHeight, prevViewSize.contextHeight);
}
let changeContextLeft = 0;
let changeContextRight = 0;
let changeContextTop = 0;
let changeContextBottom = 0;
if (contextSize.contextX !== prevViewSize.contextX) {
changeContextLeft = contextSize.contextX - prevViewSize.contextX;
} else if (contextSize.contextWidth !== prevViewSize.contextWidth) {
changeContextRight = contextSize.contextWidth - prevViewSize.contextWidth;
}
if (contextSize.contextY !== prevViewSize.contextY) {
changeContextTop = contextSize.contextY - prevViewSize.contextY;
} else if (contextSize.contextHeight !== prevViewSize.contextHeight) {
changeContextBottom = contextSize.contextHeight - prevViewSize.contextHeight;
}
return {
contextSize,
changeContextLeft,
changeContextRight,
changeContextTop,
changeContextBottom
contextSize
};
}

View file

@ -18,8 +18,6 @@ export function getViewSizeInfoFromSnapshot(snapshot: BoardViewerFrameSnapshot)
devicePixelRatio: activeStore.devicePixelRatio,
width: activeStore?.width,
height: activeStore?.height,
contextX: activeStore?.contextX,
contextY: activeStore?.contextY,
contextWidth: activeStore?.contextWidth,
contextHeight: activeStore?.contextHeight
};

View file

@ -48,14 +48,13 @@ export function viewScroll(opts: { moveX?: number; moveY?: number; viewScaleInfo
}
export function calcViewElementSize(size: ElementSize, opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): ElementSize {
const { viewScaleInfo, viewSizeInfo } = opts;
const { viewScaleInfo } = 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,
x: x * scale + offsetLeft,
y: y * scale + offsetTop,
w: w * scale,
h: h * scale,
angle
@ -64,14 +63,13 @@ export function calcViewElementSize(size: ElementSize, opts: { viewScaleInfo: Vi
}
export function calcViewPointSize(size: PointSize, opts: { viewScaleInfo: ViewScaleInfo; viewSizeInfo: ViewSizeInfo }): PointSize {
const { viewScaleInfo, viewSizeInfo } = opts;
const { viewScaleInfo } = opts;
const { x, y } = size;
const { contextX = 0, contextY = 0 } = viewSizeInfo;
const { scale, offsetTop, offsetLeft } = viewScaleInfo;
const newSize = {
x: x * scale + offsetLeft - contextX,
y: y * scale + offsetTop - contextY
x: x * scale + offsetLeft,
y: y * scale + offsetTop
};
return newSize;
}
@ -144,6 +142,9 @@ export function getViewPointAtElement(
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?.operations?.invisible === true) {
continue;
}
if (child) {
const elemSize = {
x: totalX + child.x,
@ -175,6 +176,9 @@ export function getViewPointAtElement(
for (let i = data.elements.length - 1; i >= 0; i--) {
const elem = data.elements[i];
if (elem?.operations?.invisible === true) {
continue;
}
if (isViewPointInElement(p, { context2d: ctx, element: elem, viewScaleInfo, viewSizeInfo })) {
result.index = i;
result.element = elem;