Drag'n drop. Как сказать мыши что обект нужно отпустить? На примере готового кода
Есть небольшая тестовая страница с полем и кругом, который должен перемещаться по этому полю. Задача в целом решена, если раскомментировать те участки кода, который закоментированы в примере ниже. Но почему это работает я пока логически не могу понять, поэтому ищу другие способы. Подскажите что можно добавить в код, чтобы сообщить объекту что мышь его отпустила и нужно перестать следовать за курсором?
Также подскажите как сделать так чтобы круг двигался ТОЛЬКО в пределах поля, а не по всему окну.
let circle = document.querySelector('.circle');
let moveMoving = false;
circle.addEventListener('mousedown', function(event) {
// moveMoving = true;
let locationX = event.pageX - circle.style.left - 20;
let locationY = event.pageY - circle.style.top - 20;
moveCircle(event)
function moveCircle(event) {
circle.style.left = event.clientX - locationX + 'px';
circle.style.top = event.clientY - locationY + 'px';
}
circle.addEventListener('mousemove', function(event) {
// if (!moveMoving) return;
moveCircle(event);
});
circle.addEventListener('mouseup', function(event) {
// moveMoving = false;
});
});
.parallelepiped {
width: 500px;
height: 350px;
background-color: rgb(195, 0, 255);
}
.circle {
width: 50px;
height: 50px;
background-color: rgb(23, 235, 4);
border-radius: 50%;
position: absolute;
top: 20px;
left: 20px;
}
<div class='parallelepiped'>
<div class='circle'></div>
</div>
P.S. circle.style.left - 20; В данном случае я отнимаю 20 пикселей отступа чтобы круг не прыгал в правый левый угол, когда на него нажимают мышью. решение не самое изящное, но пока так.
Ответы (2 шт):
Подскажите что можно добавить в код, чтобы сообщить объекту что мышь его отпустила и нужно перестать следовать за курсором?
Необходимо отписаться от события, то есть использовать removeEventListener на той же функции, которую добавляли ранее.
Также подскажите как сделать так чтобы круг двигался ТОЛЬКО в пределах поля, а не по всему окну.
При перемещении сравнивать получившиеся координаты с размерами параллелепипеда. Обратите внимание на свойство "position: relative" у параллелепипеда. Из-за него круг перемещается относительно параллелепипеда, а не всего документа
Но почему это работает я пока логически не могу понять
Если переменная moveMoving равна true, перемещение круга просто блокируется:
if (!moveMoving) return;
const circle = document.querySelector('.circle');
const parallelepiped = document.querySelector('.parallelepiped');
let locationX = 0;
let locationY = 0;
function moveCircle(event) {
let left = event.clientX - locationX;
let top = event.clientY - locationY;
if(left < 0){
// выходит за границу параллелепипеда слева, останавливаем
left = 0;
}
if(left > parallelepiped.scrollWidth - circle.scrollWidth){
// выходит за границу параллелепипеда справа, останавливаем
left = parallelepiped.scrollWidth - circle.scrollWidth;
}
circle.style.left = left + 'px';
// с top нужно сделать аналогично
circle.style.top = top + 'px';
}
circle.addEventListener('mousedown', function(event) {
if(circle.style.left){
locationX = event.pageX - circle.style.left.replace('px', '');
}else{
locationX = event.pageX - 20;
}
if(circle.style.top){
locationY = event.pageY - circle.style.top.replace('px', '');
}else{
locationY = event.pageY - 20;
}
moveCircle(event)
// добавляем отслеживание события перемещения
document.addEventListener('mousemove', moveCircle);
});
document.addEventListener('mouseup', function(event) {
// убираем отслеживание события перемещения
document.removeEventListener('mousemove', moveCircle);
});
.parallelepiped {
position: relative;
width: 500px;
height: 350px;
background-color: rgb(195, 0, 255);
}
.circle {
width: 50px;
height: 50px;
background-color: rgb(23, 235, 4);
border-radius: 50%;
position: absolute;
top: 20px;
left: 20px;
}
<div class='parallelepiped'>
<div class='circle'></div>
</div>
Сделал немного по своему. Ниже код.
Осталось решить одну задачу - когда водишь мышкой чуть быстрее то круг как будто "не успевает" за курсором и оцепляется. Подскажите как это можно устранить?
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class='parallelepiped'>
<div class='circle'></div>
</div>
<script>
let circle = document.querySelector('.circle');
let parallelepiped = document.querySelector('.parallelepiped');
let moveMoving = false;
circle.addEventListener('mousedown', function(event) {
moveMoving = true;
let locationX = event.pageX - circle.style.left - 20;
let locationY = event.pageY - circle.style.top - 20;
moveCircle(event)
function moveCircle(event) {
let overflowWidth = event.clientX - locationX;
let overflowHeight = event.clientY - locationY;
if (overflowWidth < 0) {
circle.style.backgroundColor = 'red';
overflowWidth = parallelepiped.scrollWidth;
}
if (overflowHeight < 0) {
circle.style.backgroundColor = 'red';
overflowHeight = parallelepiped.scrollHeight;
}
if (overflowWidth > parallelepiped.scrollWidth - circle.scrollWidth) {
circle.style.left = parallelepiped.scrollWidth;
moveMoving = false;
} else {
circle.style.left = event.clientX - locationX + 'px';
}
if (overflowHeight > parallelepiped.scrollHeight - circle.scrollHeight) {
circle.style.top = parallelepiped.scrollHeight;
moveMoving = false;
} else {
circle.style.top = event.clientY - locationY + 'px';
}
}
circle.addEventListener('mousemove', function(event) {
if (!moveMoving) return;
moveCircle(event);
});
circle.addEventListener('mouseup', function(event) {
moveMoving = false;
});
});
</script>
</body>
</html>
CSS код тот же:
.parallelepiped {
position: relative;
width: 500px;
height: 350px;
background-color: rgb(195, 0, 255);
}
.circle {
width: 50px;
height: 50px;
background-color: rgb(23, 235, 4);
border-radius: 50%;
position: absolute;
top: 20px;
left: 20px;
}
