Interact.js: dragging in scaled elements

Created on 18 Dec 2014  Â·  17Comments  Â·  Source: taye/interact.js

What happens: When the draggable element is child of a scaled element (like transform: scale(2);) the draggable element has an offset while dragging: It moves faster (scale>1) or slower (scale<1)than the cursor.
What should/could happen: Even if it is child of a scaled element, the draggable element could be normally draggable.

Use cases: Applications in which Elements are arranged; adjustment of element size to available space.

Existing Implementations: jsPlumb uses a model in which the programmer registers changes of the scale factor of the container element: https://jsplumbtoolkit.com/doc/zooming.html

wontfix

Most helpful comment

I've been thinking about transformations for a while (#90) but I've been unsure of the best way to go about it. Initially I was planning on having a method that takes an object similar to the DOMMatrix/SVGMatrix but that _might_ be too complicated. I don't know how useful it would be useful to consider translation and rotation. I'll try a few things out and then get back to you on that.

For now, you'd have to divide the event coordinates by the scale values.

interact(target).on('dragmove', function (event) {
  var scale = /* get the scale */
      x = event.pageX / scale,
      y = event.pageY / scale;

  // use x and y instead of event.pageX and event.pageY
});

All 17 comments

I've been thinking about transformations for a while (#90) but I've been unsure of the best way to go about it. Initially I was planning on having a method that takes an object similar to the DOMMatrix/SVGMatrix but that _might_ be too complicated. I don't know how useful it would be useful to consider translation and rotation. I'll try a few things out and then get back to you on that.

For now, you'd have to divide the event coordinates by the scale values.

interact(target).on('dragmove', function (event) {
  var scale = /* get the scale */
      x = event.pageX / scale,
      y = event.pageY / scale;

  // use x and y instead of event.pageX and event.pageY
});

Any news about this issue? I cannot use the fix with dividing by scale.

@marian-r There's been no development yet. The solution that I have in mind would involve the programmer supplying the scale of the element – the scale of the element would not be gotten automatically by interact.js – so it would just be a small convenience to avoid doing the calculations in every event listener.

I understand that this approach has some advantages and actually, I am using it now. However, it cannot be used in every situation, so it would be nice if we found a better solution.

I think providing the scale manually is fine, as long as the dragging is than handled in the "correct" (scale is taken in consideration) way.
jsplumb has this approach in their handling of zoom too: It takes care of dragging in a scaled element as long as the scale is provided as far as I remember.
Needed Code from the programmers side is usually triggering a custom "scaled" event after scaling the "outer" element. A provide-scale-to-dragging-framework function listened this event. All this is about ~8 lines of code without any magic. (less flexible: just hardcode the provide-scale function)

I've run into this problem. The dragging speed is fixed by dividing by the scale, but I still have the problem that it isn't possible to drag to the edges of the element when the constrain has been zoomed in with CSS scale transform. The more the element is zoomed the longer from the edge it possible to navigate to. Is seems as if the restriction values inside interact.js need to be updated after zooming/scaling the constrain container. Any help would be much appreciated.

Right, so nevermind my last comment, I was using a constrain div to do the drag restriction, but it wasn't updated properly when it was scaled. Instead of using a parent restriction I've used a function to compute the restriction rectangle.

Just to let you know that the problem exists with any kind of transformation on any parent.
Try dragging something if the parent has a rotation, it's pretty funny :)

Haha, yeah. Also when doing both scale and translate it helps to set the transformation origin, it's all about wrapping your head around the transformation matrix which easily can make your head spin.

For the record, I think gsap is the only library i know to get it right :
http://codepen.io/gavrochelegnou/pen/KpWVqo

@lauritzen I'm also using a function to compute the restriction but with no luck.
Could you show me your code?

restrict: {
    restriction: function(x, y, element) {
        // important to use getBoundingClientRect as the element might be scaled
        var rect = element.getBoundingClientRect();
        var dw = rect.width,
            dh = rect.height,
            vw = $(window).width(),
            vh = $(window).height();

        var restriction = {
            top: vh-dh < 0 ? vh-dh : 0,
            left: vw-dw < 0 ? vw-dw : 0,
            width: dw > vw ? Math.max(2*dw-vw, vw) : vw,
            height: dh > vh ? Math.max(2*dh-vh, vh) : vh
        };

        return {
            left: restriction.left,
            right: restriction.left + restriction.width,
            top: restriction.top,
            bottom: restriction.top + restriction.height
        };
    },
    endOnly: true,
    elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},

We are using interact.js to navigate on a drawing a bit like Google Maps.

Nice, thanks a lot! :)

I'm not personally interested in working on this. With the recent improvements to the codebase it should be much easier for someone else to contribute a module that does this and I might be able to offer some time to help and improve the module interfaces. I'm closing this issue as a wontfix.

for those who might want to work on this: snap.js has a drag function that works even in transformed elements, as far as I could see.

Ref @lauritzen solution above: anyone trying to use this code, note that the restriction() callback has apparently changed since 2015. The third parameter is no longer an element, but an Interaction object.

I can't tell if this is fixed or still a wontfix?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

itmaor picture itmaor  Â·  4Comments

Tlapi picture Tlapi  Â·  6Comments

kongaraju picture kongaraju  Â·  6Comments

freefalling picture freefalling  Â·  3Comments

jbaartman picture jbaartman  Â·  4Comments