Merge pull request #346 from idrawjs/dev-v0.4

feat: add method for moving elements by point and refactor rotatable
This commit is contained in:
Deepsea 2024-08-17 21:43:55 +08:00 committed by GitHub
commit 5b263d9580
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 113 additions and 80 deletions

View file

@ -30,13 +30,12 @@ jobs:
- run: pnpm i
- run: npm run beforetest
- run: npm run cover
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
files: /home/runner/work/idraw/idraw/reports/clover.xml # optional
flags: unittests # optional
name: codecov-umbrella # optional
fail_ci_if_error: true # optional (default = false)
verbose: true # optional (default = false)
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v2
# with:
# token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
# files: /home/runner/work/idraw/idraw/reports/clover.xml # optional
# flags: unittests # optional
# name: codecov-umbrella # optional
# fail_ci_if_error: true # optional (default = false)
# verbose: true # optional (default = false)

View file

@ -146,18 +146,20 @@ export const MiddlewareInfo: BoardMiddleware<
});
if (showAngleInfo) {
drawAngleInfoText(overlayContext, {
point: {
x: rectInfo.top.x + infoFontSize + 4,
y: rectInfo.top.y - infoFontSize * 2 - 18
},
rotateCenter: rectInfo.center,
angle: totalAngle,
text: angleText,
fontSize: infoFontSize,
lineHeight: infoLineHeight,
style
});
if (elem.operations?.rotatable !== false) {
drawAngleInfoText(overlayContext, {
point: {
x: rectInfo.top.x + infoFontSize + 4,
y: rectInfo.top.y - infoFontSize * 2 - 18
},
rotateCenter: rectInfo.center,
angle: totalAngle,
text: angleText,
fontSize: infoFontSize,
lineHeight: infoLineHeight,
style
});
}
}
}
}

View file

@ -91,8 +91,9 @@ export function drawSelectedElementControllersVertexes(
hideControllers,
style,
rotateControllerPattern,
viewSizeInfo
// calculator, element, viewScaleInfo, viewSizeInfo
viewSizeInfo,
element
// calculator, viewScaleInfo, viewSizeInfo
} = opts;
const { devicePixelRatio = 1 } = viewSizeInfo;
@ -113,20 +114,21 @@ export function drawSelectedElementControllersVertexes(
drawVertexes(ctx, calcViewVertexes(bottomLeft.vertexes, opts), ctrlOpts);
drawVertexes(ctx, calcViewVertexes(bottomRight.vertexes, opts), ctrlOpts);
// TODO
drawCircleController(ctx, calcViewPointSize(rotate.center, opts), { ...ctrlOpts, size: rotate.size, borderWidth: 0 });
const rotateCenter = calcViewPointSize(rotate.center, opts);
ctx.drawImage(
rotateControllerPattern.canvas,
0,
0,
rotateControllerPattern.canvas.width / devicePixelRatio,
rotateControllerPattern.canvas.height / devicePixelRatio,
rotateCenter.x - rotate.size / 2,
rotateCenter.y - rotate.size / 2,
rotate.size,
rotate.size
);
if (element?.operations?.rotatable !== false) {
drawCircleController(ctx, calcViewPointSize(rotate.center, opts), { ...ctrlOpts, size: rotate.size, borderWidth: 0 });
const rotateCenter = calcViewPointSize(rotate.center, opts);
ctx.drawImage(
rotateControllerPattern.canvas,
0,
0,
rotateControllerPattern.canvas.width / devicePixelRatio,
rotateControllerPattern.canvas.height / devicePixelRatio,
rotateCenter.x - rotate.size / 2,
rotateCenter.y - rotate.size / 2,
rotate.size,
rotate.size
);
}
}
// drawAuxiliaryExperimentBox(ctx, {

View file

@ -12,7 +12,9 @@ import {
getElementPositionFromList,
getElementPositionMapFromList,
deepResizeGroupElement,
getElementSize
getElementSize,
calcPointMoveElementInGroup,
isSameElementSize
} from '@idraw/util';
import type {
Data,
@ -52,8 +54,7 @@ import {
getSelectedListArea,
calcSelectedElementsArea,
isElementInGroup,
isPointInViewActiveGroup,
calcMoveInGroup
isPointInViewActiveGroup
} from './util';
import {
keyActionType,
@ -513,7 +514,7 @@ export const MiddlewareSelector: BoardMiddleware<
eventHub.trigger(MIDDLEWARE_INTERNAL_EVENT_SHOW_INFO_ANGLE, { show: false });
if (data && elems?.length === 1 && moveOriginalStartElementSize && originalStart && end && elems[0]?.operations?.locked !== true) {
const { moveX, moveY } = calcMoveInGroup(originalStart, end, groupQueue);
const { moveX, moveY } = calcPointMoveElementInGroup(originalStart, end, groupQueue);
let totalMoveX = calculator.toGridNum(moveX / scale);
let totalMoveY = calculator.toGridNum(moveY / scale);
@ -871,7 +872,19 @@ export const MiddlewareSelector: BoardMiddleware<
const drawBaseOpts = { calculator, viewScaleInfo, viewSizeInfo, style };
const selectedElementController = sharedStore[keySelectedElementController];
let selectedElementController = sharedStore[keySelectedElementController];
if (selectedElementController && selectedElements.length === 1 && elem) {
if (!isSameElementSize(elem, selectedElementController.originalElementSize)) {
selectedElementController = calcElementSizeController(elem, {
groupQueue: groupQueue || [],
controllerSize,
viewScaleInfo,
rotateControllerPosition,
rotateControllerSize
});
sharer.setSharedStorage(keySelectedElementController, selectedElementController);
}
}
const isHoverLocked: boolean = !!hoverElement?.operations?.locked;

View file

@ -5,7 +5,6 @@ import {
calcElementQueueVertexesQueueInGroup,
calcViewPointSize,
calcViewElementSize,
rotatePointInGroup,
rotatePoint,
parseAngleToRadian,
parseRadianToAngle,
@ -106,7 +105,10 @@ export function getPointTarget(
// resize
if (selectedElementController) {
const { left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, rotate } = selectedElementController;
const ctrls = [left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight, rotate];
const ctrls = [left, right, top, bottom, topLeft, topRight, bottomLeft, bottomRight];
if (selectedElements?.length === 1 && selectedElements?.[0]?.operations?.rotatable !== false) {
ctrls.push(rotate);
}
for (let i = 0; i < ctrls.length; i++) {
const ctrl = ctrls[i];
if (isPointInViewActiveVertexes(p, { ctx, vertexes: ctrl.vertexes, viewSizeInfo, viewScaleInfo })) {
@ -968,31 +970,3 @@ export function isElementInGroup(elem: Element<ElementType>, group: Element<'gro
}
return false;
}
export function calcMoveInGroup(start: PointSize, end: PointSize, groupQueue: Element<'group'>[]): { moveX: number; moveY: number } {
let moveX = end.x - start.x;
let moveY = end.y - start.y;
const pointGroupQueue: Element<'group'>[] = [];
groupQueue.forEach((group) => {
const { x, y, w, h, angle = 0 } = group;
pointGroupQueue.push({
x,
y,
w,
h,
angle: 0 - angle
} as Element<'group'>);
});
if (groupQueue?.length > 0) {
const startInGroup = rotatePointInGroup(start, pointGroupQueue);
const endInGroup = rotatePointInGroup(end, pointGroupQueue);
moveX = endInGroup.x - startInGroup.x;
moveY = endInGroup.y - startInGroup.y;
}
return {
moveX,
moveY
};
}

View file

@ -113,7 +113,8 @@ export {
calcElementOriginRectInfo,
calcElementViewRectInfoMap,
sortElementsViewVisiableInfoMap,
flatElementList
flatElementList,
calcPointMoveElementInGroup
} from '@idraw/util';
export { iDraw } from './idraw';
export { eventKeys } from './event';

View file

@ -1,5 +1,6 @@
import { ViewRectVertexes } from './view';
import { PointSize } from './point';
import { ElementSize } from './element';
export type ElementSizeControllerType =
| 'left'
@ -24,6 +25,8 @@ export interface ElementSizeControllerItem {
}
export interface ElementSizeController {
originalElementCenter: PointSize;
originalElementSize: ElementSize;
elementWrapper: ViewRectVertexes;
top: ElementSizeControllerItem;
bottom: ElementSizeControllerItem;
@ -40,4 +43,4 @@ export interface ElementSizeController {
rotate: ElementSizeControllerItem;
}
export type LayoutSizeController = Omit<ElementSizeController, 'rotate' | 'elementWrapper'>;
export type LayoutSizeController = Omit<ElementSizeController, 'rotate' | 'elementWrapper' | 'originalElementCenter' | 'originalElementSize'>;

View file

@ -172,11 +172,10 @@ export type ElementType = keyof ElementDetailMap;
export interface ElementOperations {
locked?: boolean;
invisible?: boolean;
disableScale?: boolean;
disableRotate?: boolean;
rotatable?: boolean;
limitRatio?: boolean;
lastModified?: number;
deepResize?: boolean;
lastModified?: number;
}
export interface ElementGlobalDetail {

View file

@ -44,7 +44,8 @@ export {
isResourceElement,
getElementPositionFromList,
getElementPositionMapFromList,
calcElementListSize
calcElementListSize,
isSameElementSize
} from './lib/element';
export { checkRectIntersect } from './lib/rect';
export {
@ -91,3 +92,4 @@ export { modifyElement, getModifiedElement } from './lib/modify';
export { enhanceFontFamliy } from './lib/text';
export { flatElementList } from './lib/flat';
export { groupElementsByPosition, ungroupElementsByPosition } from './lib/group';
export { calcPointMoveElementInGroup } from './lib/point-move-element';

View file

@ -112,6 +112,8 @@ export function calcElementSizeController(
const rotateVertexes = calcElementVertexes(rotateSize);
const sizeController: ElementSizeController = {
originalElementCenter: calcElementCenter(elemSize),
originalElementSize: { ...elemSize },
elementWrapper: vertexes,
left: {
type: 'left',

View file

@ -11,7 +11,7 @@ import type {
LoadElementType,
ElementPosition
} from '@idraw/types';
import { rotateElementVertexes } from './rotate';
import { limitAngle, rotateElementVertexes } from './rotate';
import { isAssetId, createAssetId } from './uuid';
function getGroupUUIDs(elements: Array<Element<ElementType>>, index: string): string[] {
@ -504,3 +504,9 @@ export function getElementPositionMapFromList(
_loop(elements);
return positionMap;
}
export function isSameElementSize(elem1: ElementSize, elem2: ElementSize) {
return (
elem1.x === elem2.x && elem1.y === elem2.y && elem1.h === elem2.h && elem1.w === elem2.w && limitAngle(elem1.angle || 0) === limitAngle(elem2.angle || 0)
);
}

View file

@ -0,0 +1,30 @@
import type { PointSize, Element } from '@idraw/types';
import { rotatePointInGroup } from './rotate';
export function calcPointMoveElementInGroup(start: PointSize, end: PointSize, groupQueue: Element<'group'>[]): { moveX: number; moveY: number } {
let moveX = end.x - start.x;
let moveY = end.y - start.y;
const pointGroupQueue: Element<'group'>[] = [];
groupQueue.forEach((group) => {
const { x, y, w, h, angle = 0 } = group;
pointGroupQueue.push({
x,
y,
w,
h,
angle: 0 - angle
} as Element<'group'>);
});
if (groupQueue?.length > 0) {
const startInGroup = rotatePointInGroup(start, pointGroupQueue);
const endInGroup = rotatePointInGroup(end, pointGroupQueue);
moveX = endInGroup.x - startInGroup.x;
moveY = endInGroup.y - startInGroup.y;
}
return {
moveX,
moveY
};
}