Stop drag when reaching a condition
Overview of the problem
The drag callback is not stopping when meeting conditions. For example, when setting the drag to stop reaching a certain X or Y position, the drag is not stopping, it continues.
I'm using react-rnd version 10.0.0
My browser is: Chrome
I am sure this issue is not a duplicate? Yes
Reproduced project
Here there is a demo where it can be seen. https://codesandbox.io/s/drag-drop-react-rnd-cm8x3
Description
The onDrag is not updating when meeting certain criteria in the callback. For example, when the user is dragging and it reaches a certain distance, it should stop dragging to update. Currently, it is updating once reached the position defined and as it is not stopping the criteria keeps beeing matched and therefore updating really fast.
Steps to Reproduce
In the demo. the drag updates the slide number, so if you drag to the right it should increase the slide number. The expected behaviour can be observed by doing the actions with the buttons.
- Drag the element to the right
- Once reached the defined distance the counter will increase extremely fast updating all the slides and eventually closing the modal.
Expected behavior
The drag should stop after reaching the condition (distance) and return to its original position updating the counter and the slide number.
Actual behaviour
The drag doesn't stop after reaching the condition (distance). It continues and therefore never returns to its original position, updates the counter extremely fast and the slide number.
I'm not sure if that's easy to implement. As a workaround, maybe this works:
if (400 > data.lastX && !this.state.disableDragging) {
this.setState({
...
disableDragging: true // disable here
});
....
this.prevStep();
e.dispatchEvent("ondragend"); // <<<<<<<<<<< dispatch event to trigger drag stop
}
if (500 > data.lastX && !this.state.disableDragging) {
...
this.setState({
...
disableDragging: true // disable here
});
...
e.dispatchEvent("ondragend");
}
Then, on handleStopDrag set disableDragging: false.
Stopping a user event programmatically is a bit difficult sometimes :P
I'm not sure if that's easy to implement. As a workaround, maybe this works:
if (400 > data.lastX && !this.state.disableDragging) { this.setState({ ... disableDragging: true // disable here }); .... this.prevStep(); e.dispatchEvent("ondragend"); // <<<<<<<<<<< dispatch event to trigger drag stop } if (500 > data.lastX && !this.state.disableDragging) { ... this.setState({ ... disableDragging: true // disable here }); ... e.dispatchEvent("ondragend"); }Then, on
handleStopDragsetdisableDragging: false.Stopping a user event programmatically is a bit difficult sometimes :P
This won't stop the current drag.
I don't know if this would be useful to someone, but I ended up editing the library to support what I call "custom bounds". Basically, this allows to limit the dragging operation to custom left / right / top / bottom values. Here is the patch-package file:
diff --git a/node_modules/react-rnd/.DS_Store b/node_modules/react-rnd/.DS_Store
new file mode 100644
index 0000000..ab1436d
Binary files /dev/null and b/node_modules/react-rnd/.DS_Store differ
diff --git a/node_modules/react-rnd/lib/index.js b/node_modules/react-rnd/lib/index.js
index 6d16a74..49b72b1 100644
--- a/node_modules/react-rnd/lib/index.js
+++ b/node_modules/react-rnd/lib/index.js
@@ -208,12 +208,14 @@ var Rnd = /** @class */ (function (_super) {
return;
this.updateOffsetFromParent();
var offset = this.offsetFromParent;
+ const { customTop, customRight, customBottom, customLeft } = this.props.customBounds || {};
+ const { x, y } = this.getDraggablePosition();
this.setState({
bounds: {
- top: top - offset.top,
- right: left + (boundary.offsetWidth - this.resizable.size.width) - offset.left / scale,
- bottom: top + (boundary.offsetHeight - this.resizable.size.height) - offset.top,
- left: left - offset.left / scale,
+ top: customTop !== undefined ? y - customTop : top - offset.top,
+ right: customRight !== undefined ? x + customRight : left + (boundary.offsetWidth - this.resizable.size.width) - offset.left / scale,
+ bottom: customBottom !== undefined ? y + customBottom : top + (boundary.offsetHeight - this.resizable.size.height) - offset.top,
+ left: customLeft !== undefined ? x - customLeft : left - offset.left / scale,
},
});
};
To use it, pass customBounds object to RND, for example:
<Rnd
...
customBounds={{ customLeft: 50, customRight: 50, customTop: 50, customBottom: 50 }}
>
</Rnd>