From 7d8a2282b8474d6efa643f1744de7484e14de49f Mon Sep 17 00:00:00 2001 From: "Daybrush (Younkue Choi)" Date: Sat, 23 Nov 2019 03:48:50 +0900 Subject: [PATCH] fix: fix Resizable's wrong position calculation (#101) * feat: add baseDirection props * fix: fix Resizable's wrong position calculation --- package-lock.json | 16 +-- package.json | 4 +- packages/preact-moveable/package-lock.json | 8 +- packages/preact-moveable/package.json | 4 +- packages/react-moveable/package-lock.json | 2 +- packages/react-moveable/package.json | 2 +- packages/react-moveable/src/App.css | 5 + packages/react-moveable/src/App.tsx | 26 ++-- .../src/react-moveable/DraggerUtils.ts | 33 ++++-- .../src/react-moveable/MoveableManager.tsx | 7 ++ .../src/react-moveable/ables/Resizable.ts | 112 ++++++++++++------ .../src/react-moveable/getAbleDragger.ts | 5 +- .../src/react-moveable/types.ts | 9 +- src/consts.ts | 1 + src/types.ts | 1 + 15 files changed, 161 insertions(+), 74 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5e542e859..104e9f727 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "moveable", - "version": "0.10.8-rc", + "version": "0.11.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1099,12 +1099,12 @@ } }, "preact-moveable": { - "version": "0.12.14", - "resolved": "https://registry.npmjs.org/preact-moveable/-/preact-moveable-0.12.14.tgz", - "integrity": "sha512-OaKURhEONjHfRGlxfI3mjRNaMBFfBJXGJf1wG6S4XEbFzsk9ellHRVWNBJz7PSnpOdrk+75aDI8ahPPvn0oBEA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/preact-moveable/-/preact-moveable-0.13.0.tgz", + "integrity": "sha512-Ew0um2he/IiwRq10/eHn7IcRHVSmpKKsJ1xZacmcKSM8fA5slNn0XpYnxCt/gMcpTPIB0sUK5jtw0jhvygrmvg==", "requires": { "preact-css-styler": "^1.0.0", - "react-moveable": "^0.13.12" + "react-moveable": "^0.14.0" } }, "preact-render-to-string": { @@ -1211,9 +1211,9 @@ "dev": true }, "react-moveable": { - "version": "0.13.12", - "resolved": "https://registry.npmjs.org/react-moveable/-/react-moveable-0.13.12.tgz", - "integrity": "sha512-s3gwgypLtdd3SdTR4dQGiE9c9LmvHyT+NV0MssrvwYLjh2Yn7rnhlrcaR25INswa83Wamu4Y0jxCYUt1eP4dLg==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-moveable/-/react-moveable-0.14.0.tgz", + "integrity": "sha512-4OerKOr2iFwO5Bjnk57mMkSEjLUKwrB/Q7MfQcgXs7Zi3OwnZ10dHp7MydC4bPYQS/bHG4/Cx8rwmJLj7/QHJw==", "requires": { "@daybrush/drag": "^0.11.1", "@daybrush/utils": "^0.10.0", diff --git a/package.json b/package.json index a5212f737..b108e7de2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "moveable", - "version": "0.10.8", + "version": "0.11.0-rc2", "description": "Moveable is Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable, Snappable.", "main": "./dist/moveable.cjs.js", "module": "./dist/moveable.esm.js", @@ -57,7 +57,7 @@ "dependencies": { "@egjs/component": "^2.1.2", "preact": "^10.0.4", - "preact-moveable": "^0.12.14" + "preact-moveable": "^0.13.0" }, "devDependencies": { "@daybrush/builder": "^0.1.2", diff --git a/packages/preact-moveable/package-lock.json b/packages/preact-moveable/package-lock.json index 61fa5fed6..c71459603 100644 --- a/packages/preact-moveable/package-lock.json +++ b/packages/preact-moveable/package-lock.json @@ -1,6 +1,6 @@ { "name": "preact-moveable", - "version": "0.12.14", + "version": "0.13.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -788,9 +788,9 @@ "dev": true }, "react-moveable": { - "version": "0.13.12", - "resolved": "https://registry.npmjs.org/react-moveable/-/react-moveable-0.13.12.tgz", - "integrity": "sha512-s3gwgypLtdd3SdTR4dQGiE9c9LmvHyT+NV0MssrvwYLjh2Yn7rnhlrcaR25INswa83Wamu4Y0jxCYUt1eP4dLg==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-moveable/-/react-moveable-0.14.2.tgz", + "integrity": "sha512-f0UnYcKilG5/6REUDRXMvvfVoTn5tciK3UiqQEgi9hAQf6ar9VY9O44oGResnxccYfQ3YNdsANWMtxCwY1czOQ==", "requires": { "@daybrush/drag": "^0.11.1", "@daybrush/utils": "^0.10.0", diff --git a/packages/preact-moveable/package.json b/packages/preact-moveable/package.json index ad909cda3..3a49bd822 100644 --- a/packages/preact-moveable/package.json +++ b/packages/preact-moveable/package.json @@ -1,6 +1,6 @@ { "name": "preact-moveable", - "version": "0.12.14", + "version": "0.13.1", "description": "A Preact Component that create Moveable, Draggable, Resizable, Scalable, Rotatable, Pinchable, Groupable, Snappable.", "main": "./dist/moveable.cjs.js", "module": "./dist/moveable.esm.js", @@ -61,6 +61,6 @@ }, "dependencies": { "preact-css-styler": "^1.0.0", - "react-moveable": "^0.13.12" + "react-moveable": "^0.14.2" } } diff --git a/packages/react-moveable/package-lock.json b/packages/react-moveable/package-lock.json index d07e715f8..5301ee85d 100644 --- a/packages/react-moveable/package-lock.json +++ b/packages/react-moveable/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-moveable", - "version": "0.13.12", + "version": "0.14.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/react-moveable/package.json b/packages/react-moveable/package.json index 71bb16eda..96a75a947 100644 --- a/packages/react-moveable/package.json +++ b/packages/react-moveable/package.json @@ -1,6 +1,6 @@ { "name": "react-moveable", - "version": "0.13.12", + "version": "0.14.3", "description": "A React Component that create Moveable, Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable.", "main": "./dist/moveable.cjs.js", "module": "./dist/moveable.esm.js", diff --git a/packages/react-moveable/src/App.css b/packages/react-moveable/src/App.css index 4889e067b..7e108f3eb 100644 --- a/packages/react-moveable/src/App.css +++ b/packages/react-moveable/src/App.css @@ -149,4 +149,9 @@ img { .box.box23 { border-left-width: 0px; border-right-width: 0px; + word-break: break-all; + height: auto; +} +.box.box23 span { + position: relative; } diff --git a/packages/react-moveable/src/App.tsx b/packages/react-moveable/src/App.tsx index 9dd1d3dc3..8d0edf241 100644 --- a/packages/react-moveable/src/App.tsx +++ b/packages/react-moveable/src/App.tsx @@ -17,18 +17,20 @@ setAlias("matrix3d", ["transform", "matrix3d"]); class App extends React.Component { public moveable!: Moveable; - public state = { - target: null, - container: null, - targets: [], - isResizable: true, - emo: null, - } as { + public state: { container: any, target: any, emo: any, + isShift: boolean, targets: Array, isResizable: boolean, + } = { + target: null, + container: null, + targets: [], + isResizable: true, + isShift: false, + emo: null, }; private itemMap: Map = new Map(); private items: IObject = {}; @@ -51,8 +53,8 @@ class App extends React.Component { pinchable={true} draggable={true} rotatable={true} - // resizable={true} - scalable={true} + resizable={true} + // scalable={true} ref={ref(this, "ab")} // keepRatio={false} target={this.state.targets} @@ -154,7 +156,7 @@ class App extends React.Component { target={selectedTarget} container={document.querySelector("#con")} ref={ref(this, "moveable")} - keepRatio={true} + // keepRatio={this.state.isShift} origin={false} // dragArea={true} draggable={true} @@ -352,9 +354,9 @@ class App extends React.Component { const keycon = new KeyController(window); keycon.keydown("shift", () => { - this.setState({ isResizable: false }); + this.setState({ isResizable: false, isShift: true }); }).keyup("shift", () => { - this.setState({ isResizable: true }); + this.setState({ isResizable: true, isShift: false }); }); const targets: any[] = [].slice.call(document.querySelectorAll(`[data-target="box"] span`)); diff --git a/packages/react-moveable/src/react-moveable/DraggerUtils.ts b/packages/react-moveable/src/react-moveable/DraggerUtils.ts index 6a3a03d7f..fc6ead9e9 100644 --- a/packages/react-moveable/src/react-moveable/DraggerUtils.ts +++ b/packages/react-moveable/src/react-moveable/DraggerUtils.ts @@ -6,7 +6,7 @@ import { import MoveableManager from "./MoveableManager"; import { caculatePoses, getAbsoluteMatrix, getAbsolutePosesByState } from "./utils"; import { splitUnit } from "@daybrush/utils"; -import { MoveableManagerState } from "./types"; +import { MoveableManagerState, GroupableProps, ResizableProps } from "./types"; export function setDragStart(moveable: MoveableManager, { datas }: any) { const { @@ -229,12 +229,14 @@ export function getScaleDist( } export function getResizeDist( - moveable: MoveableManager, + moveable: MoveableManager, width: number, height: number, + // prevWidth: number, + // prevHeight: number, direction: number[], + fixedPosition: number[], transformOrigin: string[], - dragClient?: number[], ) { const { groupable, @@ -245,7 +247,7 @@ export function getResizeDist( offsetMatrix, is3d, width: prevWidth, - height: prevheight, + height: prevHeight, left, top, } = moveable.state; @@ -256,14 +258,31 @@ export function getResizeDist( width, height, prevWidth, - prevheight, + prevHeight, prevOrigin, ); const groupLeft = groupable ? left : 0; const groupTop = groupable ? top : 0; const nextMatrix = getNextMatrix(offsetMatrix, targetMatrix, nextOrigin, n); - const startPos = dragClient ? dragClient : getStartPos(getAbsolutePosesByState(moveable.state), direction); - const dist = getDist(startPos, nextMatrix, width, height, n, direction); + const dist = getDist(fixedPosition, nextMatrix, width, height, n, direction); return minus(dist, [groupLeft, groupTop]); } +export function getStartDirection( + moveable: MoveableManager, + direction: number[], +) { + const { + baseDirection = [-1, -1], + } = moveable.props; + return [ + direction[0] ? direction[0] : baseDirection[0] * -1, + direction[1] ? direction[0] : baseDirection[1] * -1, + ]; +} +export function getFixedPosition( + moveable: MoveableManager, + direction: number[], +) { + return getStartPos(getAbsolutePosesByState(moveable.state), direction); +} diff --git a/packages/react-moveable/src/react-moveable/MoveableManager.tsx b/packages/react-moveable/src/react-moveable/MoveableManager.tsx index d13c9b514..da7a7d77b 100644 --- a/packages/react-moveable/src/react-moveable/MoveableManager.tsx +++ b/packages/react-moveable/src/react-moveable/MoveableManager.tsx @@ -188,9 +188,14 @@ export default class MoveableManager this.updateRect(type, true); } public getRect(): RectInfo { + const state = this.state; const poses = getAbsolutePosesByState(this.state); const [pos1, pos2, pos3, pos4] = poses; const rect = getRect(poses); + const { + width: offsetWidth, + height: offsetHeight, + } = state; const { width, height, @@ -206,6 +211,8 @@ export default class MoveableManager pos2, pos3, pos4, + offsetWidth, + offsetHeight, }; } public checkUpdate() { diff --git a/packages/react-moveable/src/react-moveable/ables/Resizable.ts b/packages/react-moveable/src/react-moveable/ables/Resizable.ts index f776dc768..503478b5b 100644 --- a/packages/react-moveable/src/react-moveable/ables/Resizable.ts +++ b/packages/react-moveable/src/react-moveable/ables/Resizable.ts @@ -7,6 +7,8 @@ import { getDragDist, getResizeDist, getPosByReverseDirection, + getFixedPosition, + getStartDirection, } from "../DraggerUtils"; import { ResizableProps, OnResizeGroup, OnResizeGroupEnd, @@ -63,19 +65,21 @@ export default { datas.datas = {}; datas.direction = direction; - datas.offsetWidth = width; - datas.offsetHeight = height; + datas.startOffsetWidth = width; + datas.startOffsetHeight = height; datas.prevWidth = 0; datas.prevHeight = 0; - datas.width = width; - datas.height = height; + datas.startWidth = width; + datas.startHeight = height; datas.transformOrigin = moveable.props.transformOrigin; + datas.startDirection = getStartDirection(moveable, direction); + datas.fixedPosition = getFixedPosition(moveable, datas.startDirection); const params = fillParams(moveable, e, { direction, set: ([startWidth, startHeight]: number[]) => { - datas.width = startWidth; - datas.height = startHeight; + datas.startWidth = startWidth; + datas.startHeight = startHeight; }, setOrigin: (origin: Array) => { datas.transformOrigin = origin; @@ -105,12 +109,6 @@ export default { } = e; const { direction, - width, - height, - offsetWidth, - offsetHeight, - prevWidth, - prevHeight, isResize, transformOrigin, } = datas; @@ -118,25 +116,32 @@ export default { if (!isResize) { return; } + const { + startWidth, + startHeight, + startOffsetWidth, + startOffsetHeight, + prevWidth, + prevHeight, + } = datas; const { throttleResize = 0, parentMoveable, } = moveable.props; const keepRatio = moveable.props.keepRatio || parentScale; const isWidth = direction[0] || !direction[1]; - const ratio = isWidth ? offsetHeight / offsetWidth : offsetWidth / offsetHeight; + const ratio = isWidth ? startOffsetHeight / startOffsetWidth : startOffsetWidth / startOffsetHeight; let distWidth: number = 0; let distHeight: number = 0; - // diagonal if (parentScale) { - distWidth = (parentScale[0] - 1) * offsetWidth; - distHeight = (parentScale[1] - 1) * offsetHeight; + distWidth = (parentScale[0] - 1) * startOffsetWidth; + distHeight = (parentScale[1] - 1) * startOffsetHeight; } else if (pinchFlag) { if (parentDistance) { distWidth = parentDistance; - distHeight = parentDistance * offsetHeight / offsetWidth; + distHeight = parentDistance * startOffsetHeight / startOffsetWidth; } } else { const dist = getDragDist({ datas, distX, distY }); @@ -144,10 +149,10 @@ export default { distWidth = direction[0] * dist[0]; distHeight = direction[1] * dist[1]; - if (keepRatio && offsetWidth && offsetHeight) { + if (keepRatio && startOffsetWidth && startOffsetHeight) { const rad = getRad([0, 0], dist); const standardRad = getRad([0, 0], direction); - const ratioRad = getRad([0, 0], [offsetWidth, offsetHeight]); + const ratioRad = getRad([0, 0], [startOffsetWidth, startOffsetHeight]); const size = Math.sqrt(distWidth * distWidth + distHeight * distHeight); const signSize = Math.cos(rad - standardRad) * size; @@ -166,8 +171,8 @@ export default { } } } - let nextWidth = direction[0] || keepRatio ? Math.max(offsetWidth + distWidth, 0) : offsetWidth; - let nextHeight = direction[1] || keepRatio ? Math.max(offsetHeight + distHeight, 0) : offsetHeight; + let nextWidth = direction[0] || keepRatio ? Math.max(startOffsetWidth + distWidth, 0) : startOffsetWidth; + let nextHeight = direction[1] || keepRatio ? Math.max(startOffsetHeight + distHeight, 0) : startOffsetHeight; let snapDist = [0, 0]; @@ -208,6 +213,8 @@ export default { nextWidth = getKeepRatioWidth(nextHeight, isWidth, ratio); } } else { + nextWidth += snapDist[0]; + nextHeight += snapDist[1]; if (!snapDist[0]) { nextWidth = throttle(nextWidth, throttleResize!); } @@ -218,8 +225,8 @@ export default { nextWidth = Math.round(nextWidth); nextHeight = Math.round(nextHeight); - distWidth = nextWidth - offsetWidth; - distHeight = nextHeight - offsetHeight; + distWidth = nextWidth - startOffsetWidth; + distHeight = nextHeight - startOffsetHeight; const delta = [distWidth - prevWidth, distHeight - prevHeight]; @@ -229,21 +236,18 @@ export default { if (!parentMoveable && delta.every(num => !num)) { return; } + const startDirection = keepRatio ? direction : datas.startDirection; + const fixedPosition = dragClient || (keepRatio ? getFixedPosition(moveable, direction) : datas.fixedPosition); const inverseDelta = !parentFlag && pinchFlag ? [0, 0] - : getResizeDist(moveable, nextWidth, nextHeight, direction, transformOrigin, dragClient); + : getResizeDist( + moveable, + nextWidth, nextHeight, + startDirection, fixedPosition, transformOrigin); - if (!keepRatio && !parentFlag) { - if (!direction[0]) { - inverseDelta[0] = 0; - } - if (!direction[1]) { - inverseDelta[1] = 0; - } - } const params = fillParams(moveable, e, { - width: width + distWidth, - height: height + distHeight, + width: startWidth + distWidth, + height: startHeight + distHeight, offsetWidth: nextWidth, offsetHeight: nextHeight, direction, @@ -258,6 +262,46 @@ export default { triggerEvent(moveable, "onResize", params); return params; }, + dragControlAfter( + moveable: MoveableManager, + e: any, + ) { + const datas = e.datas; + const { + isResize, + startOffsetWidth, + startOffsetHeight, + prevWidth, + prevHeight, + } = datas; + + if (!isResize) { + return; + } + const { + width, + height, + } = moveable.state; + const errorWidth = width - (startOffsetWidth + prevWidth); + const errorHeight = height - (startOffsetHeight + prevHeight); + const isErrorWidth = Math.abs(errorWidth) > 3; + const isErrorHeight = Math.abs(errorHeight) > 3; + + if (isErrorWidth) { + datas.startWidth += errorWidth; + datas.startOffsetWidth += errorWidth; + datas.prevWidth += errorWidth; + } + if (isErrorHeight) { + datas.startHeight += errorHeight; + datas.startOffsetHeight += errorHeight; + datas.prevHeight += errorHeight; + } + if (isErrorWidth || isErrorHeight) { + this.dragControl(moveable, e); + return true; + } + }, dragControlEnd( moveable: MoveableManager, e: any, diff --git a/packages/react-moveable/src/react-moveable/getAbleDragger.ts b/packages/react-moveable/src/react-moveable/getAbleDragger.ts index 30581c3fe..bb8b7c486 100644 --- a/packages/react-moveable/src/react-moveable/getAbleDragger.ts +++ b/packages/react-moveable/src/react-moveable/getAbleDragger.ts @@ -40,7 +40,7 @@ function triggerAble>( triggerRenderStart(moveable, isGroup, e); } else if (isEnd) { triggerRenderEnd(moveable, isGroup, e); - } else { + } else if (isUpdate) { triggerRender(moveable, isGroup, e); } if (isEnd) { @@ -55,6 +55,9 @@ function triggerAble>( } else if (isEnd && !isUpdate) { moveable.forceUpdate(); } + if (!isStart && !isEnd && isUpdate) { + triggerAble(moveable, ableType, eventOperation, eventAffix, eventType + "After", e); + } } export function getAbleDragger( moveable: MoveableManager, diff --git a/packages/react-moveable/src/react-moveable/types.ts b/packages/react-moveable/src/react-moveable/types.ts index 7e47a84fd..552f5729f 100644 --- a/packages/react-moveable/src/react-moveable/types.ts +++ b/packages/react-moveable/src/react-moveable/types.ts @@ -705,6 +705,7 @@ export interface ResizableProps { resizable?: boolean; throttleResize?: number; renderDirections?: string[]; + baseDirection?: number[]; onResizeStart?: (e: OnResizeStart) => any; onResize?: (e: OnResize) => any; @@ -831,8 +832,10 @@ export interface OnCustomDrag extends Position { * @property - The coordinates of the vertex 1 * @property - left position of the target relative to the container * @property - top position of the target relative to the container - * @property - the offset width of the target - * @property - the offset height of the target + * @property - The width of moveable element + * @property - The height of moveable element + * @property - The offset width of the target + * @property - The offset height of the target */ export interface RectInfo { pos1: number[]; @@ -843,6 +846,8 @@ export interface RectInfo { top: number; width: number; height: number; + offsetWidth: number; + offsetHeight: number; } export interface MoveableInterface { getRect(): RectInfo; diff --git a/src/consts.ts b/src/consts.ts index d80544ee1..eb8507170 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -17,6 +17,7 @@ export const PROPERTIES: Array = [ "getScrollPosition", "scrollContainer", "scrollThreshold", + "baseDirection", ]; export const EVENTS: Array = [ "dragStart", diff --git a/src/types.ts b/src/types.ts index b633de345..7e89515fa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,6 +83,7 @@ export interface MoveableOptions { dragArea?: boolean; rotationPosition?: "top" | "bottom" | "left" | "right"; + baseDirection?: number[]; renderDirections?: string[]; scrollable?: boolean;