Подтвердить что ты не робот

HTML5 Перетаскивание в любом месте экрана

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

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

Любые предложения?

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

4b9b3361

Ответ 1

Перетаскивание не перемещает элементы вокруг, если вы хотите, чтобы элемент перемещался при его удалении, вы должны установить новую позицию элемента в событии drop. Я сделал пример, который работает в 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.

Ответ 2

Спасибо за Ваш ответ. Отлично работает в 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 [Babbages 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>

Ответ 3

Я скорректировал отличный ответ 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);
}

pen