If you're looking for a JavaScript drag and drop library that provides snapping to grids, or need to make sure items can only be dropped in a specific zone, interact.js provides these capabilities out of the box!
You may come across a scenario where you need an item to be cloned when you start dragging it - e.g. if you are building a map creator that lets you drop multiple of the same icon onto it.
Check out the code below, or you can also view a working Codepen.
// This stores the position of the current item being dragged const position = { x: 0, y: 0 }; interact(".item") .draggable({ // By setting manualStart to true - we control the manualStart. // We need to do this so that we can clone the object before we begin dragging it. manualStart: true, listeners: { move(event) { position.x += event.dx; position.y += event.dy; event.target.style.transform = `translate(${position.x}px, ${position.y}px)`; } } }) // This only gets called when we trigger it below using interact.start(...) .on("move", function(event) { const { currentTarget, interaction } = event; let element = currentTarget; // If we are dragging an item from the sidebar, its transform value will be '' // We need to clone it, and then start moving the clone if ( interaction.pointerIsDown && !interaction.interacting() && currentTarget.style.transform === "" ) { element = currentTarget.cloneNode(true); // Add absolute positioning so that cloned object lives // right on top of the original object element.style.position = "absolute"; element.style.left = 0; element.style.top = 0; // Add the cloned object to the document const container = document.querySelector(".container"); container && container.appendChild(element); const { offsetTop, offsetLeft } = currentTarget; position.x = offsetLeft; position.y = offsetTop; // If we are moving an already existing item, we need to make sure // the position object has the correct values before we start dragging it } else if (interaction.pointerIsDown && !interaction.interacting()) { const regex = /translate\(([\d]+)px, ([\d]+)px\)/i; const transform = regex.exec(currentTarget.style.transform); if (transform && transform.length > 1) { position.x = Number(transform[1]); position.y = Number(transform[2]); } } // Start the drag event interaction.start({ name: "drag" }, event.interactable, element); });
Top comments (1)
Thanks! Very useful!