Нам не привыкать к перетаскиванию, тем более что HTML5 поддерживает перетаскивание, что упрощает его. Цель этой статьи — обсудить схему перетаскивания H5, этапы реализации и связанные с ней принципы.
1. Я понимаю перетаскивание
Для лучшего объяснения здесь я привожу классификацию примерно следующим образом:
- Класс операций перетаскивания, например, загрузка с помощью перетаскивания;
- Функциональное перетаскивание, сортировка перетаскиванием, направленность и обмен позициями;
- Прост в использовании, некоторые фиксированные элементы можно разместить где угодно;
Идея перетаскивания такая же, разница только в форме выражения.
Во-вторых, начните прямо
Давайте углубимся, начав с примера (используется впример адреса)!
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();
}
Здесь следует отметить несколько вопросов:
- По умолчанию данные/элементы не могут быть помещены в другие элементы. Если нам нужно установить допустимое падение, мы должны запретить обработку элемента по умолчанию, то есть, вызвав метод event.preventDefault() события ondragover;
- Вызовите preventDefault(), чтобы избежать обработки данных браузером по умолчанию (событие перетаскивания по умолчанию открывается как ссылка);
- Получите перетаскиваемые данные с помощью метода 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, который автоматически обновляется при изменении стиля элемента.
Что касается совместимости, см. изображение ниже:
Девять, 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
В течение долгого времени я использовал некоторые зрелые плагины, вот несколько рекомендуемых:
Подобных плагинов в инете куча.Фронтенд армия еще очень умеет строить колеса.Нет,мы сегодня построили еще один🙈~