Drag & Drop at any position in the div

Asked

Viewed 230 times

1

How do I get the element that will be "dropped" to stay anywhere in my div? The way I’m doing it makes the elements align.

Follow image and code so far: inserir a descrição da imagem aqui

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");
  ev.target.appendChild(document.getElementById(data).cloneNode(true));
}
#etiqueta {
  width: 400px;
  height: 100px;
  padding: 10px;
  border: 1px solid #aaaaaa;
  margin: 0 auto;
}
#toolbox {
    
  width: 150px;
  height: 500px;
  padding: 10px;
  border: 1px solid #aaaaaa;
  position: absolute;
}
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script type="text/javascript" src="js/script.js"></script>
</head>
<body>

<div id="toolbox">
<ul>
    <label id ="lblDesc" draggable="true" ondragstart="drag(event)">@Descrição</label>
    <label id ="lblPrec" draggable="true" ondragstart="drag(event)">@Preço</label>
   <label id ="lblSku" draggable="true" ondragstart="drag(event)">@Sku</label>
</ul>
</div>    

<div id="etiqueta" ondrop="drop(event)" ondragover="allowDrop(event)">
    
</div>
<br>

</body>
</html>

1 answer

0

One of the ways to do this is by using the attribute position: absolute in his CSS. This way you can use a fixed value to position your element through the property left and top of CSS. The disadvantage may occur when the screen is resized.

To calculate and obtain the value of the horizontal distance, we will use the property clientX of the object ev. The estate clientY will give us the vertical position of the object.

However, this is not enough, because the captured value will be obtained based on the beginning of the object (and not from where it was clicked)

Imagem de uma bola com a posição Y e X desenhada

To correct this flaw, we’ll have to capture the position X and Y of the object and subtract with the position clientX and clientY, respectively. This way we will capture, more precisely, the initial point of the click mouse.

Once this is done, we just need to capture the final position of the mouse and subtract with the difference obtained above.

It seems a little complicated, but I’ll be leaving a code with the explanation of step by step.

Example:

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

function drag(ev) {
  ev.dataTransfer.setData("text", ev.target.id);
  
  /* Armanezaremos as coordenadas do evento */
  ev.dataTransfer.setData("left", ev.clientX);
  ev.dataTransfer.setData("top", ev.clientY);
}

function drop(ev) {
  ev.preventDefault();
  const data = ev.dataTransfer.getData("text");
  
  const clone = document.getElementById(data).cloneNode(true)
  clone.id = new Date().getMilliseconds()
  
  /**
   * Utilizamos esta função para capturar a posição
   * relativa do objeto ao viewport
   */
  const rect = document.getElementById(data).getBoundingClientRect()
  
  /**
   * Aqui, iremos obter a diferença entre a posição inicial
   * do mouse (ao ser pressionado) com a posição relativa
   * do objeto inicial.
   *
   * Este cálculo servirá para corrigir a posição final
   */
  let left = ev.dataTransfer.getData("left") - rect.left
  let top = ev.dataTransfer.getData("top") - rect.top
  
  /**
   * Finalmente iremos capturar a posição final do mouse
   * e corrigir com os valores acima
   */
  clone.style.left = `${ev.clientX - left}px`
  clone.style.top = `${ev.clientY - top}px`
  
  ev.target.appendChild( clone );
}
#etiqueta {
  width: 400px;
  height: 100px;
  padding: 10px;
  border: 1px solid #aaaaaa;
  margin: 0 auto;
}
#toolbox {
    
  width: 150px;
  height: 500px;
  padding: 10px;
  border: 1px solid #aaaaaa;
  position: absolute;
}
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

#etiqueta label { position: absolute }
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script type="text/javascript" src="js/script.js"></script>
</head>
<body>

<div id="toolbox">
<ul>
    <label id ="lblDesc" draggable="true" ondragstart="drag(event)">@Descrição</label>
    <label id ="lblPrec" draggable="true" ondragstart="drag(event)">@Preço</label>
   <label id ="lblSku" draggable="true" ondragstart="drag(event)">@Sku</label>
</ul>
</div>    

<div id="etiqueta" ondrop="drop(event)" ondragover="allowDrop(event)">
    
</div>
<br>

</body>
</html>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.