Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tilt/rotate the item being dragged in javascript drag and drop?

I want to tilt an item being dragged to show distinction. I have basic drag and drop fiddle here https://jsfiddle.net/igaurav/bqprc9p8/3/

My javascript looks like:

"use strict";

var source = null;

function listItemDragStartHandler(event){
    // What is true there for?
    source = event.currentTarget;
    event.dataTransfer.setData("text/plain", event.currentTarget.innerHTML);
    event.currentTarget.style.transform = 'rotate(15deg)';
    event.dataTransfer.effectAllowed = "move";
}

function dragoverHandler(event) {
    event.preventDefault();
    event.dataTransfer.dropEffect = "move";
}

function dropHandler(event) {
    event.preventDefault();
    event.stopPropagation();
    var currentElement = event.currentTarget;
    var listContainer = currentElement.parentNode;
    listContainer.insertBefore(source, currentElement);
    source.style.transform = 'rotate(0deg)';
}

function delete_item(event) {
    var currentTarget = event.currentTarget;
    var grandParentOfDelete = currentTarget.parentNode.parentNode;
    grandParentOfDelete.remove();
}

function add_item() {
    var item_text_node = document.getElementsByName("add-item-text")[0]
    var item_text = item_text_node.value;
    if (item_text.length > 0) {
        var item_template = document.getElementById("item-template");
        var item_clone = item_template.cloneNode(true);
        item_clone.removeAttribute("id");
        var clone_text = item_clone.getElementsByClassName("item-text")[0];
        clone_text.textContent = item_text;
        // reset the value
        item_text_node.value = "";
        var item_list = document.getElementById("item-list");
        item_list.appendChild(item_clone);
    } else {
        alert("No text?? Add some text!");
    }
}

function add_item_listener() {
    var add_item_button = document.getElementById("add-item");
    add_item_button.addEventListener("click", add_item);
}

function sample_data() {
    for(var i=0;i<10;i++){
        var item_text_node = document.getElementsByName('add-item-text')[0]
        item_text_node.value = i;
        add_item();
    }
}

function init_app() {
    add_item_listener();
    sample_data();
}

window.onload = function () {
    init_app()
}

Relevant HTML is:

<body>
    <div id="container">
        <div id="add-item-div">
            <input type="text" name="add-item-text">
            <button id="add-item">Add Item</button>
        </div>
        <div id="item-list">
        </div>
        <div id="item-template" class="item-list-element" draggable="true" ondragstart="listItemDragStartHandler(event);" ondrop="dropHandler(event);" ondragover="dragoverHandler(event);">
            <div class="item-text"></div>
            <div class="delete-item-div">
                <button class="delete-item" onclick="delete_item(event);">Delete Item</button>
            </div>
        </div>
    </div>
</body>

I am applying the transform on line 9 but the drag operation stops and drag doesn't start.

What am I doing wrong?

P.S: I don't want to use libraries.

like image 984
igauravsehrawat Avatar asked Apr 19 '17 08:04

igauravsehrawat


2 Answers

Basically, we can use setDragImage for replacing the browser implementation of the ghost image it is rendering for the dragging operation, with one of our own.

We use a cloned node as you do in the fiddle, and we add it to the dom.

Then, you can do the transformation on an inner container in the cloned element.

document.getElementById("drag-with-create-add").addEventListener("dragstart", function(e) {
    var crt = this.cloneNode(true);

    crt.style.position = "absolute"; 
    crt.style.top = "0px"; 
    crt.style.left = "-100px";
    
    var inner = crt.getElementsByClassName("inner")[0];
    inner.style.backgroundColor = "orange";
    inner.style.transform = "rotate(20deg)";
    
    document.body.appendChild(crt);
    e.dataTransfer.setDragImage(crt, 20, 20);
}, false);
<div id="drag-with-create-add" class="dragdemo" draggable="true">
  <div class="inner">
    drag me
  </div>
</div>

This is partly based on an helpfull article by Stuart Langridge.

Note: Trick here is to apply transformation on inner element and not on the one which has drag events. Transformation would appear only if applied to inner elements.

like image 194
elpddev Avatar answered Sep 18 '22 12:09

elpddev


I just created a sample fiddle. Which uses the setDragImage method, Please have a look and comment your needs so that we can upate the answer.

I have added a ghost image and added 'shake' feel while drag start. You can similarly rotate the dragging ghost image via css.

Also note, we are cloning the image while dragging to show ghost image. So we need to manually remove that from dom.

document.addEventListener("dragstart", function(e) {
  var img = document.createElement("img");
  img.src = "http://i.imgur.com/BDcvqmf.jpg";
  e.dataTransfer.setDragImage(img, 5000, 5000); //5000 will be out of the window
  drag(e)
}, false);

var crt, dragX, dragY;
//document.addEventListener('drag',drag)
function drag(ev) {
  crt = ev.target.cloneNode(true);
  crt.className = "face";
  crt.style.position = "absolute";
  crt.style.opacity = "0.9";
  document.body.appendChild(crt);
  ev.dataTransfer.setData("text", ev.target.id);
}

document.addEventListener("dragover", function(ev) {
  ev = ev || window.event;
  dragX = ev.pageX;
  dragY = ev.pageY;
  crt.style.left = dragX + "px";
  crt.style.top = dragY + "px";
}, false);

document.addEventListener("dragend", function(event) {
  crt.style.display = 'none';
  crt.remove()
});
body {
  padding: 10px
}

#draggable-element {
  width: 100px;
  height: 100px;
  background-color: #666;
  color: white;
  padding: 10px 12px;
  cursor: move;
  position: relative;
  /* important (all position that's not `static`) */
}

.face {
  animation: shake 1s cubic-bezier(.36, .07, .19, .97) both;
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
  perspective: 1000px;
}

@keyframes shake {
  10%,
  90% {
    transform: translate3d(-1px, 0, 0);
  }
  20%,
  80% {
    transform: translate3d(4px, 0, 0);
  }
  30%,
  50%,
  70% {
    transform: translate3d(-5px, 0, 0);
  }
  40%,
  60% {
    transform: translate3d(5px, 0, 0);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

See the tilt in action on drag start. <br>

<img draggable id="draggable-element" src="http://i.imgur.com/BDcvqmf.jpg">
like image 38
Rohith K P Avatar answered Sep 20 '22 12:09

Rohith K P