EzDevInfo.com

interact.js

JavaScript drag and drop, resizing and multi-touch gestures with inertia and snapping for modern browsers (and also IE8+) interact.js - JavaScript drag and drop, resizing and gestures with inertia and snapping

interact.js dragged item move on top

it's my first time to use this plugin.

I want to add a stacking of elements whenever it's dragged. I use z-index and position relative.

    onstart: function (event) {

    //get max z-index on page   
      var maxZ = Math.max.apply(null, 
      $.map($('body > *'), function(e,n) {
        if ($(e).css('position') != 'static')
          return parseInt($(e).css('z-index')) || 1;
      }));

        event.target.style.background = 'red';
        event.target.style.zIndex = maxZ + 1; 
        event.target.style.position = 'relative'; 
    },

Is there more efficient way to do this?

original drag and drop demo

my edited drag and drop demo with stacking


Source: (StackOverflow)

Can't drag-n-drop from sidebar to dropzone

i want to achieve the following. I have an off-canvas left sidebar using ui-kit and for drag-n-drop i'm using interact. I want to drag elements from sidebar to drop zone with id #inner-dropzone . What is preventing me to achieve this? I've tried removing z-index on left sidebar and also overflow-y: hidden. Is this related to css rules, or restrictions on interact api?

restrict: {
  restriction: "inner-dropzone",
  endOnly: true,
  elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},

Current implementation codepen.io


Source: (StackOverflow)

Advertisements

How to find original location of an image?

I am using the interact.js library for drag/drop functionality. I'm using raw images instead of divs as my draggable objects and this seems to work fine:

<img id="drag4" src="images/SVG/ksTire.svg" class="draggable js-drag" style="width:85px">

I cannot figure out how to return an image back to its original starting point before the drag began. I need to store the original coords in a js variable, and depending on certain events, return the image back to its exact original starting location. I experimented with various x/y coordinates on the event, and tried getElementById also, with no luck. Whenever I try to return the image back to its original location, some approaches will bring it back the first time, but then when I begin to drag it again, it's way off in a strange place, not under the mouse pointer anymore.

Could someone please provide a bit of sample code showing how to constantly snap a draggable object back to its initial location? I already figured out the places in code where to call this, all I need is how to get images back to the right place, and then to continue to behave properly after that occurs.

Note: interact.js isn't built on jquery, so I'd prefer a non-jquery solution in this particular case.

Here is the full contents of my dropzone.js, which is where most of the pertinent stuff happens related to this issue:

(function(interact) {

    'use strict';

    var transformProp;
    var startPos = null;
    var startX = 0;
    var startY = 0;
    var validDrop = false;

    interact.maxInteractions(Infinity);

    // setup draggable elements.


    /* block below was copied from https://github.com/taye/interact.js/issues/79 -- try to get this working */

    // setup drop areas.

    setupDropzone('#drop1', '#drag1, #drag2, #drag4');
    setupDropzone('#drop2', '#drag4');
    setupDropzone('#drop4', '#drag4');
    setupDropzone('#drop5', '#drag1, #drag2, #drag4');
    setupDropzone('#drop6', '#drag3');
    setupDropzone('#drop7', '#drag1');


    /* SNAP code was copied from http://kundprojekt.soonce.com/lintex/zonbuilder/ and https://github.com/taye/interact.js/issues/79 -- try to get this working */

    // dropzone #1 accepts draggable #1
    //setupDropzone('#drop1', '#drag1');
    // dropzone #2 accepts draggable #1 and #2
    //setupDropzone('#drop2', '#drag1, #drag2');
    // every dropzone accepts draggable #3
    //setupDropzone('.js-drop', '#drag3');

    /**
     * Setup a given element as a dropzone.
     *
     * @param {HTMLElement|String} el
     * @param {String} accept
     */
    function setupDropzone(el, accept) {
        interact(el)
            .dropzone({
                accept: accept,
                ondropactivate: function(event) {
                    addClass(event.relatedTarget, '-drop-possible');
                },
                ondropdeactivate: function(event) {
                    removeClass(event.relatedTarget, '-drop-possible');
                }
            })
            .snap({
                mode: 'anchor',
                anchors: [],
                range: Infinity,
                elementOrigin: {
                    x: 0.5,
                    y: 0.5
                },
                endOnly: true
            })
            .on('dropactivate', function(event) {
                var active = event.target.getAttribute('active') | 0;

                // change style if it was previously not active
                if (active === 0) {
                    addClass(event.target, '-drop-possible');
                    //event.target.textContent = 'Drop me here!';
                }

                event.target.setAttribute('active', active + 1);
            })
            .on('dropdeactivate', function(event) { // this fires after each drop, whether a drop into a valid drop zone occurs or not
                var active = event.target.getAttribute('active') | 0;

                // change style if it was previously active
                // but will no longer be active
                if (active === 1) {
                    removeClass(event.target, '-drop-possible');
                    //event.target.textContent = 'Dropzone';
                }

                event.target.setAttribute('active', active - 1);

                if (!validDrop) {
                    //document.getElementById("drag4").style.position = 'absolute';
                    //document.getElementById("drag4").style.left = startX + "px";
                    //document.getElementById("drag4").style.top = startY + "px";
                }

            })

        .on('dragstart', function(event) {
            // snap to the start position

            if (!startPos) {
                var rect = interact.getElementRect(event.target);

                // record center point when starting the very first a drag
                startPos = {
                    x: rect.left + rect.width / 2,
                    y: rect.top + rect.height / 2
                }
            }
            event.interactable.snap({
                anchors: [startPos]
            });
        })
        .on('dragenter', function(event) {
                addClass(event.target, '-drop-over');


                var dropRect = interact.getElementRect(event.target),
                    dropCenter = {
                        x: dropRect.left + dropRect.width / 2,
                        y: dropRect.top + dropRect.height / 2
                    };

                event.draggable.snap({
                    anchors: [dropCenter]
                });


                //event.relatedTarget.textContent = 'I\'m in';
            })
            .on('dragleave', function(event) {
                removeClass(event.target, '-drop-over');

                event.draggable.snap(false);

                // when leaving a dropzone, snap to the start position
                event.draggable.snap({
                    anchors: [startPos]
                });

                var svgFilename = getSVGFilename(event.relatedTarget.src);

                if (document.getElementById("message").innerHTML) {
                    document.getElementById("message").innerHTML = document.getElementById("message").innerHTML.replace(svgFilename + "<br>", "");
                }

                //event.relatedTarget.textContent = 'Drag me…';
            })
            .on('drop', function(event) { // this only fires when an object is dropped into a valid drop zone for that object
                validDrop = true;
                removeClass(event.target, '-drop-over');
                var svgFilename = getSVGFilename(event.relatedTarget.src);
                document.getElementById("message").innerHTML += svgFilename + "<br>";

                //event.relatedTarget.textContent = 'Dropped';
            });
    }

    function getAbsolutePosition(el) {
        var el2 = el;
        var curtop = 0;
        var curleft = 0;
        if (document.getElementById || document.all) {
            do {
                curleft += el.offsetLeft - el.scrollLeft;
                curtop += el.offsetTop - el.scrollTop;
                el = el.offsetParent;
                el2 = el2.parentNode;
                while (el2 != el) {
                    curleft -= el2.scrollLeft;
                    curtop -= el2.scrollTop;
                    el2 = el2.parentNode;
                }
            } while (el.offsetParent);

        } else if (document.layers) {
            curtop += el.y;
            curleft += el.x;
        }
        return [curleft, curtop];
    };

    function getSVGFilename(url) {
        if (url.indexOf("/") > -1)
            return url.substr(url.lastIndexOf('/') + 1);
        else
            return "";
    }

    function addClass(element, className) {
        if (element.classList) {
            return element.classList.add(className);
        } else {
            element.className += ' ' + className;
        }
    }

    function removeClass(element, className) {
        if (element.classList) {
            return element.classList.remove(className);
        } else {
            element.className = element.className.replace(new RegExp(className + ' *', 'g'), '');
        }
    }

    interact('.js-drag')
        .draggable({
            max: Infinity
        })
        .on('dragstart', function(event) {
            validDrop = false;

            event.interaction.x = parseInt(event.target.getAttribute('data-x'), 10) || 0;
            event.interaction.y = parseInt(event.target.getAttribute('data-y'), 10) || 0;

            var absolutePosition = getAbsolutePosition(event.target);
            startX = absolutePosition[0];
            startY = absolutePosition[1];

        })
        .on('dragmove', function(event) {
            event.interaction.x += event.dx;
            event.interaction.y += event.dy;

            if (transformProp) {
                event.target.style[transformProp] =
                    'translate(' + event.interaction.x + 'px, ' + event.interaction.y + 'px)';
            } else {
                event.target.style.left = event.interaction.x + 'px';
                event.target.style.top = event.interaction.y + 'px';
            }
        })
        .on('dragend', function(event) {
            event.target.setAttribute('data-x', event.interaction.x);
            event.target.setAttribute('data-y', event.interaction.y);
        });

    interact(document).on('ready', function() {
        transformProp = 'transform' in document.body.style ? 'transform' : 'webkitTransform' in document.body.style ? 'webkitTransform' : 'mozTransform' in document.body.style ? 'mozTransform' : 'oTransform' in document.body.style ? 'oTransform' : 'msTransform' in document.body.style ? 'msTransform' : null;
    });

}(window.interact));

And here is my base html file:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <title>WorkScreen Prototype #1</title>
   <script src="js/interact.js"></script>
   <script src="js/dropzones.js"></script>
   <link rel="stylesheet" rel='nofollow' href="css/dropzones.css">
</head>
<body style="background-color: #CCC; height: 852px">
   <a rel='nofollow' href="ShowSVGs.aspx" target="_blank">View All SVGs</a>
   <div style="margin-top:55px">
      <div style="float: left; vertical-align: top">
         <img id="drag1" src="images/SVG/ksBatteryBox.svg" class="draggable js-drag" style="width:80px"><br />
         <img id="drag2" src="images/SVG/ksBumper6308700.svg" class="draggable js-drag" style="width:85px"><br />
         <img id="drag3" src="images/SVG/ksHood8090130.svg" class="draggable js-drag" style="width:165px"><br />
         <img id="drag4" src="images/SVG/ksTire.svg" class="draggable js-drag" style="width:85px"><br />
      </div>
      <div style="float: left;vertical-align:top;margin-left:-72px">
         <div style ="margin-left:100px;">

            <div id="drop1" class="dropzone js-drop" style="margin-left:186px;"></div>
            <div id="drop2" class="dropzone js-drop" style="margin-left:90px"></div>

            <div style="">
               <div id="drop6" class="dropzone js-drop" style="clear: both; margin-left: 0px; margin-top: 37px"></div>
               <div style="float:left"><img src="images/BaseTruck.png" /></div>
               <div id="drop7" class="dropzone js-drop" style="float: left; margin-left: 251px; margin-top: 153px; position: absolute;"></div>
               <div id="drop3" class="dropzone js-drop" style="float:left; margin-left:10px;margin-top:37px"></div>
            </div>

            <div id="drop5" class="dropzone js-drop" style="clear: both; margin-left: 186px;"></div>
            <div id="drop4" class="dropzone js-drop" style="margin-left: 90px;"></div>

            <br /><br />
            <div id="message" style="clear: both; margin-left: 0px; margin-top: 44px; width: 245px; display: inherit; border: 2px solid gray; padding: 7px;"></div>

         </div>
      </div>
   </div>
</body>
</html>

Source: (StackOverflow)

Overlap issue using interact.js when scaling

Take a look at this

I'm using this function to drag the object around into his parent and drag it back whenever it overlap the parent:

// target elements with the "draggable" class
interact('.draggable')
.draggable({
// enable inertial throwing
inertia: true,
// keep the element within the area of it's parent
restrict: {
  restriction: "parent",
  endOnly: true,
  elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},

// call this function on every dragmove event
onmove: function (event) {
  var target = event.target,
      // keep the dragged position in the data-x/data-y attributes
      x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
      y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

  // translate the element
  target.style.webkitTransform =
  target.style.transform =
    'translate(' + x + 'px, ' + y + 'px)';

  // update the posiion attributes
  target.setAttribute('data-x', x);
  target.setAttribute('data-y', y);
}
});

The problem is that the "drag back when overlap parent" thing works fine if I drag it manualy. But if you animate the div in the fiddle from that position (close to the parent's edge) it overlap it and it doesn't come back because that function that brings it back is set to run only onmove:. How do I take out that function to trigger it whenever I want?

Plugin Page


Source: (StackOverflow)

Object snaps to old top (InteractJs)

I am using InteractJs and I almost have it working but when I put the star on a tree that was small before it goes to the top of the small tree.

So when you drag the star on a tree the other trees get smaller. When you drag it to another tree the trees get normal height again but the star goes to the top of the small tree height that it used to be.

    interact('.draggable')
    .draggable({
        onmove: function (event) {
            var target = event.target,
                x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
                y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

            target.style.webkitTransform =
            target.style.transform =
                'translate(' + x + 'px, ' + y + 'px)';

            target.setAttribute('data-x', x);
            target.setAttribute('data-y', y);
        },
        onend: function (event) {
            var textEl = event.target.querySelector('p');

            textEl && (textEl.textContent =
                'moved a distance of '
                + (Math.sqrt(event.dx * event.dx +
                             event.dy * event.dy)|0) + 'px');
        }
    })
    .inertia(true)
    .restrict({
        drag: "parent",
        endOnly: true,
        elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
    });

interact('.draggable').snap({
      mode: 'anchor',
      anchors: [],
      range: Infinity,
      elementOrigin: { x: 0.5, y: 2 },
      endOnly: true
});

// enable draggables to be dropped into this
interact('.tree').dropzone({
    // only accept elements matching this CSS selector
    accept: '#star',
    // Require a 75% element overlap for a drop to be possible
    overlap: 0.75,

    // listen for drop related events:

    ondropactivate: function (event) {
        // add active dropzone feedback
        event.target.classList.add('drop-active');

    },
    ondragenter: function (event) {
        var draggableElement = event.relatedTarget,
            dropzoneElement = event.target;

        // feedback the possibility of a drop
        clearInterval(interval); // stop star rotation
        dropzoneElement.classList.add('drop-target');
        draggableElement.classList.add('can-drop');
        $('.tree:not(.drop-target)').find('img').animate({
            opacity: .5,
            height: "160px"
            });
        var dropRect = interact.getElementRect(event.target),
            dropCenter = {
              x: dropRect.left + dropRect.width  / 2,
              y: dropRect.top  + dropRect.height / 2
            };

        event.draggable.snap({
          anchors: [ dropCenter ]
        });

    },
    ondragleave: function (event) {
        var draggableElement = event.relatedTarget,
            dropzoneElement = event.target;
        // remove the drop feedback style
        event.target.classList.remove('drop-target');
        event.relatedTarget.classList.remove('can-drop');
        $('.tree:not(.drop-target)').find('img').animate({
            opacity: 1,
            height: "186px"
            });

        event.draggable.snap(false);
    },
    ondrop: function (event) {
        //Dropped event
    },
    ondropdeactivate: function (event) {
        // remove active dropzone feedback
        event.target.classList.remove('drop-active');
        event.target.classList.remove('drop-target');
    }
})

//Start star rotation
var angle = 0;
var interval = setInterval(function(){
    angle+=1;
    $("#star img").rotate(angle);
},50)

jsfiddle: http://jsfiddle.net/hpq7rpnh/4/

Library: http://interactjs.io/


Source: (StackOverflow)