Фигуры, нарисованные на холсте, перемещаются слишком далеко при перетаскивании события

#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:

Вот что вы можете сделать:

  1. В функции верхнего уровня добавьте две переменные для смещения внутри объекта:
 let objectOffsetX = 0;
let objectOffsetY = 0;
 
  1. Вычислите их при получении события щелчка:
 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")
    }
}
 
  1. При перемещении мыши вычислите новое положение объекта, используя смещение холста и смещение объекта:
 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) Я должен вычислить смещение фигуры, чтобы удерживать курсор мыши при его перемещении.