HTML5 Drag and Drop в любом месте экрана - PullRequest
37 голосов
/ 03 июня 2011

У меня есть журнал отладчика, который я написал на JavaScript для проекта, над которым я работаю. Журнал в основном является тегом <aside> в HTML5, который отображается только при необходимости. Я хотел поиграть с идеей возможности перемещать журнал по экрану, так как он может перекрывать определенные вещи (что хорошо для моего проекта). Однако я не могу понять, как использовать HTML5 для правильного перетаскивания тега, чтобы его можно было разместить в любом месте экрана (ну или внутри элемента <div>).

После прочтения поддержки перетаскивания в HTML5 у меня есть общее представление о том, как это работает, но я не уверен, с чего начать, когда нужно разрешить размещение div где угодно (его z-index является высоким значение, так как я уже сказал, перекрытие в порядке).

Есть предложения?

О, и я бы хотел, по возможности, избегать использования внешних библиотек для этого проекта. Я пытаюсь сделать это на чистом JavaScript / HTML5.

Ответы [ 3 ]

103 голосов
/ 05 июня 2011

Перетаскивание не перемещает элементы, если вы хотите, чтобы элемент перемещался при его перетаскивании, вам нужно установить новую позицию элемента в событии перетаскивания.Я сделал пример , который работает в Firefox и Chrome, вот ключевые моменты:

function drag_start(event) {
    var style = window.getComputedStyle(event.target, null);
    event.dataTransfer.setData("text/plain",
    (parseInt(style.getPropertyValue("left"),10) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top"),10) - event.clientY));
} 

Событие dragstart определяет смещение указателя мыши слеваи верх элемента и передает его в dataTransfer.Я не беспокоюсь о передаче идентификатора, потому что на странице есть только один перетаскиваемый элемент - без ссылок или изображений - если у вас есть какой-либо из этих элементов на вашей странице, вам придется проделать здесь немного больше работы.

function drop(event) {
    var offset = event.dataTransfer.getData("text/plain").split(',');
    var dm = document.getElementById('dragme');
    dm.style.left = (event.clientX + parseInt(offset[0],10)) + 'px';
    dm.style.top = (event.clientY + parseInt(offset[1],10)) + 'px';
    event.preventDefault();
    return false;
}

Событие drop распаковывает смещения и использует их для позиционирования элемента относительно указателя мыши.

Событию dragover просто нужно preventDefault, когда что-либо перетаскивается.Опять же, если на странице есть еще что-то перетаскиваемое, вам может потребоваться сделать что-то более сложное здесь:

function drag_over(event) {
    event.preventDefault();
    return false;
} 

Так что свяжите это с document.body вместе с событием drop, чтобы захватить все:

var dm = document.getElementById('dragme');
dm.addEventListener('dragstart',drag_start,false);
document.body.addEventListener('dragover',drag_over,false);
document.body.addEventListener('drop',drop,false); 

Если вы хотите, чтобы это работало в IE, вам необходимо преобразовать aside в a элемент, и, конечно, весь код привязки события будет другим.Насколько мне известно, API перетаскивания не работает ни в Opera, ни в любых мобильных браузерах.Кроме того, я знаю, что вы сказали, что не хотите использовать jQuery, но кросс-браузерная привязка событий и манипулирование позициями элементов - это то, что jQuery делает намного проще.

6 голосов
/ 22 марта 2016

Я немного подкорректировал robertc отличный ответ для случаев с несколькими предметами. Здесь имя класса second просто для другой позиции.

<aside draggable="true" class="dragme" data-item="0">One</aside>
<aside draggable="true" class="dragme second" data-item="1">Two</aside>

Добавить атрибут элемента данных в функцию setData.

function drag_start(event) {
  var style = window.getComputedStyle(event.target, null);
  event.dataTransfer.setData("text/plain", (parseInt(style.getPropertyValue("left"), 10) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top"), 10) - event.clientY) + ',' + event.target.getAttribute('data-item'));
}

Нацельтесь на элемент, который перетаскивается.

function drop(event) {
  var offset = event.dataTransfer.getData("text/plain").split(',');
  var dm = document.getElementsByClassName('dragme');
  dm[parseInt(offset[2])].style.left = (event.clientX + parseInt(offset[0], 10)) + 'px';
  dm[parseInt(offset[2])].style.top = (event.clientY + parseInt(offset[1], 10)) + 'px';
  event.preventDefault();
  return false;
}

И перебрать все элементы с классом dragme.

var dm = document.getElementsByClassName('dragme');
for (var i = 0; i < dm.length; i++) {
  dm[i].addEventListener('dragstart', drag_start, false);
  document.body.addEventListener('dragover', drag_over, false);
  document.body.addEventListener('drop', drop, false);
}

ручка

5 голосов
/ 30 июня 2014

Спасибо за ваш ответ.Отлично работает в Chrome и Firefox.Я настроил его для работы в IE. Ниже приведен код.

 <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="generator" content="CoffeeCup HTML Editor (www.coffeecup.com)">
        <meta name="dcterms.created" content="Fri, 27 Jun 2014 21:02:23 GMT">
        <meta name="description" content="">
        <meta name="keywords" content="">
        <title></title>
        
        <!--[if IE]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    	<style>
    	li
    	{ 
          position:  absolute;
          left: 0;
          top: 0; /* set these so Chrome doesn't return 'auto' from getComputedStyle */
          width: 200px; 
          background: rgba(255,255,255,0.66); 
          border: 2px  solid rgba(0,0,0,0.5); 
          border-radius: 4px; padding: 8px;
    	}
    	</style>
    	<script>
            function drag_start(event) {
                var style = window.getComputedStyle(event.target, null);
                var str = (parseInt(style.getPropertyValue("left")) - event.clientX) + ',' + (parseInt(style.getPropertyValue("top")) - event.clientY) + ',' + event.target.id;
                event.dataTransfer.setData("Text", str);
            }

            function drop(event) {
                var offset = event.dataTransfer.getData("Text").split(',');
                var dm = document.getElementById(offset[2]);
                dm.style.left = (event.clientX + parseInt(offset[0], 10)) + 'px';
                dm.style.top = (event.clientY + parseInt(offset[1], 10)) + 'px';
                event.preventDefault();
                return false;
            }

            function drag_over(event) {
                event.preventDefault();
                return false;
            }
    	</script>
      </head>
      <body ondragover="drag_over(event)" ondrop="drop(event)">
       <ul>
              <li id="txt1" draggable="true" ondragstart="drag_start(event)"> Drag this text </li><br>
              <li id="txt2" draggable="true" ondragstart="drag_start(event)"> Drag me</li>
      </ul>
      	   <p>I never am really satisfied that I understand anything; because, understand it well as I may, my comprehension can only be an infinitesimal fraction of all I want to understand about the many connections and relations which occur to me, how the matter in question was first thought of or arrived at, etc., etc.</p>
      	   <p>In almost every computation a great variety of arrangements for the succession of the processes is possible, and various considerations must influence the selections amongst them for the purposes of a calculating engine. One essential object is to choose that arrangement which shall tend to reduce to a minimum the time necessary for completing the calculation.</p>
      	   <p>Many persons who are not conversant with mathematical studies imagine that because the business of [Babbage’s Analytical Engine] is to give its results in numerical notation, the nature of its processes must consequently be arithmetical and numerical, rather than algebraical and analytical. This is an error. The engine can arrange and combine its numerical quantities exactly as if they were letters or any other general symbols; and in fact it might bring out its results in algebraical notation, were provisions made accordingly.</p>
      	   <p>The Analytical Engine has no pretensions whatever to originate anything. It can do whatever we know how to order it to perform. It can follow analysis, but it has no power of anticipating any analytical revelations or truths. Its province is to assist us in making available what we are already acquainted with.</p>
    
      </body>
   </html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...