If you drag an autoscroll-enabled draggable beyond the visible area of the div, the container should scroll and the draggable should be at the same position as the mouse is.
The draggable is stuck at the same place and does not follow the mouse pointer, the container scrolls. Here you can see the behaviour: https://jsfiddle.net/y4e7nqw6/4/ .
interact.js version: 1.3.0
Browser name and version: Chrome version 63.0.3239.84
Operating System: Ubuntu 16.04
Seems to me slightly different from #298 and #38 .
I'm having this exact same problem. From reading into the old issues from the past few years, it sounds like @taye isn't keen on addressing this (you linked to the issues); however, finding a decent solution around this would really help.
@taye if this is something that you want to bake into the project, I'm happy to take a stab at a PR if I can get a little guidance on what you envision
@micvm setting position:absolute on draggable elements should work for you in this case.
@vinaynb is right. In that jsfiddle, if you add
target.style.position = 'absolute';
to dragMoveListener, then it works.
But I don't know why.
@vinaynb but if a parent container has position: relative on it, then the same breaking behavior happens. Here is a fiddle of that:
https://jsfiddle.net/kb645t4a/
_Edit: naturally, using fixed would make it relative to the page..._
Regardless, I'm working with a scenario with multiple nested overflows and stacking contexts (transform on parents), so fixed wouldn't work anyway. I found a way to calculate the (x, y) position for the draggable items' translate function, but it looks like the internal tracking which allows for a draggable item to enter a dropzone is confused by autoScroll, as well.
I'm going to dig in to this project and see what I can come up with, unless @taye has a better idea. :)
Perhaps some version of https://github.com/taye/interact.js/issues/38#issuecomment-47808652 might help...
Thanks for your replies @vinaynb and @rpearce . Concerning the position: absolute rule it works in the jsfiddle I provided. However, if you afterwards try to scroll the container, you will see the draggable does not scroll and instead stays at the same place.
In my original code even position:absolute does not work. I will try to investigate why it is the case and post a better jsfiddle that might maybe help for analyzing.
Ok, now I updated the fiddle https://jsfiddle.net/y4e7nqw6/5/ : I changed the position of the draggable to absolute as suggested. The change that affects the functionality in my original code is that the innermost container's position is relative in my original code. In that case as you can see it does not scroll as expected and the mentioned unexpected behavior arises.
It still feels like autoScroll should trigger the move event, and the math doesn't seem too crazy (a super na茂ve concept pseudo-code for the y axis):
const scrollableContainer = document.querySelector('.someSelector')
const isDragging = areWeDragging() // something that gets set when dragstart happens
let y = yValueFromDragMove() // something that gets set when dragmove happens
let yBefore = 0
let yAfter = 0
scrollableContainer.addEventListener('scroll', e => {
yBefore = yAfter
yAfter = e.currentTarget.scrollTop
if (isDragging) {
y = y + (yAfter - yBefore)
}
})
The part of this that matters is that you
y axisy should be accordinglyI did this on my side to calculate the transform amount(s) which worked, BUT the internal (x,y) tracking seems to get messed up and makes dropzones whack. 馃槶
@micvm Update: nothing yet, but I'm going to try for another day or so to try to fix this in the project (not sure if that's possible yet).
https://github.com/taye/interact.js/issues/353 is similar, as well
Update: Combining that hacky scroll logic above with interact.dynamicDrop lets me bypass this problem for now.
@rpearce Thanks to your suggestion I managed to have something working and yes... it is definitely hacky what I've done here and I did not check any possible case :) I share it anyway in case it might be helpful for others:
var currentDraggable=null; //this is set and unset on the startDrag and endDrag of the draggable
var beforeY=0,beforeX=0; //these are both reset to 0 on endDrag
var afterY=0,afterX=0; //these are both reset to 0 on endDrag
interact(document.getElementById('container')).on('scroll', function () {
if (!currentDraggable) { return; }
beforeY=afterY;
beforeX=afterX;
if(afterY==0 && beforeY==0) //needed because otherwise it works only if you scroll the first time
beforeY=this.scrollTop;
if(afterX==0 && beforeX==0) //needed because otherwise it works only if you scroll the first time
beforeX=this.scrollLeft;
afterY=this.scrollTop;
afterX=this.scrollLeft;
var y = (parseFloat(currentDraggable.getAttribute('data-y')) || 0) + (afterY-beforeY);
var x = (parseFloat(currentDraggable.getAttribute('data-x')) || 0) + (afterX-beforeX);
// translate the element
currentDraggable.style.webkitTransform = currentDraggable.style.transform ='translate(' + x + 'px, ' + y + 'px)';
// update the position attributes
currentDraggable.setAttribute('data-x', x);
currentDraggable.setAttribute('data-y', y);
});
Update: I can confirm that dynamicDrop fixes the problem of the droppables also here after scrolling the draggable.
@micvm do you happen to have an updated JSFiddle you could share for others in the future?
Sure. Here it is: https://jsfiddle.net/a3na7hf0/2/
What bothers me are that "state" variables and the fact that I have to set the currentDraggable via dragStart and dragEnd listeners. Probably that works much easier via native interact.js api but I could not find in the docs how. As you can see there is room for improvement :)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Most helpful comment
Sure. Here it is: https://jsfiddle.net/a3na7hf0/2/
What bothers me are that "state" variables and the fact that I have to set the currentDraggable via dragStart and dragEnd listeners. Probably that works much easier via native interact.js api but I could not find in the docs how. As you can see there is room for improvement :)