Skip to content

Commit bf5df64

Browse files
author
boev
committed
Added resize symmetry feature
1 parent e869e5f commit bf5df64

File tree

6 files changed

+166
-11
lines changed

6 files changed

+166
-11
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,11 @@ you to, for example, get the correct resize and drag deltas while you are zoomed
331331
a transform or matrix in the parent of this element.
332332
If omitted, set `1`.
333333

334+
#### `resizeSymmetry?: 'none' | 'vertical' | 'horizontal' | 'central'`
335+
336+
Allows resize so what `vertical` or `horizontal` axes or `central` point stands still while resizing.
337+
Also useful with `lockAspectRatio` option.
338+
334339
## Callback
335340

336341
#### `onResizeStart?: RndResizeStartCallback;`

src/index.tsx

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export interface Props {
157157
enableUserSelectHack?: boolean;
158158
allowAnyClick?: boolean;
159159
scale?: number;
160+
resizeSymmetry?: "none" | "horizontal" | "vertical" | "central"
160161
[key: string]: any;
161162
}
162163

@@ -488,21 +489,64 @@ export class Rnd extends React.PureComponent<Props, State> {
488489
) {
489490
// INFO: Apply x and y position adjustments caused by resizing to draggable
490491
const newPos = { x: this.originalPosition.x, y: this.originalPosition.y };
491-
const left = -delta.width;
492-
const top = -delta.height;
493-
const directions: ResizeDirection[] = ["top", "left", "topLeft", "bottomLeft", "topRight"];
494-
495-
if (directions.includes(direction)) {
496-
if (direction === "bottomLeft") {
497-
newPos.x += left;
498-
} else if (direction === "topRight") {
499-
newPos.y += top;
500-
} else {
492+
if (!this.props.resizeSymmetry || this.props.resizeSymmetry == "none")
493+
{
494+
const left = -delta.width;
495+
const top = -delta.height;
496+
const directions: ResizeDirection[] = ["top", "left", "topLeft", "bottomLeft", "topRight"];
497+
if (directions.includes(direction)) {
498+
if (direction === "bottomLeft") {
499+
newPos.x += left;
500+
} else if (direction === "topRight") {
501+
newPos.y += top;
502+
} else {
503+
newPos.x += left;
504+
newPos.y += top;
505+
}
506+
}
507+
}
508+
else if (!this.props.resizeSymmetry || this.props.resizeSymmetry == "vertical")
509+
{
510+
const left = -delta.width / 2;
511+
const top = -delta.height;
512+
const directions: ResizeDirection[] = ["top", "left", "right", "topLeft", "bottomLeft", "topRight", "bottomRight"];
513+
if (directions.includes(direction)) {
514+
if (direction === "bottomLeft" || direction === "bottomRight") {
515+
newPos.x += left;
516+
} else if (direction === "right") {
517+
newPos.x -= -left;
518+
newPos.y += top;
519+
} else {
520+
newPos.x += left;
521+
newPos.y += top;
522+
}
523+
}
524+
}
525+
else if (!this.props.resizeSymmetry || this.props.resizeSymmetry == "horizontal")
526+
{
527+
const left = -delta.width;
528+
const top = -delta.height / 2;
529+
const directions: ResizeDirection[] = ["left", "bottom", "top", "bottomLeft", "bottomRight", "topLeft", "topRight", "bottomLeft"];
530+
if (directions.includes(direction)) {
531+
if (direction === "bottomRight" || direction === "topRight") {
532+
newPos.y += top;
533+
} else {
534+
newPos.x += left;
535+
newPos.y += top;
536+
}
537+
}
538+
}
539+
else if (!this.props.resizeSymmetry || this.props.resizeSymmetry == "central")
540+
{
541+
const left = -delta.width / 2;
542+
const top = -delta.height / 2;
543+
const directions: ResizeDirection[] = ["top", "left", "right", "bottom", "topLeft", "bottomLeft", "topRight", "bottomRight"];
544+
if (directions.includes(direction)) {
501545
newPos.x += left;
502546
newPos.y += top;
503547
}
504548
}
505-
549+
506550
const draggableState = this.draggable.state as unknown as { x: number; y: number };
507551
if (newPos.x !== draggableState.x || newPos.y !== draggableState.y) {
508552
flushSync(() => {
@@ -623,6 +667,13 @@ export class Rnd extends React.PureComponent<Props, State> {
623667
// INFO: Make uncontorolled component when resizing to control position by setPostion.
624668
const pos = this.state.resizing ? undefined : draggablePosition;
625669
const dragAxisOrUndefined = this.state.resizing ? "both" : dragAxis;
670+
let resizeRatio:number | [number, number] | undefined = [1, 1];
671+
if (this.props.resizeSymmetry == "vertical")
672+
resizeRatio = [2, 1];
673+
else if (this.props.resizeSymmetry == "horizontal")
674+
resizeRatio = [1, 2];
675+
else if (this.props.resizeSymmetry == "central")
676+
resizeRatio = [2, 2];
626677

627678
return (
628679
<Draggable
@@ -677,6 +728,7 @@ export class Rnd extends React.PureComponent<Props, State> {
677728
handleClasses={resizeHandleClasses}
678729
handleComponent={resizeHandleComponent}
679730
scale={this.props.scale}
731+
resizeRatio={resizeRatio}
680732
>
681733
{children}
682734
</Resizable>

stories/index.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ import SandboxLockAspectRatioWithBounds from "./sandbox/lock-aspect-ratio-with-b
5151
import LockAspectRatioBasic from "./lock-aspect-ratio/basic";
5252
import Issue622 from "./sandbox/issue-#622";
5353

54+
import ResizeSymmetryVertical from "./resizeSymmetry/vertical"
55+
import ResizeSymmetryHorizontal from "./resizeSymmetry/horizontal"
56+
import ResizeSymmetryCentral from "./resizeSymmetry/central"
57+
5458
storiesOf("bare", module).add("bare", () => <Bare />);
5559

5660
storiesOf("basic", module)
@@ -106,3 +110,8 @@ storiesOf("sandbox", module)
106110
storiesOf("ratio", module).add("lock aspect ratio", () => <LockAspectRatioBasic />);
107111

108112
storiesOf("min", module).add("min uncontrolled", () => <MinUncontrolled />);
113+
114+
storiesOf("resize symmetry", module).add("vertical", () => <ResizeSymmetryVertical />);
115+
storiesOf("resize symmetry", module).add("horizontal", () => <ResizeSymmetryHorizontal />);
116+
storiesOf("resize symmetry", module).add("central", () => <ResizeSymmetryCentral />);
117+

stories/resizeSymmetry/central.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React, {CSSProperties} from "react";
2+
import { Rnd } from "../../src";
3+
import { style } from "../styles";
4+
5+
const innerDiv: CSSProperties = {
6+
display: "flex",
7+
alignItems: "center",
8+
justifyContent: "center",
9+
border: "dashed 1px #9C27B0",
10+
height: "120%",
11+
};
12+
const lineStyle: CSSProperties = {
13+
width: "120%",
14+
top: "50%",
15+
border: "dashed 1px #9C27B0",
16+
position: 'absolute'
17+
}
18+
19+
20+
export default () => (
21+
<Rnd
22+
style={style}
23+
default={{
24+
width: 200,
25+
height: 200,
26+
x: 0,
27+
y: 0,
28+
}}
29+
resizeSymmetry="central"
30+
>
31+
<div style={lineStyle} />
32+
<div style={innerDiv}>
33+
34+
</div>
35+
</Rnd>
36+
);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, {CSSProperties} from "react";
2+
import { Rnd } from "../../src";
3+
import { style } from "../styles";
4+
5+
const lineStyle: CSSProperties = {
6+
width: "120%",
7+
top: "50%",
8+
border: "dashed 1px #9C27B0",
9+
position: 'absolute'
10+
}
11+
12+
export default () => (
13+
<Rnd
14+
style={style}
15+
default={{
16+
width: 200,
17+
height: 200,
18+
x: 0,
19+
y: 0,
20+
}}
21+
resizeSymmetry="horizontal"
22+
>
23+
<div style={lineStyle} />
24+
</Rnd>
25+
);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React, {CSSProperties} from "react";
2+
import { Rnd } from "../../src";
3+
import { style } from "../styles";
4+
5+
const innerDiv: CSSProperties = {
6+
display: "flex",
7+
alignItems: "center",
8+
justifyContent: "center",
9+
border: "dashed 1px #9C27B0",
10+
height: "120%",
11+
};
12+
13+
export default () => (
14+
<Rnd
15+
style={style}
16+
default={{
17+
width: 200,
18+
height: 200,
19+
x: 0,
20+
y: 0,
21+
}}
22+
resizeSymmetry="vertical"
23+
>
24+
<div style={innerDiv}>
25+
26+
</div>
27+
</Rnd>
28+
);

0 commit comments

Comments
 (0)