Реализация перетаскивания HTML5

внешний интерфейс Element CSS Angular.js
Реализация перетаскивания HTML5

Нам не привыкать к перетаскиванию, тем более что HTML5 поддерживает перетаскивание, что упрощает его. Цель этой статьи — обсудить схему перетаскивания H5, этапы реализации и связанные с ней принципы.

1. Я понимаю перетаскивание

Для лучшего объяснения здесь я привожу классификацию примерно следующим образом:

  1. Класс операций перетаскивания, например, загрузка с помощью перетаскивания;
  2. Функциональное перетаскивание, сортировка перетаскиванием, направленность и обмен позициями;
  3. Прост в использовании, некоторые фиксированные элементы можно разместить где угодно;

Идея перетаскивания такая же, разница только в форме выражения.

Во-вторых, начните прямо

Давайте углубимся, начав с примера (используется впример адреса)!

1. Во-первых, установите перетаскиваемый элемент, мы используемdraggable

<img src="img/1.png" width="250" draggable="true" />

Для удобства конкретного описания ниже я добавил сюдаidа такжеondragstartсобытия следующим образом:

<img id="jartto" src="img/1.png" width="250"  draggable="true" ondragstart="drag(event)" />

ondragstartСвойство вызывает функцию drag(event), которая указывает перетаскиваемые данные.

2. Затем укажите, что происходит при перетаскивании элемента. Ключевые словаsetData()

function drag(ev)
{
  ev.dataTransfer.setData('Text',ev.target.id);
}

dataTransfer.setData()Метод устанавливает тип данных и значение перетаскиваемых данных, я позжеПодробное описание.

Здесь следует отметить, что тип данных setData — «Текст», а значение — идентификатор перетаскиваемого элемента.

3. Наконец, куда его поставить,ondragoverСобытие указывает, куда поместить перетаскиваемые данные, когда перетаскиваемые данные помещаютсяondropбудет запущен.

<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

function drop(ev)
{
  ev.preventDefault();
  var data=ev.dataTransfer.getData("Text");
  ev.target.appendChild(document.getElementById(data));
}
function allowDrop(ev)
{
  ev.preventDefault();
}

Здесь следует отметить несколько вопросов:

  1. По умолчанию данные/элементы не могут быть помещены в другие элементы. Если нам нужно установить допустимое падение, мы должны запретить обработку элемента по умолчанию, то есть, вызвав метод event.preventDefault() события ondragover;
  2. Вызовите preventDefault(), чтобы избежать обработки данных браузером по умолчанию (событие перетаскивания по умолчанию открывается как ссылка);
  3. Получите перетаскиваемые данные с помощью метода dataTransfer.getData('Text'). Этот метод вернет все данные, установленные для того же типа в методе setData().

Для получения подробной информации, пожалуйста, проверьте,демо1 пример кода.

3. Перетащите туда и обратно

На этом этапе мы можем перетащить элемент в указанный контейнер, так как же перетаскивать элемент туда и обратно между двумя контейнерами?
Продолжайте поддерживать предыдущую идею, давайте сделаем несколько простых корректировок:

1. Во-первых, убедитесь, что элементов два;

.jartto1,
.jartto2 {
  float: left;
  width: 150px;
  height: 140px;
  margin: 10px;
  border-radius: 3px;
  border: 1px solid #aaaaaa;
}

2. Измените структуру html

<div class="jartto1" ondrop="drop(event)" ondragover="allowDrop(event)">
  <img id="drag1" src="img/2.png" width="150" 
  draggable="true" ondragstart="drag(event)" />
</div>
<div class="jartto2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

3. Триггерный метод

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));
}

Код вроде бы не сильно изменился, но суть вот в чем:

<div class="jartto1" ondrop="drop(event)" ondragover="allowDrop(event)">
  <img id="drag1" src="img/2.png" width="150" 
  draggable="true" ondragstart="drag(event)" />
</div>

Как видите, мы установили оба контейнераondropа такжеondragoverТак что оба контейнера могут быть размещены, и перетаскивание реализуется.

Для получения подробной информации, пожалуйста, проверьте,пример кода demo2.

4. Перетащите куда угодноdrag everywhere

Что ж, перетаскивание вперед и назад также было реализовано, и мы продолжаем обновляться, чтобы видеть перетаскивание повсюду. Здесь немного сложнее, поэтому кратко разберемся с идеями:

1. Первый наборdragoverСобытие затрагивает весьdocument, чтобы элементы можно было размещать где угодно;
2. ВdragstartРассчитать положение перетаскивания мыши в событии;
3. ВdropСобытие, которое будет рассчитано на предыдущем шагеoffsetа такжеclientX,clientYОперация, расчет позиции размещения элемента;

Здесь я использую Angularjs в качестве примера, другие фреймворки могут иметь другие формы реализации, которые приведены только для справки.

Сначала создайте директиву и установите элемент эффектаdraggableАтрибуты;

angular.module('app')
  .directive('dragdrop', [function () {
    return {
      link: (scope, element, attrs) => {
        var el = element[0];
        el.draggable = true;
      }
    };
  }
]);

Во-вторых, сохраните данные перетаскивания;

el.addEventListener('dragstart',
  function(e) {
    let style = window.getComputedStyle(e.target, null);
    e.dataTransfer.setData('text/plain', 
      `${(parseInt(style.getPropertyValue('left')) - e.clientX)},${(parseInt(style.getPropertyValue('top')) - e.clientY)}`
    );
  },false);

Затем мы должны запретить обработку элементов по умолчанию, чтобы элементы можно было размещать внутри других элементов;

document.body.addEventListener('dragover',function(e) {
  e.preventDefault(); 
  return false; 
},false);

Снова удалите данные перетаскивания и заново определите положение элемента;

document.body.addEventListener('drop',function(e) {
  let offset = e.dataTransfer.getData('text/plain').split(',');
  el.style.left = (e.clientX + parseInt(offset[0])) + 'px';
  el.style.top = (e.clientY + parseInt(offset[1])) + 'px';
  e.preventDefault();
  return false;
},false);

Наконец, мы можем использовать:

<div id="jartto" dragdrop></div>

На самом деле, мы также можем выполнять некоторую обработку стилей (добавление и удаление классов) во время процесса перетаскивания, чтобы получить лучший эффект взаимодействия с пользователем, но это не обязательно, поэтому в коде это не отражено.

Для получения подробной информации, пожалуйста, проверьте,демо6 пример кода

Конечно, мы также можемmouseСобытия реализованы следующим образом:

element.on('mousedown', function(event) {
  // Prevent default dragging of selected content
  event.preventDefault();
  startX = event.pageX - x;
  startY = event.pageY - y;
  $document.on('mousemove', mousemove);
  $document.on('mouseup', mouseup);
});

Здесь показаны только фрагменты кода, пожалуйста, проверьте подробности,демо6 пример кода

5. Обработка деталей

Весь процесс вроде бы достаточно гладкий, на самом деле деталей еще много, вот краткий список:
Во-первых, элемент, расположенный с помощью fix, будет недействителен при перетаскивании;
Во-вторых, у контейнера есть отношение вмещения, если только вы не хотитеdrag everywhere, иначе перетаскивание не удастся;
В-третьих, поведение браузера по умолчанию, такое как перенаправление, должно быть заблокировано;
В-четвертых, по умолчанию данные/элементы нельзя помещать в другие элементы. Если нам нужно установить разрешение на размещение, мы должны запретить обработку элемента по умолчанию, т. е. вызовомondragoverмероприятиеevent.preventDefault()метод;
В-пятых, мобильная совместимость плохая, выбирайте внимательно;

Шесть, события перетаскивания

Давайте перечислимdragа такжеdropСмысл события предельно ясен, поэтому повторяться здесь не буду.

  • drag
  • dragstart
  • dragend
  • dragover
  • dragenter
  • dragleave
  • drop

7. О насDataTransfer

мы вdrag everywhereиспользуется в примереDataTransfer.setData(), познакомиться заново.

DataTransfer.setData()Метод используется для установки данных перетаскивания операции перетаскивания на указанные данные и тип.

  • Если данные данного типа не существуют, они добавляются в конец хранилища данных перетаскивания, так что последним элементом в списке типов будет новый тип.
  • Если данные данного типа уже существуют, существующие данные будут заменены тем же местоположением. То есть порядок списка типов не меняется при замене данных того же типа.

Примеры типов данных:"text/plain"а также"text/uri-list"

грамматика:

void dataTransfer.setData(format, data);

параметр:

  • формат: DOMString, представляющий тип данных перетаскивания для добавления к объекту перетаскивания.
  • data: DOMString, представляющий данные для добавления к объекту перетаскивания.

Больше, пожалуйста, переместитеmozilla setData

Восемь, Window.getComputedStyle()

КромеDataTransfer.setData()Здесь я хотел бы представить особенно интересное свойство,Window.getComputedStyle(), Почему ты это сказал? Давайте сначала посмотрим на его документацию:

Метод Window.getComputedStyle() возвращает значения всех свойств CSS элемента после применения активной таблицы стилей и разрешает любые базовые вычисления, которые могут содержаться в этих значениях.

грамматика:

let style = window.getComputedStyle(element, [pseudoElt]);

параметр:

  • element: Элемент, используемый для получения вычисляемого стиля
  • псевдоЭльт: необязательный, указывает строку псевдоэлементов для сопоставления. Должен быть опущен (или равен нулю) для обычных элементов.

Вот сила: стиль, который он возвращает, является живым объектом CSSStyleDeclaration, который автоматически обновляется при изменении стиля элемента.

Что касается совместимости, см. изображение ниже:
getComputedStyle

Девять, getPropertyValue

The CSSStyleDeclaration.getPropertyValue() method interface returns a DOMString containing the value of a specified CSS property.

грамматика:

var value = style.getPropertyValue(property);

Пример:

var declaration = document.styleSheets[0].cssRules[0].style;
var value = declaration.getPropertyValue('margin'); // "1px 2px"

Дополнительное свойство и два метода были расширены просто для того, чтобы предоставить больше идей для реализации и сделать нашу разработку более эффективной. Это не тестовый центр, тест не будет тестироваться~

10. Рекомендации по подключаемым модулям

пытаясь достичьdragВ течение долгого времени я использовал некоторые зрелые плагины, вот несколько рекомендуемых:

  1. Сортировка перетаскиванием HTML5
  2. codepen
  3. angular-drop

Подобных плагинов в инете куча.Фронтенд армия еще очень умеет строить колеса.Нет,мы сегодня построили еще один🙈~

Одиннадцать, ссылка

  1. w3school
  2. Implement html5 drag in angularjs
  3. Native drag and drop in AngularJS
  4. move anywhere
  5. mozilla getPropertyValue
  6. mozilla getComputedStyle