Придя впервые к технологии DRAG and DROP столкнулся с очень тяжелым её описанием (Это мое субъективное мнение. Прошу с ним не соглашаться, а перечитать все что только можно и посмотреть на этот вопрос с многих сторон). И решил написать пару статей, нацеленных на начинающих разработчиков, кто хочет познать дзен.
Статья будет состоять из двух частей:
Перед началом глубокого разбора, посмотрим поверхностно. Представьте себя в роли грузчика, вам необходимо перемесить коробку с одного места на другое. Для грузчика это «Ну взял, ну перенес. Готово!», а для программиста “Подошел к коробке, наклонился, взял коробку, поднял коробку, прошел N шагов, наклонился, отпустил коробку.”. Я это к тому, что перед началом работы проиграйте все в голове, по шагам и вы станете гораздо ближе к истине.
Я хочу оговориться, что методов создания данного эффекта несколько и обязательно прочтите о всех. Я воспользуюсь тем, который на данный момент считаю самым удобным.
При создании DRAG and DROP первым шагом необходимо объекту, который мы будем перемещать, присвоить значение draggable='true'.
,
На первом этапе я хочу показать сам процесс, а после мы его распространим на все объекты. Мы сейчас работаем в JS и как вам известно, в браузере существуют различные события, к которым мы можем привязать свои последовательности действий. Давайте разберем необходимые события для создания DRAG and DROP:
dragstart — происходит, когда пользователь начинает перетаскивать элемент.
drag — происходит, когда элемент перетаскивается.
dragend — происходит, когда пользователь закончил перетаскивание элемента.
dragenter — происходит, когда перетаскиваемый элемент попадает в целевой объект.
dragleave — происходит, когда перетаскиваемый элемент покидает целевой объект.
dragover — происходит, когда перетаскиваемый элемент находится над целью.
drop — происходит, когда перетаскиваемый элемент падает на целевой объект.
Теперь очень важная информация! События делятся на две группы. Для перемещаемого элемента (тот кого мы перетаскиваем): dragstart, Drag, Dragend. Для принимающего элемента (куда перетаскиваем): Dragenter, Dragleave, Dragover, Drop. И эти события не могут работать наоборот, но они могут работать друг без друга.
К примеру: Необходимо переместить объект и оставить его там, где мы отпустили кнопку мыши. Эта задача не требует принимающей части.
Бесспорно, пример сделан на коленке, но он замечательно иллюстрирует не обязательность принимающего объекта.
Я считаю примеры с отдельными событиями ни к чему, так как если в строчке d1.addEventListener('dragstart',function() { вы замените 'dragstart' на любое другое событие, сами сможете с ним поиграть и получить интересные результаты. Давайте даже так, поиграйте и то что вам показалось необычным и интересным покажите в комментариях, так каждый узнает много нового и сам сможет это повторить.
Когда вы попробуете все события, вы обнаружите что drop не работает. Это разработчики данного метода делают атата тем, кто решил «И это всё… Хух, ерунда».
Ну тут все просто, перед событием drop необходимо на этот же элемент повесить событие
Это примите как факт, без него работать не будет.
Статья будет состоять из двух частей:
- Метод создания DRAG and DROP эффектов.
- Практическое применение полученных знаний для создание сортировки при помощи DRAG and DROP
Параграф №1 Метод создания DRAG and DROP эффекта
Перед началом глубокого разбора, посмотрим поверхностно. Представьте себя в роли грузчика, вам необходимо перемесить коробку с одного места на другое. Для грузчика это «Ну взял, ну перенес. Готово!», а для программиста “Подошел к коробке, наклонился, взял коробку, поднял коробку, прошел N шагов, наклонился, отпустил коробку.”. Я это к тому, что перед началом работы проиграйте все в голове, по шагам и вы станете гораздо ближе к истине.
Я хочу оговориться, что методов создания данного эффекта несколько и обязательно прочтите о всех. Я воспользуюсь тем, который на данный момент считаю самым удобным.
При создании DRAG and DROP первым шагом необходимо объекту, который мы будем перемещать, присвоить значение draggable='true'.
<html>
<head>
<style>
.ddd {
display:block;
float:left;
padding:10px;
border:1px solid #000;
}
</style>
</head>
<body>
<div id='d1' class='ddd' draggable='true'>Pervii 1</div>
</body>
</html>
,
На первом этапе я хочу показать сам процесс, а после мы его распространим на все объекты. Мы сейчас работаем в JS и как вам известно, в браузере существуют различные события, к которым мы можем привязать свои последовательности действий. Давайте разберем необходимые события для создания DRAG and DROP:
dragstart — происходит, когда пользователь начинает перетаскивать элемент.
drag — происходит, когда элемент перетаскивается.
dragend — происходит, когда пользователь закончил перетаскивание элемента.
dragenter — происходит, когда перетаскиваемый элемент попадает в целевой объект.
dragleave — происходит, когда перетаскиваемый элемент покидает целевой объект.
dragover — происходит, когда перетаскиваемый элемент находится над целью.
drop — происходит, когда перетаскиваемый элемент падает на целевой объект.
Теперь очень важная информация! События делятся на две группы. Для перемещаемого элемента (тот кого мы перетаскиваем): dragstart, Drag, Dragend. Для принимающего элемента (куда перетаскиваем): Dragenter, Dragleave, Dragover, Drop. И эти события не могут работать наоборот, но они могут работать друг без друга.
К примеру: Необходимо переместить объект и оставить его там, где мы отпустили кнопку мыши. Эта задача не требует принимающей части.
<html>
<head>
<style>
.ddd {
display:block;
float:left;
padding:10px;
border:1px solid #000;
}
</style>
</head>
<body>
<div id='d1' class='ddd' draggable='true'>Pervii 1</div>
<div id='d2' class='ddd'>Vtoroy 2</div>
<div id='d3' class='ddd'>Tretii 3</div>
<div id='d4' class='ddd'>Chetverty 4</div>
<div id='d5' class='ddd'>Pyatii 5</div>
<script>
var d1 = document.getElementById('d1');
var startCursorX;
var startCursorY;
var startX;
var startY;
d1.addEventListener('dragstart',function() {
startCursorX = event.pageX;//Начальная позиция курсора по оси X
startCursorY = event.pageY;//Начальная позиция курсора по оси Y
startX = d1.style.marginLeft.replace('px','')*1; // Нам нужны только цыфры без PX
startY = d1.style.marginTop.replace('px','')*1;
});
d1.addEventListener('dragend',function() {
d1.style.position = 'absolute';//CSS теперь элемент "Блуждающий" :)
d1.style.marginLeft = startX + event.pageX-startCursorX; //позиция элемента + позиция курсора - позиция курсоа в начале перетаскивания
d1.style.marginTop = startY + event.pageY-startCursorY; // Так же как и в предыдущем случае, только по другой оси
});
</script>
</body>
</html>
Бесспорно, пример сделан на коленке, но он замечательно иллюстрирует не обязательность принимающего объекта.
Я считаю примеры с отдельными событиями ни к чему, так как если в строчке d1.addEventListener('dragstart',function() { вы замените 'dragstart' на любое другое событие, сами сможете с ним поиграть и получить интересные результаты. Давайте даже так, поиграйте и то что вам показалось необычным и интересным покажите в комментариях, так каждый узнает много нового и сам сможет это повторить.
Параграф №2. Не работает DROP в DRAG and DROP
Когда вы попробуете все события, вы обнаружите что drop не работает. Это разработчики данного метода делают атата тем, кто решил «И это всё… Хух, ерунда».
Ну тут все просто, перед событием drop необходимо на этот же элемент повесить событие
d2.addEventListener('dragover',function() {
event.preventDefault();
});
Это примите как факт, без него работать не будет.
Комментарии (5)
ua30
14.08.2019 10:11Весьма интересно, не знал про
значениеатрибут draggable.
Подобные статьи гораздо лучше воспринимаются с живым demo. Дублируйте код в https://jsfiddle.net/ и давайте линк.
Пример кода простой, но называть класс именем «ddd» не есть хорошо. Порядок важен и в мелочах.
Неплохо было бы так же упомянуть о неплохой, но не полной поддержке технологии на данный момент https://caniuse.com/#search=draggable — 84.35% + 3.5% частично. ИМХО, пока и удобней и практичней пользоваться соответствующими JS библиотеками.
Minu
14.08.2019 12:38В примере после d1.style.marginLeft =… и d1.style.marginTop =… не хватает + 'px'.
BigDflz
есть вопрос по изображению объекта во время перемещения. Если объект не большой (примерно до 250*250 px) то он отображается нормально, но если объект больше то на него накладывается радиальная прозрачность с центром в точке захвата и к границам становится совсем прозрачной, что очень не удобно. Есть ли возможность изменить вид прозрачности? В мануалах я не нашёл упоминание и прозрачности, плохо искал?
GeneAYak
Сам не проовал, но вообще есть такой раздел в документации
Возможно, это то, что нужно
BigDflz
спасибо, при следующем применении проверю.