Open jarben opened 6 years ago
Thanks for your question! You should be able to use the Collidable plugin for that:
import {Sortable, Plugins} from '@shopify/draggable';
const sortable = new Sortable(containers, {
draggable: 'li',
collidables: 'body:not(.cant-move-out-of-this-element)'
});
The Collidable
plugin is still very simple and limited, but should give you the effect you want. For more information check out the docs about Collidable: https://github.com/Shopify/draggable/tree/master/src/Plugins/Collidable
Let me know if that worked for you
Hey @jarben - so you are looking for something that does not allow you to drag the mirror
outside of a container
(bounding box)? I suspect in this scenario the mirror
originates from within the container
, can be moved around within the container
, but cannot be moved OUTSIDE of the container
. Am I getting this right? Image example below showing the blue mirror unable to cross the black border container:
As @tsov mentioned - Collidable could be used for this... but it would be a different implementation than what I think you are looking for. Essentially (if I understand this correctly), you would need to have invisible elements on all sides of the container
that are the "collidables" with which your mirror
cannot cross.
I can see the possibility of extending the mirror
to allow for a constrainToParent
option (a boolean?) or a constrainToContainer
which could be any ancestor node passed to the property. @tsov and I will chat about this - not sure if we add something to the mirror
or expand on the capabilities of Collidable.
As an alternative, you could definitely code this logic within the drag:move
event. Basically, you would get the bounding box of the container
and compare the coordinates with your mouse position while moving around. Then, you could cancel the event or do something else to prevent the mirror from moving outside. The Intersection Observer API may also be your friend here.
Let us know if that makes sense! Cheers 😄
Hey @tsov & @beefchimi, thanks for your quick answers!
Yeah, the constrainToParent or constrainToContainer is exactly what I'm trying to achieve. Tried collidables on the parent container but that didn't seem to do the trick, I'll create an online JS fiddle and try to reproduce.
Good point around the drag:move event, will give it a try!
Regarding API design, it kind of makes sense to put it beside the xAxis/yAxis constraints doesn't it? Maybe a container property? Collidables feels a bit more external and related to drag source -> drag target (like shaking invalid target etc) so restricting mirror (source) might not fit into it.. not 100% sure thought!
Anyway, thanks again for your answers and this great library!!!
Hi! Would really love this feature as well. Could you please add it?
Also neither the collidable nor listening to drag:move
actually allows to solve the issue.
Where are we with this feature now? Any progress? Is there any more simple and straightforward way to achieve this than via a drag:move
handler?
In the meantime, this drag:move
handler has been working reasonably well for me:
draggableInstance.on('drag:move', (event) => {
let mirror = document.querySelector('.draggable-mirror')
let gameContainer = document.getElementById('game-container')
let bounds = gameContainer.getBoundingClientRect()
// To give a little extra room around the edges:
let boundsPaddingX = 50
let boundsPaddingY = 60
let minX = (bounds.x - boundsPaddingX) + (mirror.offsetWidth / 2)
let maxX = (bounds.x + bounds.width + boundsPaddingX) - (mirror.offsetWidth / 2)
let minY = (bounds.y - boundsPaddingY) + (mirror.offsetHeight / 2)
let maxY = (bounds.y + bounds.height + boundsPaddingY) - (mirror.offsetHeight / 2)
let ex = event.sensorEvent.clientX
let ey = event.sensorEvent.clientY
if (ex < minX || ex > maxX || ey < minY || ey > maxY) {
event.cancel()
}
})
It would be great if there is a plugin (or mirror option) that allows to constrain dragging inside a specific element. For example: