Кратко
События мыши: click (клик), mousedown (нажатие), mouseup (отпускание), mousemove (движение). Координаты: clientX/Y (от viewport), pageX/Y (от страницы). Drag and Drop: dragstart → dragover → drop. dataTransfer передаёт данные между элементами.
Подробно
События мыши:
- click — полный клик (mousedown + mouseup)
- mousedown — кнопка нажата
- mouseup — кнопка отпущена
- mousemove — движение мыши (срабатывает часто!)
- dblclick — двойной клик
Координаты:
element.addEventListener('mousemove', (e) => { console.log('clientX:', e.clientX, 'clientY:', e.clientY); console.log('pageX:', e.pageX, 'pageY:', e.pageY); });
clientX/Y — от начала viewport (окна браузера) pageX/Y — от начала страницы (с учётом прокрутки)
Drag and Drop API:
- dragstart — начало перетаскивания
- drag — элемент перетаскивается
- dragenter — элемент вошёл в drop-зону
- dragover — элемент над drop-зоной
- dragleave — элемент покинул drop-зону
- drop — элемент dropped в зону
- dragend — перетаскивание завершено
Пример:
// Draggable элемент const draggable = document.querySelector('.draggable'); draggable.addEventListener('dragstart', (e) => { e.dataTransfer.setData('text/plain', draggable.id); e.dataTransfer.effectAllowed = 'move'; });
// Drop-зона const dropZone = document.querySelector('.drop-zone'); dropZone.addEventListener('dragover', (e) => { e.preventDefault(); // обязательно! dropZone.classList.add('over'); });
dropZone.addEventListener('dragleave', () => { dropZone.classList.remove('over'); });
dropZone.addEventListener('drop', (e) => { e.preventDefault(); const id = e.dataTransfer.getData('text/plain'); const element = document.getElementById(id); dropZone.appendChild(element); });
Ментальная модель
Drag and Drop — как перестановка мебели. Вы берёте предмет (dragstart), несёте его (drag), подносите к новому месту (dragover), и ставите (drop). dataTransfer — как этикетка на предмете: на ней написано, что это за предмет.
Примеры
**Самый простой:**
const box = document.querySelector('.box');
box.addEventListener('mousedown', () => console.log('Нажал'));
box.addEventListener('mouseup', () => console.log('Отпустил'));
box.addEventListener('click', () => console.log('Клик'));
// При клике: Нажал → Отпустил → КликПорядок событий: mousedown → mouseup → click.
**Простой:**
const area = document.querySelector('.area');
const dot = document.querySelector('.dot');
let isDragging = false;
area.addEventListener('mousedown', (e) => {
isDragging = true;
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
dot.style.left = e.clientX + 'px';
dot.style.top = e.clientY + 'px';
});
document.addEventListener('mouseup', () => {
isDragging = false;
});Перетаскивание через mouse events (не Drag and Drop API).
**Реальный пример:**
// HTML5 Drag and Drop
const items = document.querySelectorAll('.item');
const container = document.querySelector('.container');
items.forEach(item => {
item.draggable = true;
item.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', item.id);
item.classList.add('dragging');
});
item.addEventListener('dragend', () => {
item.classList.remove('dragging');
});
});
container.addEventListener('dragover', (e) => {
e.preventDefault();
const afterElement = getDragAfterElement(container, e.clientY);
const dragging = document.querySelector('.dragging');
if (afterElement == null) {
container.appendChild(dragging);
} else {
container.insertBefore(dragging, afterElement);
}
});Реальный Drag and Drop: сортировка списка с определением позиции.
Частые ошибки
**Неправильно:** Забывать e.preventDefault() в dragover
**Почему:** По умолчанию браузер НЕ позволяет drop. Нужно отменить default action в dragover.
**Правильно:** В dragover всегда вызывайте e.preventDefault().
**Неправильно:** Использовать mousemove без throttle/debounce
**Почему:** mousemove срабатывает десятки раз в секунду — это может замедлить страницу.
**Правильно:** Для анимаций используйте requestAnimationFrame. Для редких обновлений — throttle.
**Неправильно:** Путать clientX и pageX
**Почему:** clientX — от viewport. pageX — от страницы. При прокрутке они различаются.
**Правильно:** Для позиционирования элемента используйте clientX/Y. Для позиции на странице — pageX/Y.
Важно запомнить
- mousedown → mouseup → click (порядок событий)
- clientX/Y — от viewport, pageX/Y — от страницы
- mousemove срабатывает часто — будьте аккуратны
- Drag and Drop: dragstart → dragover → drop
- В dragover обязательно e.preventDefault()
- dataTransfer передаёт данные между drag и drop
Связь
Назад: Вы знаете события (DA1-DA5). Теперь вы работаете с конкретными взаимодействиями мыши и перетаскиванием.
Вперёд: Следующий урок (DA7) — взаимодействие с формами: свойства, методы и события.