From 5e5b4ffc92a6260302c3dded970190b7b75174ab Mon Sep 17 00:00:00 2001 From: chenshenhai Date: Sat, 16 Sep 2023 17:25:39 +0800 Subject: [PATCH] refactor: refactor selector middleware --- packages/board/src/lib/sharer.ts | 6 - packages/board/src/lib/viewer.ts | 5 +- packages/core/src/index.ts | 2 - .../core/src/middleware/scroller/index.ts | 16 +- packages/core/src/middleware/scroller/util.ts | 4 +- .../src/middleware/selector/draw-wrapper.ts | 6 +- .../core/src/middleware/selector/index.ts | 43 +- .../core/src/middleware/selector/types.ts | 10 +- packages/core/src/middleware/selector/util.ts | 676 ++++++++++++++---- packages/renderer/src/index.ts | 4 +- packages/types/src/lib/controller.ts | 10 +- packages/types/src/lib/view.ts | 2 - packages/util/__tests__/lib/rotate.test.ts | 214 ++++++ packages/util/src/index.ts | 3 +- packages/util/src/lib/controller.ts | 25 + packages/util/src/lib/element.ts | 32 +- packages/util/src/lib/middleware.ts | 2 - packages/util/src/lib/view-calc.ts | 20 +- 18 files changed, 859 insertions(+), 221 deletions(-) create mode 100644 packages/util/__tests__/lib/rotate.test.ts diff --git a/packages/board/src/lib/sharer.ts b/packages/board/src/lib/sharer.ts index a51b2ea..07d2f40 100644 --- a/packages/board/src/lib/sharer.ts +++ b/packages/board/src/lib/sharer.ts @@ -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 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 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') }; diff --git a/packages/board/src/lib/viewer.ts b/packages/board/src/lib/viewer.ts index 6824905..34486f2 100644 --- a/packages/board/src/lib/viewer.ts +++ b/packages/board/src/lib/viewer.ts @@ -43,8 +43,7 @@ export class Viewer extends EventEmitter 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 implements BoardVi viewSizeInfo: { width, height, - contextX, - contextY, contextHeight, contextWidth, devicePixelRatio diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index bd3e200..ad12719 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -29,8 +29,6 @@ export class Core { width, height, devicePixelRatio, - contextX: 0, - contextY: 0, contextWidth: width, contextHeight: height }); diff --git a/packages/core/src/middleware/scroller/index.ts b/packages/core/src/middleware/scroller/index.ts index 90756ac..b2617a8 100644 --- a/packages/core/src/middleware/scroller/index.ts +++ b/packages/core/src/middleware/scroller/index.ts @@ -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 }); diff --git a/packages/core/src/middleware/scroller/util.ts b/packages/core/src/middleware/scroller/util.ts index 3c3a633..018510c 100644 --- a/packages/core/src/middleware/scroller/util.ts +++ b/packages/core/src/middleware/scroller/util.ts @@ -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; diff --git a/packages/core/src/middleware/selector/draw-wrapper.ts b/packages/core/src/middleware/selector/draw-wrapper.ts index 90d5458..f6d77e7 100644 --- a/packages/core/src/middleware/selector/draw-wrapper.ts +++ b/packages/core/src/middleware/selector/draw-wrapper.ts @@ -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[], opts?: Omit) { diff --git a/packages/core/src/middleware/selector/index.ts b/packages/core/src/middleware/selector/index.ts index 4af8849..e7cc697 100644 --- a/packages/core/src/middleware/selector/index.ts +++ b/packages/core/src/middleware/selector/index.ts @@ -321,8 +321,7 @@ export const MiddlewareSelector: BoardMiddleware = (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 = (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 = (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 = (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(); + // } } }; }; diff --git a/packages/core/src/middleware/selector/types.ts b/packages/core/src/middleware/selector/types.ts index d7407fe..f7e0d93 100644 --- a/packages/core/src/middleware/selector/types.ts +++ b/packages/core/src/middleware/selector/types.ts @@ -52,7 +52,15 @@ export type ControllerStyle = ElementSize & { export type SelectedElementSizeController = Record; -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'; diff --git a/packages/core/src/middleware/selector/util.ts b/packages/core/src/middleware/selector/util.ts index 0dee19c..4339da3 100644 --- a/packages/core/src/middleware/selector/util.ts +++ b/packages/core/src/middleware/selector/util.ts @@ -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 }; } diff --git a/packages/renderer/src/index.ts b/packages/renderer/src/index.ts index a120d2f..017be84 100644 --- a/packages/renderer/src/index.ts +++ b/packages/renderer/src/index.ts @@ -57,7 +57,7 @@ export class Renderer extends EventEmitter 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 implements BoardRen viewSizeInfo: { width, height, - contextX, - contextY, contextHeight, contextWidth, devicePixelRatio diff --git a/packages/types/src/lib/controller.ts b/packages/types/src/lib/controller.ts index 351a91c..76ac55d 100644 --- a/packages/types/src/lib/controller.ts +++ b/packages/types/src/lib/controller.ts @@ -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; } diff --git a/packages/types/src/lib/view.ts b/packages/types/src/lib/view.ts index 1c9767c..3817ce5 100644 --- a/packages/types/src/lib/view.ts +++ b/packages/types/src/lib/view.ts @@ -12,8 +12,6 @@ export interface ViewScaleInfo { } export interface ViewContextSize { - contextX: number; - contextY: number; contextWidth: number; contextHeight: number; } diff --git a/packages/util/__tests__/lib/rotate.test.ts b/packages/util/__tests__/lib/rotate.test.ts new file mode 100644 index 0000000..d25a5e3 --- /dev/null +++ b/packages/util/__tests__/lib/rotate.test.ts @@ -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); + }); +}); diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index 30b5ea7..d7b5f4b 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -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'; diff --git a/packages/util/src/lib/controller.ts b/packages/util/src/lib/controller.ts index 70f96ca..3c68c4b 100644 --- a/packages/util/src/lib/controller.ts +++ b/packages/util/src/lib/controller.ts @@ -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; diff --git a/packages/util/src/lib/element.ts b/packages/util/src/lib/element.ts index c968cab..7445daa 100644 --- a/packages/util/src/lib/element.ts +++ b/packages/util/src/lib/element.ts @@ -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 }; } diff --git a/packages/util/src/lib/middleware.ts b/packages/util/src/lib/middleware.ts index fc3cf39..fceca71 100644 --- a/packages/util/src/lib/middleware.ts +++ b/packages/util/src/lib/middleware.ts @@ -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 }; diff --git a/packages/util/src/lib/view-calc.ts b/packages/util/src/lib/view-calc.ts index 64a0917..7560384 100644 --- a/packages/util/src/lib/view-calc.ts +++ b/packages/util/src/lib/view-calc.ts @@ -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;