mirror of
https://github.com/idrawjs/idraw
synced 2026-05-23 17:48:23 +00:00
feat: rewrite rotate element func
This commit is contained in:
parent
5d3e84fbec
commit
4b9ab4a5b2
7 changed files with 179 additions and 150 deletions
|
|
@ -14,4 +14,5 @@
|
|||
- [x] Move elements' index
|
||||
- [] Rotate elements
|
||||
- [x] Transform elements's size
|
||||
- [] Undo action record
|
||||
- [] Undo action record
|
||||
- [] Controll elements by data
|
||||
|
|
@ -139,6 +139,8 @@ class Core {
|
|||
// console.log('handlePoint = ', point);
|
||||
|
||||
const [uuid, direction] = this[_helper].isPointInElementWrapperDot(point);
|
||||
console.log('uuid, direction =', uuid, direction);
|
||||
|
||||
if (uuid && direction) {
|
||||
this[_mode] = Mode.SELECT_ELEMENT_WRAPPER_DOT;
|
||||
this[_selectedDotDirection] = direction;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
// TypePoint,
|
||||
} from '@idraw/types';
|
||||
import util from './../util';
|
||||
import { translateRotateAngle, translateRotateCenter } from './calculate';
|
||||
import { rotateContext, rotateElement } from './transform';
|
||||
|
||||
const { isColorStr } = util.color;
|
||||
|
||||
|
|
@ -36,25 +36,10 @@ export function drawContext(ctx: TypeContext, data: TypeData, config: TypeHelper
|
|||
|
||||
function drawRect<T extends keyof TypeElemDesc>(ctx: TypeContext, ele: TypeElement<T>) {
|
||||
const desc = ele.desc as TypeElemDesc['rect'];
|
||||
|
||||
const angle = translateRotateAngle(ele.angle);
|
||||
const center = translateRotateCenter(ele);
|
||||
|
||||
if (angle > 0 || angle < 0) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(angle);
|
||||
ctx.translate(0 - center.x, 0 - center.y);
|
||||
}
|
||||
|
||||
ctx.setFillStyle(desc.color);
|
||||
ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
|
||||
|
||||
// reset rotate
|
||||
if (angle > 0 || angle < 0) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(0 - angle);
|
||||
ctx.translate(0 - center.x, 0 - center.y);
|
||||
}
|
||||
rotateElement(ctx, ele, () => {
|
||||
ctx.setFillStyle(desc.color);
|
||||
ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
|
||||
});
|
||||
}
|
||||
|
||||
function drawBgColor(ctx: TypeContext, color: string) {
|
||||
|
|
@ -69,41 +54,47 @@ function drawElementWrapper(ctx: TypeContext, config: TypeHelperConfig) {
|
|||
}
|
||||
const wrapper = config.selectedElementWrapper;
|
||||
|
||||
if (typeof wrapper.angle === 'number' && wrapper.translate) {
|
||||
ctx.translate(wrapper.translate.x, wrapper.translate.y);
|
||||
ctx.rotate(wrapper.angle);
|
||||
ctx.translate(0 - wrapper.translate.x, 0 - wrapper.translate.y);
|
||||
}
|
||||
|
||||
// draw wrapper's box
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash(wrapper.lineDash);
|
||||
ctx.setLineWidth(wrapper.lineWidth);
|
||||
ctx.setStrokeStyle(wrapper.color);
|
||||
ctx.moveTo(wrapper.topLeft.x, wrapper.topLeft.y);
|
||||
ctx.lineTo(wrapper.topRight.x, wrapper.topRight.y);
|
||||
ctx.lineTo(wrapper.bottomRight.x, wrapper.bottomRight.y);
|
||||
ctx.lineTo(wrapper.bottomLeft.x, wrapper.bottomLeft.y);
|
||||
ctx.lineTo(wrapper.topLeft.x, wrapper.topLeft.y - wrapper.lineWidth / 2);
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
|
||||
// draw wrapper's dots
|
||||
ctx.setFillStyle(wrapper.color);
|
||||
[
|
||||
wrapper.topLeft, wrapper.top, wrapper.topRight, wrapper.right,
|
||||
wrapper.bottomRight, wrapper.bottom, wrapper.bottomLeft, wrapper.left,
|
||||
].forEach((dot) => {
|
||||
rotateContext(ctx, wrapper.translate, wrapper.angle || 0, () => {
|
||||
// draw wrapper's box
|
||||
ctx.beginPath();
|
||||
ctx.arc(dot.x, dot.y, wrapper.dotSize, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.setLineDash(wrapper.lineDash);
|
||||
ctx.setLineWidth(wrapper.lineWidth);
|
||||
ctx.setStrokeStyle(wrapper.color);
|
||||
ctx.moveTo(wrapper.dots.topLeft.x, wrapper.dots.topLeft.y);
|
||||
ctx.lineTo(wrapper.dots.topRight.x, wrapper.dots.topRight.y);
|
||||
ctx.lineTo(wrapper.dots.bottomRight.x, wrapper.dots.bottomRight.y);
|
||||
ctx.lineTo(wrapper.dots.bottomLeft.x, wrapper.dots.bottomLeft.y);
|
||||
ctx.lineTo(wrapper.dots.topLeft.x, wrapper.dots.topLeft.y - wrapper.lineWidth / 2);
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
});
|
||||
|
||||
// reset rotate
|
||||
if (typeof wrapper.angle === 'number' && wrapper.translate) {
|
||||
ctx.translate(wrapper.translate.x, wrapper.translate.y);
|
||||
ctx.rotate(0 - wrapper.angle);
|
||||
ctx.translate(0 - wrapper.translate.x, 0 - wrapper.translate.y);
|
||||
}
|
||||
|
||||
// draw wrapper's rotate line
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(wrapper.dots.top.x, wrapper.dots.top.y);
|
||||
ctx.lineTo(wrapper.dots.rotate.x, wrapper.dots.rotate.y + wrapper.dotSize);
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
|
||||
// draw wrapper's rotate
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash([]);
|
||||
ctx.setLineWidth(wrapper.dotSize / 2);
|
||||
ctx.arc(wrapper.dots.rotate.x, wrapper.dots.rotate.y, wrapper.dotSize * 0.8, Math.PI / 6, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
|
||||
// draw wrapper's dots
|
||||
ctx.setFillStyle(wrapper.color);
|
||||
[
|
||||
wrapper.dots.topLeft, wrapper.dots.top, wrapper.dots.topRight, wrapper.dots.right,
|
||||
wrapper.dots.bottomRight, wrapper.dots.bottom, wrapper.dots.bottomLeft, wrapper.dots.left,
|
||||
].forEach((dot) => {
|
||||
ctx.beginPath();
|
||||
ctx.arc(dot.x, dot.y, wrapper.dotSize, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
// TypeElemDesc,
|
||||
} from '@idraw/types';
|
||||
import util from './../util';
|
||||
import { translateRotateAngle, translateRotateCenter } from './calculate';
|
||||
import { rotateElement } from './transform';
|
||||
|
||||
const { createUUID } = util.uuid;
|
||||
|
||||
|
|
@ -33,35 +33,22 @@ export class Element {
|
|||
let uuid = null
|
||||
for (let i = data.elements.length - 1; i >= 0; i--) {
|
||||
const ele = data.elements[i];
|
||||
const angle = translateRotateAngle(ele.angle);
|
||||
const center = translateRotateCenter(ele);
|
||||
|
||||
if (angle > 0 || angle < 0) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(angle);
|
||||
ctx.translate(0 - center.x, 0 - center.y);
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(ele.x, ele.y);
|
||||
ctx.lineTo(ele.x + ele.w, ele.y);
|
||||
ctx.lineTo(ele.x + ele.w, ele.y + ele.h);
|
||||
ctx.lineTo(ele.x, ele.y + ele.h);
|
||||
ctx.lineTo(ele.x, ele.y);
|
||||
rotateElement(ctx, ele, () => {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(ele.x, ele.y);
|
||||
ctx.lineTo(ele.x + ele.w, ele.y);
|
||||
ctx.lineTo(ele.x + ele.w, ele.y + ele.h);
|
||||
ctx.lineTo(ele.x, ele.y + ele.h);
|
||||
ctx.lineTo(ele.x, ele.y);
|
||||
|
||||
ctx.rect(ele.x, ele.y, ele.w, ele.h);
|
||||
ctx.closePath();
|
||||
if (ctx.isPointInPath(p.x, p.y)) {
|
||||
idx = i;
|
||||
uuid = ele.uuid;
|
||||
}
|
||||
|
||||
// reset rotate
|
||||
if (angle > 0 || angle < 0) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(0 - angle);
|
||||
ctx.translate(0 - center.x, 0 - center.y);
|
||||
}
|
||||
ctx.rect(ele.x, ele.y, ele.w, ele.h);
|
||||
ctx.closePath();
|
||||
if (ctx.isPointInPath(p.x, p.y)) {
|
||||
idx = i;
|
||||
uuid = ele.uuid;
|
||||
}
|
||||
});
|
||||
|
||||
if (idx >= 0) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
TypeConfigStrict,
|
||||
} from '@idraw/types';
|
||||
import { translateRotateAngle, translateRotateCenter } from './calculate';
|
||||
import { rotateContext } from './transform';
|
||||
|
||||
export class Helper implements TypeHelper {
|
||||
|
||||
|
|
@ -55,37 +56,29 @@ export class Helper implements TypeHelper {
|
|||
}
|
||||
const wrapper = this._helperConfig.selectedElementWrapper;
|
||||
const dots = [
|
||||
wrapper.topLeft, wrapper.top, wrapper.topRight, wrapper.right,
|
||||
wrapper.bottomRight, wrapper.bottom, wrapper.bottomLeft, wrapper.left,
|
||||
wrapper.dots.topLeft, wrapper.dots.top, wrapper.dots.topRight, wrapper.dots.right,
|
||||
wrapper.dots.bottomRight, wrapper.dots.bottom, wrapper.dots.bottomLeft, wrapper.dots.left,
|
||||
wrapper.dots.rotate,
|
||||
];
|
||||
const directionNames: TypeHelperWrapperDotDirection[] = [
|
||||
'top-left', 'top', 'top-right', 'right',
|
||||
'bottom-right', 'bottom', 'bottom-left', 'left',
|
||||
'bottom-right', 'bottom', 'bottom-left', 'left',
|
||||
'rotate',
|
||||
];
|
||||
|
||||
if (typeof wrapper.angle === 'number' && wrapper.translate) {
|
||||
ctx.translate(wrapper.translate.x, wrapper.translate.y);
|
||||
ctx.rotate(wrapper.angle);
|
||||
ctx.translate(0 - wrapper.translate.x, 0 - wrapper.translate.y);
|
||||
}
|
||||
for (let i = 0; i < dots.length; i ++) {
|
||||
const dot = dots[i];
|
||||
ctx.beginPath();
|
||||
ctx.arc(dot.x, dot.y, wrapper.dotSize, 0, Math.PI * 2);
|
||||
ctx.closePath();
|
||||
if (ctx.isPointInPath(p.x, p.y)) {
|
||||
direction = directionNames[i];
|
||||
rotateContext(ctx, wrapper.translate, wrapper.angle || 0, () => {
|
||||
for (let i = 0; i < dots.length; i ++) {
|
||||
const dot = dots[i];
|
||||
ctx.beginPath();
|
||||
ctx.arc(dot.x, dot.y, wrapper.dotSize, 0, Math.PI * 2);
|
||||
ctx.closePath();
|
||||
if (ctx.isPointInPath(p.x, p.y)) {
|
||||
direction = directionNames[i];
|
||||
}
|
||||
if (direction) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (direction) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// reset rotate
|
||||
if (typeof wrapper.angle === 'number' && wrapper.translate) {
|
||||
ctx.translate(wrapper.translate.x, wrapper.translate.y);
|
||||
ctx.rotate(0 - wrapper.angle);
|
||||
ctx.translate(0 - wrapper.translate.x, 0 - wrapper.translate.y);
|
||||
}
|
||||
});
|
||||
return [uuid, direction];
|
||||
}
|
||||
|
||||
|
|
@ -108,45 +101,52 @@ export class Helper implements TypeHelper {
|
|||
const dotSize = this._coreConfig.elementWrapper.dotSize / scale;
|
||||
const lineWidth = this._coreConfig.elementWrapper.lineWidth / scale;
|
||||
const lineDash = this._coreConfig.elementWrapper.lineDash.map(n => (n / scale));
|
||||
const rotateLimit = 12;
|
||||
|
||||
const wrapper: TypeHelperConfig['selectedElementWrapper'] = {
|
||||
uuid,
|
||||
dotSize: dotSize,
|
||||
dots: {
|
||||
topLeft: {
|
||||
x: elem.x - dotSize,
|
||||
y: elem.y - dotSize,
|
||||
},
|
||||
top: {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y - dotSize,
|
||||
},
|
||||
topRight: {
|
||||
x: elem.x + elem.w + dotSize,
|
||||
y: elem.y - dotSize,
|
||||
},
|
||||
right: {
|
||||
x: elem.x + elem.w + dotSize,
|
||||
y: elem.y + elem.h / 2,
|
||||
},
|
||||
bottomRight: {
|
||||
x: elem.x + elem.w + dotSize,
|
||||
y: elem.y + elem.h + dotSize,
|
||||
},
|
||||
bottom: {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y + elem.h + dotSize,
|
||||
},
|
||||
bottomLeft: {
|
||||
x: elem.x - dotSize,
|
||||
y: elem.y + elem.h + dotSize,
|
||||
},
|
||||
left: {
|
||||
x: elem.x - dotSize,
|
||||
y: elem.y + elem.h / 2,
|
||||
},
|
||||
rotate: {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y - dotSize - (dotSize * 2 + rotateLimit),
|
||||
}
|
||||
},
|
||||
lineWidth: lineWidth,
|
||||
lineDash: lineDash,
|
||||
color: '#2ab6f1',
|
||||
topLeft: {
|
||||
x: elem.x - dotSize,
|
||||
y: elem.y - dotSize,
|
||||
},
|
||||
top: {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y - dotSize,
|
||||
},
|
||||
topRight: {
|
||||
x: elem.x + elem.w + dotSize,
|
||||
y: elem.y - dotSize,
|
||||
},
|
||||
right: {
|
||||
x: elem.x + elem.w + dotSize,
|
||||
y: elem.y + elem.h / 2,
|
||||
},
|
||||
bottomRight: {
|
||||
x: elem.x + elem.w + dotSize,
|
||||
y: elem.y + elem.h + dotSize,
|
||||
},
|
||||
bottom: {
|
||||
x: elem.x + elem.w / 2,
|
||||
y: elem.y + elem.h + dotSize,
|
||||
},
|
||||
bottomLeft: {
|
||||
x: elem.x - dotSize,
|
||||
y: elem.y + elem.h + dotSize,
|
||||
},
|
||||
left: {
|
||||
x: elem.x - dotSize,
|
||||
y: elem.y + elem.h / 2,
|
||||
},
|
||||
};
|
||||
|
||||
if (typeof elem.angle === 'number' && (elem.angle > 0 || elem.angle < 0)) {
|
||||
|
|
|
|||
44
packages/core/src/lib/transform.ts
Normal file
44
packages/core/src/lib/transform.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import {
|
||||
TypeContext,
|
||||
TypePoint,
|
||||
TypeElement,
|
||||
TypeElemDesc,
|
||||
} from '@idraw/types';
|
||||
import { translateRotateCenter, translateRotateAngle } from './calculate';
|
||||
|
||||
function rotateElement(
|
||||
ctx: TypeContext,
|
||||
elem: TypeElement<keyof TypeElemDesc>,
|
||||
callback: (ctx: TypeContext) => void
|
||||
) {
|
||||
const center: TypePoint = translateRotateCenter(elem);
|
||||
const angle = translateRotateAngle(elem.angle);
|
||||
return rotateContext(ctx, center, angle || 0, callback);
|
||||
}
|
||||
|
||||
|
||||
function rotateContext(
|
||||
ctx: TypeContext,
|
||||
center: TypePoint | undefined,
|
||||
angle: number,
|
||||
callback: (ctx: TypeContext) => void
|
||||
): void {
|
||||
if (center && (angle > 0 || angle < 0)) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(angle);
|
||||
ctx.translate(- center.x, - center.y);
|
||||
}
|
||||
|
||||
callback(ctx);
|
||||
|
||||
if (center && (angle > 0 || angle < 0)) {
|
||||
ctx.translate(center.x, center.y);
|
||||
ctx.rotate(- angle);
|
||||
ctx.translate(- center.x, - center.y);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
rotateContext,
|
||||
rotateElement,
|
||||
}
|
||||
|
|
@ -8,17 +8,20 @@ type TypeHelperConfig = {
|
|||
selectedElementWrapper?: {
|
||||
uuid: string;
|
||||
dotSize: number;
|
||||
dots: {
|
||||
topLeft: TypePoint,
|
||||
top: TypePoint,
|
||||
topRight: TypePoint,
|
||||
right: TypePoint,
|
||||
bottomRight: TypePoint,
|
||||
bottom: TypePoint,
|
||||
bottomLeft: TypePoint,
|
||||
left: TypePoint,
|
||||
rotate: TypePoint,
|
||||
}
|
||||
lineDash: number[];
|
||||
lineWidth: number;
|
||||
color: string;
|
||||
topLeft: TypePoint,
|
||||
top: TypePoint,
|
||||
topRight: TypePoint,
|
||||
right: TypePoint,
|
||||
bottomRight: TypePoint,
|
||||
bottom: TypePoint,
|
||||
bottomLeft: TypePoint,
|
||||
left: TypePoint,
|
||||
angle?: number;
|
||||
translate?: TypePoint;
|
||||
}
|
||||
|
|
@ -40,7 +43,8 @@ interface TypeHelper {
|
|||
|
||||
type TypeHelperWrapperDotDirection
|
||||
= 'top-left' | 'top' | 'top-right' | 'right'
|
||||
| 'bottom-right' | 'bottom' | 'bottom-left' | 'left';
|
||||
| 'bottom-right' | 'bottom' | 'bottom-left' | 'left'
|
||||
| 'rotate';
|
||||
|
||||
export {
|
||||
TypeHelper,
|
||||
|
|
|
|||
Loading…
Reference in a new issue