Skip to content

Commit

Permalink
feat: Support rotate and resize together #467
Browse files Browse the repository at this point in the history
  • Loading branch information
daybrush committed Jul 24, 2022
1 parent 68b4a92 commit 24482a6
Show file tree
Hide file tree
Showing 19 changed files with 466 additions and 146 deletions.
17 changes: 14 additions & 3 deletions packages/react-moveable/src/react-moveable/MoveableManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from "./types";
import { triggerAble, getTargetAbleGesto, getAbleGesto } from "./gesto/getAbleGesto";
import { plus } from "@scena/matrix";
import { cancelAnimationFrame, getKeys, IObject, requestAnimationFrame } from "@daybrush/utils";
import { cancelAnimationFrame, find, getKeys, IObject, requestAnimationFrame } from "@daybrush/utils";
import { renderLine } from "./renderDirections";
import { fitPoints, getAreaSize, getOverlapSize, isInside } from "overlap-area";
import EventManager from "./EventManager";
Expand Down Expand Up @@ -67,7 +67,7 @@ export default class MoveableManager<T = {}>
};
public state: MoveableManagerState = {
container: null,
gesto: null,
gestos: {},
renderPoses: [[0, 0], [0, 0], [0, 0], [0, 0]],
disableNativeEvent: false,
...getMoveableTargetInfo(null),
Expand Down Expand Up @@ -181,6 +181,16 @@ export default class MoveableManager<T = {}>
manager && manager.destroy();
}
}
/**
* Get the able used in MoveableManager.
* @method Moveable#getAble
* @param - able name
*/
public getAble<T extends Able>(ableName: string): T | undefined {
const ables: Able[] = this.props.ables || [];

return find(ables, able => able.name === ableName) as T;
}
public getContainer(): HTMLElement | SVGElement {
const { parentMoveable, wrapperMoveable, container } = this.props;

Expand Down Expand Up @@ -544,7 +554,8 @@ export default class MoveableManager<T = {}>
const props = this.props;
const {
originalBeforeOrigin, transformOrigin,
allMatrix, is3d, pos1, pos2, pos3, pos4,
allMatrix, is3d,
pos1, pos2, pos3, pos4,
left: stateLeft, top: stateTop,
} = state;
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import { fillChildEvents } from "../groupUtils";


function isIdentityMatrix(matrix: string, is3d?: boolean) {
const value = is3d ? `matrix3d(${createIdentityMatrix(4)}` : `matrix(${createIdentityMatrix(3)})`;
const n = is3d ? 4 : 3;
const identityMatrix = createIdentityMatrix(n);
const value = `matrix${is3d ? "3d" : ""}(${identityMatrix.join(",")})`;

return matrix === value || matrix === `matrix(1,0,0,1,0,0)`;
}
Expand Down
19 changes: 11 additions & 8 deletions packages/react-moveable/src/react-moveable/ables/Draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
triggerEvent, fillParams,
getDistSize, prefix,
fillEndParams, getComputedStyle,
fillCSSObject,
} from "../utils";
import { minus, plus } from "@scena/matrix";
import {
Expand Down Expand Up @@ -79,13 +80,13 @@ export default {
const state = moveable.state;
const {
target,
gesto,
gestos,
} = state;

if (gesto) {
if (gestos.draggable) {
return false;
}
state.gesto = parentGesto || moveable.targetGesto;
gestos.draggable = parentGesto || moveable.targetGesto;
const style = getComputedStyle(target!);

datas.datas = {};
Expand Down Expand Up @@ -119,7 +120,7 @@ export default {
dist: [0, 0],
};
} else {
state.gesto = null;
gestos.draggable = null;
datas.isPinch = false;
}
return datas.isDrag ? params : false;
Expand Down Expand Up @@ -246,6 +247,9 @@ export default {
width,
height,
isPinch,
...fillCSSObject({
style: nextTransform,
}),
});

!parentEvent && triggerEvent(moveable, "onDrag", params);
Expand All @@ -272,7 +276,6 @@ export default {
) {
const { parentEvent, datas } = e;

moveable.state.gesto = null;
moveable.state.dragInfo = null;
if (!datas.isDrag) {
return;
Expand All @@ -293,7 +296,7 @@ export default {
const events = triggerChildGesto(moveable, this, "dragStart", [
clientX || 0,
clientY || 0,
], e, false);
], e, false, "draggable");

const nextParams: OnDragGroupStart = {
...params,
Expand All @@ -314,7 +317,7 @@ export default {
}
const params = this.drag(moveable, e);
const { passDelta } = e.datas;
const events = triggerChildGesto(moveable, this, "drag", passDelta, e, false);
const events = triggerChildGesto(moveable, this, "drag", passDelta, e, false, "draggable");

if (!params) {
return;
Expand All @@ -335,7 +338,7 @@ export default {
return;
}
this.dragEnd(moveable, e);
const events = triggerChildGesto(moveable, this, "dragEnd", [0, 0], e, false);
const events = triggerChildGesto(moveable, this, "dragEnd", [0, 0], e, false, "draggable");
triggerEvent(moveable, "onDragGroupEnd", fillEndParams<OnDragGroupEnd>(moveable, e, {
targets: moveable.props.targets!,
events,
Expand Down
113 changes: 82 additions & 31 deletions packages/react-moveable/src/react-moveable/ables/Resizable.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import {
getDirection, triggerEvent,
fillParams, fillCSSObject,
fillParams,
fillEndParams,
getAbsolutePosesByState,
catchEvent,
getOffsetSizeDist,
getProps,
getDirectionCondition,
calculatePoses,
fillAfterTransform,
} from "../utils";
import {
setDragStart,
getResizeDist,
getAbsolutePosition,
getPosByDirection,
getNextMatrix,
getNextTransforms,
} from "../gesto/GestoUtils";
import {
ResizableProps, OnResizeGroup, OnResizeGroupEnd,
Expand All @@ -26,7 +30,7 @@ import {
triggerChildAbles,
} from "../groupUtils";
import Draggable from "./Draggable";
import { calculate, createRotateMatrix, plus } from "@scena/matrix";
import { calculate, convertDimension, createRotateMatrix, plus } from "@scena/matrix";
import CustomGesto, { setCustomDrag } from "../gesto/CustomGesto";
import { checkSnapResize } from "./Snappable";
import {
Expand All @@ -36,6 +40,7 @@ import {
isNumber,
} from "@daybrush/utils";
import { TINY_NUM } from "../consts";
import { parseMat } from "css-to-mat";

/**
* @namespace Resizable
Expand Down Expand Up @@ -80,16 +85,23 @@ export default {
isPinch,
isGroup,
parentDirection,
parentGesto,
datas,
parentFixedDirection,
parentEvent,
} = e;

const direction = parentDirection || (isPinch ? [0, 0] : getDirection(inputEvent.target));
const state = moveable.state;
const { target, width, height } = state;
const { target, width, height, gestos } = state;

if (!direction || !target) {
return false;
}
if (gestos.resizable) {
return false;
}
gestos.resizable = parentGesto || moveable.controlGesto;
!isPinch && setDragStart(moveable, e);

datas.datas = {};
Expand Down Expand Up @@ -120,6 +132,9 @@ export default {
? transformOrigin.split(" ")
: transformOrigin;

datas.startOffsetMatrix = state.offsetMatrix;
datas.startTransformOrigin = state.transformOrigin;

datas.isWidth = e?.parentIsWidth ?? ((!direction[0] && !direction[1]) || direction[0] || !direction[1]);

function setRatio(ratio: number) {
Expand Down Expand Up @@ -154,7 +169,7 @@ export default {
}

setRatio(width / height);
setFixedDirection([-direction[0], -direction[1]]);
setFixedDirection(parentFixedDirection || [-direction[0], -direction[1]]);

datas.setFixedDirection = setFixedDirection;
datas.setMin = setMin;
Expand All @@ -178,7 +193,8 @@ export default {
new CustomGesto().dragStart([0, 0], e),
),
});
const result = triggerEvent(moveable, "onResizeStart", params);
const result = parentEvent || triggerEvent(moveable, "onResizeStart", params);

if (result !== false) {
datas.isResize = true;
moveable.state.snapRenderInfo = {
Expand All @@ -201,6 +217,8 @@ export default {
parentDist,
isRequest,
isGroup,
parentEvent,
resolveMatrix,
} = e;

const {
Expand All @@ -216,12 +234,39 @@ export default {
startOffsetWidth,
startOffsetHeight,
isWidth,

} = datas;

if (!isResize) {
return;
}
if (resolveMatrix) {
const {
is3d,
} = moveable.state;
const {
startOffsetMatrix,
startTransformOrigin,
} = datas;
const n = is3d ? 4 : 3;
let targetMatrix = parseMat(getNextTransforms(e));
const targetN = Math.sqrt(targetMatrix.length);

if (n !== targetN) {
targetMatrix = convertDimension(targetMatrix, targetN, n);
}

const nextAllMatrix = getNextMatrix(
startOffsetMatrix,
targetMatrix,
startTransformOrigin,
n,
);
const poses = calculatePoses(nextAllMatrix, startOffsetWidth, startOffsetHeight, n);

datas.startPositions = poses;
datas.nextTargetMatrix = targetMatrix;
datas.nextAllMatrix = nextAllMatrix;
}
const props = getProps(moveable.props, "resizable");
const {
resizeFormat,
Expand All @@ -240,14 +285,15 @@ export default {
const keepRatio = (ratio && (parentKeepRatio != null ? parentKeepRatio : props.keepRatio)) || false;

function getNextBoundingSize() {
const fixedDirection = datas.fixedDirection;
const nextSize = getOffsetSizeDist(sizeDirection, keepRatio, datas, e);

distWidth = nextSize.distWidth;
distHeight = nextSize.distHeight;

let nextWidth = sizeDirection[0] || keepRatio
let nextWidth = (sizeDirection[0] - fixedDirection[0]) || keepRatio
? Math.max(startOffsetWidth + distWidth, TINY_NUM) : startOffsetWidth;
let nextHeight = sizeDirection[1] || keepRatio
let nextHeight = (sizeDirection[1] - fixedDirection[1]) || keepRatio
? Math.max(startOffsetHeight + distHeight, TINY_NUM) : startOffsetHeight;

if (keepRatio && startOffsetWidth && startOffsetHeight) {
Expand All @@ -263,22 +309,24 @@ export default {

let [boundingWidth, boundingHeight] = getNextBoundingSize();

datas.setFixedDirection(datas.fixedDirection);
if (!parentEvent) {
datas.setFixedDirection(datas.fixedDirection);

triggerEvent(moveable, "onBeforeResize", fillParams<OnBeforeResize>(moveable, e, {
setFixedDirection(nextFixedDirection: number[]) {
datas.setFixedDirection(nextFixedDirection);
triggerEvent(moveable, "onBeforeResize", fillParams<OnBeforeResize>(moveable, e, {
setFixedDirection(nextFixedDirection: number[]) {
datas.setFixedDirection(nextFixedDirection);

[boundingWidth, boundingHeight] = getNextBoundingSize();
[boundingWidth, boundingHeight] = getNextBoundingSize();

return [boundingWidth, boundingHeight];
},
boundingWidth,
boundingHeight,
setSize(size: number[]) {
[boundingWidth, boundingHeight] = size;
},
}, true));
return [boundingWidth, boundingHeight];
},
boundingWidth,
boundingHeight,
setSize(size: number[]) {
[boundingWidth, boundingHeight] = size;
},
}, true));
}

let fixedPosition = dragClient;

Expand Down Expand Up @@ -379,18 +427,19 @@ export default {
moveable,
boundingWidth,
boundingHeight,
datas.fixedDirection,
fixedPosition,
transformOrigin,
datas,
);

if (!parentMoveable && delta.every(num => !num) && inverseDelta.every(num => !num)) {
return;
}
const drag = Draggable.drag(
moveable,
setCustomDrag(e, moveable.state, inverseDelta, !!isPinch, false),
setCustomDrag(e, moveable.state, inverseDelta, !!isPinch, false, "draggable"),
) as OnDrag;
const transform = drag.transform;
const params = fillParams<OnResize>(moveable, e, {
width: startWidth + distWidth,
height: startHeight + distHeight,
Expand All @@ -404,13 +453,15 @@ export default {
delta,
isPinch: !!isPinch,
drag,
...fillCSSObject({
width: `${boundingWidth}px`,
height: `${boundingHeight}px`,
transform: drag.transform,
}),
...fillAfterTransform({
style: {
width: `${boundingWidth}px`,
height: `${boundingHeight}px`,
},
transform,
}, drag),
});
triggerEvent(moveable, "onResize", params);
!parentEvent && triggerEvent(moveable, "onResize", params);
return params;
},
dragControlAfter(
Expand Down Expand Up @@ -456,14 +507,14 @@ export default {
moveable: MoveableManagerInterface<ResizableProps & DraggableProps>,
e: any,
) {
const { datas } = e;
const { datas, parentEvent } = e;
if (!datas.isResize) {
return;
}
datas.isResize = false;

const params = fillEndParams<OnResizeEnd>(moveable, e, {});
triggerEvent(moveable, "onResizeEnd", params);
!parentEvent && triggerEvent(moveable, "onResizeEnd", params);
return params;
},
dragGroupControlCondition: directionCondition,
Expand Down

0 comments on commit 24482a6

Please sign in to comment.