mirror of
https://github.com/idrawjs/idraw
synced 2026-05-23 01:28:31 +00:00
feat: add method for moving elements by point and refactor rotatable operation
This commit is contained in:
parent
ac6d484e5f
commit
8512fdf4dc
11 changed files with 104 additions and 70 deletions
|
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ export {
|
|||
calcElementOriginRectInfo,
|
||||
calcElementViewRectInfoMap,
|
||||
sortElementsViewVisiableInfoMap,
|
||||
flatElementList
|
||||
flatElementList,
|
||||
calcPointMoveElementInGroup
|
||||
} from '@idraw/util';
|
||||
export { iDraw } from './idraw';
|
||||
export { eventKeys } from './event';
|
||||
|
|
|
|||
|
|
@ -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'>;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ export function calcElementSizeController(
|
|||
const rotateVertexes = calcElementVertexes(rotateSize);
|
||||
|
||||
const sizeController: ElementSizeController = {
|
||||
originalElementCenter: calcElementCenter(elemSize),
|
||||
originalElementSize: { ...elemSize },
|
||||
elementWrapper: vertexes,
|
||||
left: {
|
||||
type: 'left',
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
30
packages/util/src/lib/point-move-element.ts
Normal file
30
packages/util/src/lib/point-move-element.ts
Normal 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
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue