anseki / plain-draggable

The simple and high performance library to allow HTML/SVG element to be dragged.
https://anseki.github.io/plain-draggable/
MIT License
765 stars 96 forks source link

Recalculate the position of the dragged element after container/window resize #48

Closed frumbert closed 4 years ago

frumbert commented 4 years ago

If I drag an element and it snaps to an element that is itself positioned using relative units and then a resize event occurs, how can I modify the position of the draggable so that it matches the position of the snap element it snapped to (while retaining the ability to drag)? As you confirmed here there's no property storing the snap target nor the index of the this.snap.targets object - the index of the target would be great to get in places where the snapped property is set during events.

https://jsfiddle.net/frumbert/docr5mj7/

In your example, you just iterate the snap targets and match bounding boxes / coordinates and drag positions to find the particular target, which is fine for static objects. However during certain resize conditions it can become un-apparent which droppable object was snapped to which target so its position could be adjusted after resize.

anseki commented 4 years ago

Hi @frumbert, thank you for the comment. So, do you mean that you want to update the snap option?

frumbert commented 4 years ago

When you resized my example, you would have seen the dragged elements would no longer match the targets they had snapped to. I am seeking to correct the position of the dragged elements after the container resizes.

I'd like the element or elements that were snapped to a snap target to be able to have their difference in position calculated and updated to match the snap targets they last snapped to.

As the position of the dragged element has no relationship to the snapped element other than at the time the snap applies, and as the transform uses an absolute pixel unit rather than a relative unit such as rem/percentage, I need to be able to create that relationship myself somehow so the new positions can be calculated.

anseki commented 4 years ago

Do you mean that you want to get coordinates of the draggable element when it was snapped?

anseki commented 4 years ago

BTW, you can specify string as percentage (e.g. '30%') for snap.

frumbert commented 4 years ago

I have percentage / relative em values on the elements that the draggable snap to already.

Here is a new example of a box and a snap object.

https://jsfiddle.net/frumbert/z0tqpabc/

I want to be able to snap a draggable to an object however it is positioned. This is fine.

Then when the container everything is in resizes, I want the position of the draggable blue square to follow the position it already snapped to. If the transform was a relative/percentage this would work; but the transform is ab absolute pixel value.

I then want to still be able to move the draggable object around.

anseki commented 4 years ago

Do you mean that you want to know how to hook the resize event of the element? You can do that by using MutationObserver. For example: https://jsfiddle.net/bmy70oL3/

frumbert commented 4 years ago

Yes, this is similar to what I'm giong for - I wasn't asking how to hook an event - but using a mutation observer is clearly better than what I had in mind. Good tip! 👍

In your example there's a problem with the snapping if you make the container wider the box before you first move the draggable - it snaps to the initial line position, not the actual element line. You can see the blue square snapping in the wrong spot here:

snap

frumbert commented 4 years ago

Also, what happens if there are more than one snap target? How do I find out the offset to calculate if I only know that it was snapped - which "elmline" was it snapped to?

https://jsfiddle.net/frumbert/1vkajrez/3/

anseki commented 4 years ago

As I said in this comment and document, that means specifying four lines. https://github.com/anseki/plain-draggable/issues/26#issuecomment-484565305 Therefore, that snapping to original position of the line is correct behavior. Also, you can update snap when that is moved. For example: https://jsfiddle.net/4kd3r8jL/

anseki commented 4 years ago

Specifying coordinates as SnapTarget instead of the element is more better way because that is a convenient way instead of four lines. For example: https://jsfiddle.net/o8y059sv/

anseki commented 4 years ago

No reply came, then this abandoned issue is closed.

anseki commented 4 years ago

FYI, I don't know what is a problem for you, but the SnapOptions is recalculated by position() method, and also the method is called automatically when a window is resized (or a window or something is scrolled). That is, you have to do nothing basically. If you want to make the draggable element keep positioning with percentage coordinates, you can specify those by current position when dragging is ended. For example: https://jsfiddle.net/tk7vhyqL/