1

I have a picture that when I drag it to the red circle it copies. I want it so it stays where it is copied, not snap to the upper-left corner. How do I do this?

HTML:

<span class="box" ondrop="drop(event)" ondragover="allowDrop(event)"></span>
<br />
<div id="picture" ondrop="drop(event)">
   <img src="https://www.w3schools.com/html/img_w3slogo.gif" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
</div>

CSS:

.box {
   display: block;
   height: 300px;
   width: 300px;
   background-color: red;
}

JavaScript:

function allowDrop(ev) {
   ev.preventDefault();
}

function drag(ev) {
   ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
   ev.preventDefault();
   var data = ev.dataTransfer.getData("text");
   var nodeCopy = document.getElementById(data).cloneNode(true);
   nodeCopy.id = "newId";
   ev.target.appendChild(nodeCopy);
}

Or see a TryIt here: https://www.w3schools.com/code/tryit.asp?Filename=GBY2BVYBXUPW

mattywelch
  • 49
  • 1
  • 9

1 Answers1

2

The events have variables you can use.

In this example im using x and y and im positioning the image with absolute position with this line of code

 nodeCopy.setAttribute("style", "position:absolute; left:"+ ev.x +"px;top:"+ ev.y+"px");

function allowDrop(ev) {
  ev.preventDefault();
}

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
}

function drop(ev) {
  ev.preventDefault();
  var data = ev.dataTransfer.getData("text");
  var nodeCopy = document.getElementById(data);
  if (nodeCopy.classList.contains('insideBox')){
    nodeCopy.setAttribute("style", "position:absolute; left:"+ ev.x +"px;top:"+ ev.y+"px;transform:translate(-"+nodeCopy.width/2+"px,-"+nodeCopy.height/2+"px)");
    }
    else{
      nodeCopy=nodeCopy.cloneNode(true)
      nodeCopy.classList.add("insideBox");
      nodeCopy.id = "newId"+Math.random(100);
      nodeCopy.setAttribute("style", "position:absolute; left:"+ ev.x +"px;top:"+ ev.y+"px;transform:translate(-"+nodeCopy.width/2+"px,-"+nodeCopy.height/2+"px)");
      ev.target.appendChild(nodeCopy);
    }

}
*{
  margin:0;
  padding:0;
}     
.box {
  display: block;
  height: 300px;
  width: 300px;
  background-color: red;
}
<span class="box" ondrop="drop(event)" ondragover="allowDrop(event)"></span>
 <br />
  <div id="picture" ondrop="drop(event)">
      <img src="https://www.w3schools.com/html/img_w3slogo.gif" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
  </div>
German
  • 36
  • 2
  • Thanks! You're awesome! It always snaps to the upper left corner where the mouse is though. Is there a way to make it so it goes exactly where the mouse is? Also, is there a way to make it so it only copies from outside the box and if it's dragged around inside the box, it moves? Thanks again! – mattywelch Feb 16 '20 at 11:58
  • Thanks, that's terrific! One last thing, can you make it so it moves if it's from already in the red box but it copies when it is from outside of the red box? – mattywelch Feb 16 '20 at 17:25
  • I did it in the original snippet but i do not recommend to use it. Just use it as example on how its done – German Feb 16 '20 at 19:05
  • Okay, I will look into it. Thanks for all your help! – mattywelch Feb 17 '20 at 13:10
  • I know I already said "one last thing" but is there any chance that you can also make this work for mobile as well? I'm trying to avoid jQuery and other libraries and I'd like to use the touchmove, touchstart, and similar events to accomplish this. From my understanding, you need both the drag events and the touch events in order for it to work for desktop AND mobile? Thanks in advance! – mattywelch Feb 18 '20 at 21:17
  • Drag and drop doesnt work on mobile, you need to use a external library – German Feb 18 '20 at 23:30
  • What about touchmove? See: https://www.w3schools.com/jsref/event_touchmove.asp – mattywelch Feb 20 '20 at 12:59