#drag-and-drop #html5-canvas
#перетаскивание #html5-холст
Вопрос:
Я сталкиваюсь с проблемой при перетаскивании прямоугольника, если я немного переместил его, он будет перерисован слишком далеко от текущего нового положения мыши. Как мне исправить расчет расстояния?
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
</head>
<body>
<canvas id="face-canvas" style="border:1px solid #000000;"></canvas>
<script type="module">
(() => {
let canvas = document.getElementById("face-canvas");
canvas.height = 300;
canvas.width = 300;
let cnt = canvas.getContext("2d");
let isDragging = false;
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX = 0, startY = 0;
let selectedObjIndex = 0;
let drawn_obj = [];
drawn_obj.push({...drawBox(20, 15, 50, 50, "#1df"), index: 1})
drawn_obj.push({...drawBox(80, 40, 50, 50, "#a33"), index: 2})
document.addEventListener("mousedown", (event) => onMouseDown(event));
document.addEventListener("mousemove", (event) => onMouseMove(event));
document.addEventListener("mouseup", (event) => onMouseUp(event));
function onMouseDown(event) {
event.preventDefault();
event.stopPropagation();
startX = Math.abs(parseInt(event.clientX - offsetX));
startY = Math.abs(parseInt(event.clientY - offsetY));
selectedObjIndex = selectedObj(startX, startY);
if(selectedObjIndex > 0) {
isDragging = true;
console.log("ffffffff")
}
}
function onMouseMove(event) {
if(isDragging amp;amp; selectedObjIndex > 0) {
let moveX = parseInt(event.clientX - offsetX);
let moveY = parseInt(event.clientY - offsetY);
let newX = parseInt(moveX - startX);
let newY = parseInt(moveY - startY);
drawn_obj[selectedObjIndex - 1].x = newX;
drawn_obj[selectedObjIndex - 1].y = newY;
console.log("newX, newY", newX, newY)
redrawAll();
}
}
function onMouseUp() {
event.preventDefault();
event.stopPropagation();
isDragging = false;
}
function selectedObj(x, y) {
for(let i = 0; i < drawn_obj.length; i) {
if(x >= drawn_obj[i].x amp;amp; x <= (drawn_obj[i].x drawn_obj[i].w) amp;amp;
y >= drawn_obj[i].y amp;amp; y <= (drawn_obj[i].y drawn_obj[i].h)) {
return drawn_obj[i].index;
}
}
return 0;
}
function redrawAll() {
cnt.clearRect(0, 0, canvas.width, canvas.height);
for(let i = 0; i < drawn_obj.length; i) {
drawBox(drawn_obj[i].x, drawn_obj[i].y, drawn_obj[i].w, drawn_obj[i].h, drawn_obj[i].color);
}
}
function drawBox(x, y, w, h, color) {
cnt.fillStyle = color;
cnt.fillRect(x, y, w, h);
return {x: x, y: y, w: w, h: h, color: color}
}
})();
</script>
</body>
</html>
Комментарии:
1. Очевидная проблема заключается в использовании
=
, вы продолжаете увеличивать координаты все больше и больше с каждым ходом. Вот почему он так быстро удаляется с холста. Вам нужно просто использовать=
и назначать координаты мыши с поправкой на смещение точки внутри объекта, где она была первоначально нажата.2. @tromgy Сейчас это работает, но теперь, когда я перетаскиваю фигуру из любой позиции, кроме той, которую курсор установит в ее угол во время процесса перетаскивания, как я могу удерживать курсор в той позиции, в которой вы нажали на нее?
Ответ №1:
Вот что вы можете сделать:
- В функции верхнего уровня добавьте две переменные для смещения внутри объекта:
let objectOffsetX = 0;
let objectOffsetY = 0;
- Вычислите их при получении события щелчка:
function onMouseDown(event) {
event.preventDefault();
event.stopPropagation();
startX = event.clientX - offsetX;
startY = event.clientY - offsetY;
selectedObjIndex = selectedObj(startX, startY);
objectOffsetX = startX - drawn_obj[selectedObjIndex - 1].x;
objectOffsetY = startY - drawn_obj[selectedObjIndex - 1].y;
if(selectedObjIndex > 0) {
isDragging = true;
console.log("ffffffff")
}
}
- При перемещении мыши вычислите новое положение объекта, используя смещение холста и смещение объекта:
function onMouseMove(event) {
if(isDragging amp;amp; selectedObjIndex > 0) {
let newX = event.clientX - offsetX - objectOffsetX;
let newY = event.layerY - offsetY - objectOffsetY;
drawn_obj[selectedObjIndex - 1].x = newX;
drawn_obj[selectedObjIndex - 1].y = newY;
console.log("newX, newY", newX, newY)
redrawAll();
}
}
Вы можете заметить, что я упростил некоторый код, который вам действительно не нужно использовать parseInt
, у вас уже есть все в виде (целых) чисел, а не строк.
Вы можете видеть, как все это работает в codepen
Комментарии:
1. Итак, в основном у меня есть две проблемы: 01)
=
, он увеличивался все больше и больше с каждым ходом. 02) Я должен вычислить смещение фигуры, чтобы удерживать курсор мыши при его перемещении.