You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 2-ui/3-event-details/4-mouse-drag-and-drop/article.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ Drag'n'Drop - отличный способ улучшить интерфейс.
6
6
7
7
Они интересны тем, что позволяют легко решать простые задачи. Например, можно перетащить файл в браузер, так что JS получит доступ к его содержимому.
8
8
9
-
Но у встроенных событий, входящих в Drag’n’Drop, также есть ограничения. Например, нельзя организовать перенос «только по горизонтали» или «только по вертикали». Также нельзя ограничить перенос внутри заданной зоны. Есть и другие интерфейсные задачи, которые такими встроенными событиями нереализуемы.
9
+
Но у встроенных событий, входящих в Drag’n’Drop, также есть ограничения. Например, нельзя организовать перенос "только по горизонтали" или "только по вертикали". Также нельзя ограничить перенос внутри заданной зоны. Есть и другие интерфейсные задачи, которые такими встроенными событиями нереализуемы.
10
10
11
11
Поэтому здесь мы будем рассматривать Drag’n’Drop при помощи событий мыши. Это не так уж сложно.
12
12
@@ -19,7 +19,7 @@ Drag'n'Drop - отличный способ улучшить интерфейс.
19
19
3. При наступлении `mousemove` передвигаем элемент на новые координаты путём смены `left/top` и `position:absolute`.
20
20
4. На `mouseup` (при отпускании кнопки мыши) -- остановить перенос элемента и произвести все действия, связанные с окончанием Drag’n’Drop..
21
21
22
-
Это есть база Drag'n'Drop. Мы могли бы расширить этот алгоритм, например, подсветив элементы при наведении на них курсора.
22
+
Это и есть база Drag'n'Drop. Мы могли бы расширить этот алгоритм, например, подсветив элементы при наведении на них курсора.
23
23
24
24
В следующем примере эти шаги реализованы для переноса мяча:
Если запустить этот код, то мы заметим нечто странное. При начале переноса мяч «раздваивается» и переносится не сам мяч, а его «клон».
61
+
Если запустить этот код, то мы заметим нечто странное. При начале переноса мяч "раздваивается" и переносится не сам мяч, а его "клон".
62
62
63
63
```online
64
64
Это можно увидеть в действии:
@@ -88,7 +88,7 @@ ball.ondragstart = function() {
88
88
89
89
Ещё одна особенность правильного Drag’n’Drop -- событие `mousemove` отслеживается на `document`, а не на `ball`. С первого взгляда кажется, что мышь всегда над мячом и обработчик `mousemove` можно повесить на сам мяч, а не на документ.
90
90
91
-
Но как мы помним, событие `mousemove` возникает хоть и часто, но не для каждого пикселя. Поэтому из-за быстрого движения курсор может выпрыгнуть и оказаться где-нибудь в середине документа (или даже за пределами окна).
91
+
Но как мы помним, событие `mousemove` возникает хоть и часто, но не для каждого пикселя. Поэтому из-за быстрого движения курсор может спрыгнуть с мяча и оказаться где-нибудь в середине документа (или даже за пределами окна).
92
92
93
93
Вот почему мы должны отслеживать `mousemove` на всём `document`.
Неплохо, но есть побочные эффекты. В частности, в самом начале переноса, особенно если мячик «взят» за край – он резко «прыгает» центром под курсор мыши.
104
+
Неплохо, но есть побочные эффекты. В частности, в самом начале переноса, особенно если мячик "взят" за край – он резко "прыгает" центром под курсор мыши.
105
105
106
106
Было бы лучше, если бы изначальный сдвиг курсора относительно элемента сохранялся.
107
107
108
-
Где захватили, за ту «часть элемента» и переносим:
108
+
Где захватили, за ту "часть элемента" и переносим:
Различие особенно заметно, если захватить мяч за правый нижний угол. В предыдущем примере мячик «прыгнет» серединой под курсор, в этом – будет плавно переноситься с текущей позиции.
181
+
Различие особенно заметно, если захватить мяч за правый нижний угол. В предыдущем примере мячик "прыгнет" серединой под курсор, в этом – будет плавно переноситься с текущей позиции.
Существует метод `document.elementFromPoint(clientX, clientY)`. Он возвращает наиболее глубоко вложенный элемент по заданным координатам окна (или `null` если координаты находятся за пределами окна).
220
+
Существует метод `document.elementFromPoint(clientX, clientY)`. Он возвращает наиболее глубоко вложенный элемент по заданным координатам окна (или `null`, если координаты находятся за пределами окна).
221
221
222
222
Таким образом, через любой из наших обработчиков событий мыши мы можем обнаружить тот элемент, который потеницально мог бы принять на себя конец перемещения:
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
228
228
ball.hidden = false;
229
-
// elemBelow - элемент под шаром. Если на нем можно закончить перемещение, мы сможем этим управлять.
229
+
// elemBelow - элемент под шаром. Если на нём можно закончить перемещение, мы сможем этим управлять.
230
230
```
231
231
232
232
Заметим, нам нужно спрятать мяч перед вызовом функции `(*)`. В противном случае по этим координатам мы будем получать мяч, ведь это и есть элемент непосредственно под указателем:`elemBelow=ball`.
@@ -275,7 +275,7 @@ function onMouseMove(event) {
275
275
276
276
[codetabs height=250 src="ball4"]
277
277
278
-
Теперь в течение всего процесса в переменной `currentDroppable` мы храним текущую «цель удаления», и мы можем использовать её для того, чтобы выделить цель, или для любых других вещей.
278
+
Теперь в течение всего процесса в переменной `currentDroppable` мы храним текущую "цель удаления", и мы можем использовать её для того, чтобы выделить цель, или для любых других вещей.
0 commit comments