Skip to content

Commit 7b936ac

Browse files
committed
fix: fix keepRatio for zero scale #927
1 parent d63283c commit 7b936ac

6 files changed

Lines changed: 91 additions & 27 deletions

File tree

packages/react-moveable/src/ables/Scalable.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ export default {
206206
const keepRatio = (ratio && (parentKeepRatio != null ? parentKeepRatio : props.keepRatio)) || false;
207207
const state = moveable.state;
208208

209+
let tempStartX = startValue[0];
210+
let tempStartY = startValue[1];
211+
209212
function getNextScale() {
210213
const {
211214
distWidth,
@@ -216,8 +219,14 @@ export default {
216219
let scaleX = startOffsetWidth ? (startOffsetWidth + distWidth) / startOffsetWidth : 1;
217220
let scaleY = startOffsetHeight ? (startOffsetHeight + distHeight) / startOffsetHeight : 1;
218221

219-
scaleX = sizeDirection[0] || keepRatio ? scaleX * startValue[0] : startValue[0];
220-
scaleY = sizeDirection[1] || keepRatio ? scaleY * startValue[1] : startValue[1];
222+
if (!startValue[0]) {
223+
tempStartX = distWidth / startOffsetWidth;
224+
}
225+
if (!startValue[1]) {
226+
tempStartY = distHeight / startOffsetHeight;
227+
}
228+
scaleX = (sizeDirection[0] || keepRatio ? scaleX : 1) * tempStartX;
229+
scaleY = (sizeDirection[1] || keepRatio ? scaleY : 1) * tempStartY;
221230

222231
if (scaleX === 0) {
223232
scaleX = (prevDist[0] > 0 ? 1 : -1) * MIN_SCALE;
@@ -254,7 +263,10 @@ export default {
254263
},
255264
}, true));
256265

257-
const dist = [scale[0] / startValue[0], scale[1] / startValue[1]];
266+
const dist = [
267+
scale[0] / tempStartX,
268+
scale[1] / tempStartY,
269+
];
258270
let fixedPosition = dragClient;
259271
let snapDist = [0, 0];
260272

@@ -294,9 +306,9 @@ export default {
294306

295307
if (isNoSnap) {
296308
if (isWidth) {
297-
dist[0] = throttle(dist[0] * startValue[0], throttleScale!) / startValue[0];
309+
dist[0] = throttle(dist[0] * tempStartX, throttleScale!) / tempStartX;
298310
} else {
299-
dist[1] = throttle(dist[1] * startValue[1], throttleScale!) / startValue[1];
311+
dist[1] = throttle(dist[1] * tempStartY, throttleScale!) / tempStartY;
300312
}
301313
}
302314
if (
@@ -305,27 +317,27 @@ export default {
305317
|| (isNoSnap && isWidth)
306318
) {
307319
dist[0] += snapDist[0];
308-
const snapHeight = startOffsetWidth * dist[0] * startValue[0] / ratio;
320+
const snapHeight = startOffsetWidth * dist[0] * tempStartX / ratio;
309321

310-
dist[1] = snapHeight / startOffsetHeight / startValue[1];
322+
dist[1] = snapHeight / startOffsetHeight / tempStartY;
311323
} else if (
312324
(!sizeDirection[0] && sizeDirection[1])
313325
|| (!snapDist[0] && snapDist[1])
314326
|| (isNoSnap && !isWidth)
315327
) {
316328
dist[1] += snapDist[1];
317-
const snapWidth = startOffsetHeight * dist[1] * startValue[1] * ratio;
329+
const snapWidth = startOffsetHeight * dist[1] * tempStartY * ratio;
318330

319-
dist[0] = snapWidth / startOffsetWidth / startValue[0];
331+
dist[0] = snapWidth / startOffsetWidth / tempStartX;
320332
}
321333
} else {
322334
dist[0] += snapDist[0];
323335
dist[1] += snapDist[1];
324336
if (!snapDist[0]) {
325-
dist[0] = throttle(dist[0] * startValue[0], throttleScale!) / startValue[0];
337+
dist[0] = throttle(dist[0] * tempStartX, throttleScale!) / tempStartX;
326338
}
327339
if (!snapDist[1]) {
328-
dist[1] = throttle(dist[1] * startValue[1], throttleScale!) / startValue[1];
340+
dist[1] = throttle(dist[1] * tempStartY, throttleScale!) / tempStartY;
329341
}
330342
}
331343

@@ -336,15 +348,24 @@ export default {
336348
dist[1] = (prevDist[1] > 0 ? 1 : -1) * MIN_SCALE;
337349
}
338350
const delta = [dist[0] / prevDist[0], dist[1] / prevDist[1]];
339-
scale = multiply2(dist, startValue);
351+
scale = multiply2(dist, [tempStartX, tempStartY]);
352+
353+
354+
355+
const distText = `scale(${dist.join(", ")})`;
356+
const scaleText = `scale(${scale.join(", ")})`;
357+
const nextTransform = convertTransformFormat(
358+
datas, scaleText, distText);
359+
const isZeroScale = !startValue[0] || !startValue[1];
340360

341361
const inverseDist = getScaleDist(
342362
moveable,
343-
dist,
363+
isZeroScale ? scaleText : distText,
344364
datas.fixedDirection,
345365
fixedPosition,
346366
datas.fixedOffset,
347367
datas,
368+
isZeroScale,
348369
);
349370
const inverseDelta = isSelfPinch ? inverseDist : minus(inverseDist, datas.prevInverseDist || [0, 0]);
350371

@@ -360,8 +381,6 @@ export default {
360381
}
361382

362383

363-
const nextTransform = convertTransformFormat(
364-
datas, `scale(${scale.join(", ")})`, `scale(${dist.join(", ")})`);
365384
const params = fillParams<OnScale>(moveable, e, {
366385
offsetWidth: startOffsetWidth,
367386
offsetHeight: startOffsetHeight,

packages/react-moveable/src/gesto/GestoUtils.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ export function getNextTransformMatrix(
344344
state: MoveableManagerState<any>,
345345
datas: any,
346346
transform: string | number[],
347+
isAllTransform?: boolean,
347348
) {
348349
const {
349350
transformOrigin,
@@ -359,10 +360,14 @@ export function getNextTransformMatrix(
359360
afterTransform,
360361
} = datas;
361362

362-
targetTransform = convertDimension(
363-
multiply(multiply(beforeTransform, parseMat([transform]), 4), afterTransform, 4),
364-
4, n,
365-
);
363+
if (isAllTransform) {
364+
targetTransform = convertDimension(parseMat(transform), 4, n);
365+
} else {
366+
targetTransform = convertDimension(
367+
multiply(multiply(beforeTransform, parseMat([transform]), 4), afterTransform, 4),
368+
4, n,
369+
);
370+
}
366371
} else {
367372
targetTransform = transform;
368373
}
@@ -489,8 +494,9 @@ export function getTranslateFixedPosition(
489494
fixedDirection: number[],
490495
fixedOffset: number[],
491496
datas: any,
497+
isAllTransform?: boolean,
492498
) {
493-
const nextMatrix = getNextTransformMatrix(moveable.state, datas, transform);
499+
const nextMatrix = getNextTransformMatrix(moveable.state, datas, transform, isAllTransform);
494500
const nextFixedPosition = getDirectionOffset(
495501
moveable,
496502
fixedDirection,
@@ -508,13 +514,15 @@ export function getTranslateDist(
508514
fixedPosition: number[],
509515
fixedOffset: number[],
510516
datas: any,
517+
isAllTransform?: boolean,
511518
) {
512519
const nextFixedPosition = getTranslateFixedPosition(
513520
moveable,
514521
transform,
515522
fixedDirection,
516523
fixedOffset,
517524
datas,
525+
isAllTransform,
518526
);
519527
const state = moveable.state;
520528
const {
@@ -531,19 +539,21 @@ export function getTranslateDist(
531539
}
532540
export function getScaleDist(
533541
moveable: MoveableManagerInterface<any>,
534-
scaleDist: number[],
542+
transform: string,
535543
fixedDirection: number[],
536544
fixedPosition: number[],
537545
fixedOffset: number[],
538546
datas: any,
547+
isAllTransform?: boolean,
539548
) {
540549
const dist = getTranslateDist(
541550
moveable,
542-
`scale(${scaleDist.join(", ")})`,
551+
transform,
543552
fixedDirection,
544553
fixedPosition,
545554
fixedOffset,
546555
datas,
556+
isAllTransform,
547557
);
548558

549559
return dist;

packages/react-moveable/src/renderDirections.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from "./types";
66
import { DIRECTION_INDEXES, DIRECTION_ROTATIONS, DIRECTIONS, DIRECTIONS4 } from "./consts";
77
import { IObject, throttle, getRad, getKeys } from "@daybrush/utils";
8+
import { absDegree } from "./ables/Snappable";
89

910
export interface DirectionControlInfo {
1011
data: Record<string, any>;
@@ -25,15 +26,14 @@ export function renderDirectionControlsByInfos(
2526
rotation: rotationRad,
2627
direction,
2728
} = moveable.getState();
29+
2830
const {
2931
zoom,
3032
} = getProps(moveable.props, ableName as any);
3133

32-
3334
const sign = (direction > 0 ? 1 : -1);
34-
const degRotation = rotationRad / Math.PI * 180;
35+
const degRotation = absDegree(rotationRad / Math.PI * 180);
3536
const directionMap: IObject<boolean> = {};
36-
3737
const renderState = moveable.renderState;
3838
if (!renderState.renderDirectionMap) {
3939
renderState.renderDirectionMap = {};

packages/react-moveable/src/utils.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { prefixNames } from "framework-utils";
33
import {
44
isUndefined, isObject, splitUnit,
55
IObject, hasClass, isArray, isString, getRad,
6-
getShapeDirection, isFunction, convertUnitSize, between, getKeys, decamelize, isNumber,
6+
isFunction, convertUnitSize, between, getKeys, decamelize, isNumber,
77
getDocumentBody,
88
getDocumentElement,
99
getWindow,
@@ -537,6 +537,7 @@ export function calculateMoveableClientPositions(
537537
});
538538

539539
}
540+
540541
export function calculateMoveablePosition(
541542
matrix: number[],
542543
origin: number[],
@@ -572,7 +573,11 @@ export function calculateMoveablePosition(
572573
originX = (originX - left) || 0;
573574
originY = (originY - top) || 0;
574575

575-
const direction = getShapeDirection(calculatePoses(matrix, 100, 100, n));
576+
577+
const sx = matrix[0];
578+
const sy = matrix[n + 1];
579+
const direction = sx * sy >= 0 ? 1 : -1;
580+
576581
return {
577582
left,
578583
top,

packages/react-moveable/stories/99-Tests/Deafult.stories.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,11 @@ export const TestChangeTargetsOnClick = add("Test Change Target on Click Group",
217217
path: require.resolve("./ReactChangeTargetsOnClickApp"),
218218
});
219219

220+
221+
222+
export const TestScalableKeepRatio = add("Even if the size is 0, the ratio is maintained.", {
223+
app: require("./ReactScalableKeepRatioApp").default,
224+
path: require.resolve("./ReactScalableKeepRatioApp"),
225+
});
226+
227+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as React from "react";
2+
import Moveable from "@/react-moveable";
3+
4+
export default function App() {
5+
return <div className="container">
6+
<div className="target" style={{
7+
transform: "scale(1, 0)",
8+
}}>Target1</div>
9+
<Moveable
10+
target={".target"}
11+
scalable={true}
12+
keepRatio={true}
13+
onScaleStart={e => {
14+
e.setRatio(1);
15+
}}
16+
onScale={e => {
17+
// console.log(e.scale);
18+
e.target.style.cssText += e.cssText;
19+
}}
20+
/>
21+
</div>;
22+
}

0 commit comments

Comments
 (0)