在HTML5画布中拖放多个对象

5
I希望您能在给定区域内实现一个应用程序,用户可以在其中拖放多个对象。我正在使用HTML5画布标签来实现这一点。当仅有一个对象要在画布中拖放时,代码运行正常,但是当我尝试在画布中独立地拖放多个对象时,我没有得到期望的输出。
这是仅有一个对象的拖放工作示例和绘图函数。

http://jsfiddle.net/KZ99q/

function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
rect(0,0,WIDTH,HEIGHT);
ctx.fillStyle = "#444444";
rect(x - 15, y - 15, 30, 30);

}

我认为在draw()函数中添加更多的对象会起作用,因此我在draw()函数中添加了新对象的代码,如此链接所示。

http://jsfiddle.net/KZ99q/1/

  function draw() {
  clear();
  ctx.fillStyle = "#FAF7F8";
  rect(0,0,WIDTH,HEIGHT);
  ctx.fillStyle = "#444444";
  rect(x - 15, y - 15, 30, 30);
  ctx.fillStyle = "#ff550d";
  rect(x - 25, y - 25, 30, 30);
 ctx.fillStyle = "#800080";
  rect(x - 35, y - 35, 30, 30);
  ctx.fillStyle = "#0c64e8";
 rect(x - 45, y - 45, 30, 30);
}

我似乎无法理解在MyMove()、MyUp()和MyDown()函数中需要进行哪些更改,以使对象彼此独立移动。请帮忙。


@markE,你能否帮我看一下这个问题并帮我解决一下吗? - Lucy
2个回答

30

当移动1个或多个形状时,步骤如下:

创建定义每个形状的对象:

// an array of objects that define different rectangles
var rects=[];
rects.push({x:75-15,y:50-15,width:30,height:30,fill:"#444444",isDragging:false});
rects.push({x:75-25,y:50-25,width:30,height:30,fill:"#ff550d",isDragging:false});
rects.push({x:75-35,y:50-35,width:30,height:30,fill:"#800080",isDragging:false});
rects.push({x:75-45,y:50-45,width:30,height:30,fill:"#0c64e8",isDragging:false});

在mousedown事件中:

  • 获取当前鼠标位置
  • 对于任何一个被鼠标覆盖的形状,将其isDragging标志设为true
  • 保存当前鼠标位置

在mousemove事件中:

  • 获取当前鼠标位置
  • 计算鼠标移动的距离(距离 = 新鼠标位置 - 旧鼠标位置)
  • 将距离加到任何一个被标记为isDragging的形状位置上
  • 保存当前鼠标位置
  • 用新位置重新绘制场景中的形状

在mouseup事件中:

  • 清除所有标记为isDragging的标志

以下是有注释的代码和演示:http://jsfiddle.net/m1erickson/qm9Eb/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
window.onload=function(){

    // get canvas related references
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var BB=canvas.getBoundingClientRect();
    var offsetX=BB.left;
    var offsetY=BB.top;
    var WIDTH = canvas.width;
    var HEIGHT = canvas.height;

    // drag related variables
    var dragok = false;
    var startX;
    var startY;

    // an array of objects that define different rectangles
    var rects=[];
    rects.push({x:75-15,y:50-15,width:30,height:30,fill:"#444444",isDragging:false});
    rects.push({x:75-25,y:50-25,width:30,height:30,fill:"#ff550d",isDragging:false});
    rects.push({x:75-35,y:50-35,width:30,height:30,fill:"#800080",isDragging:false});
    rects.push({x:75-45,y:50-45,width:30,height:30,fill:"#0c64e8",isDragging:false});

    // listen for mouse events
    canvas.onmousedown = myDown;
    canvas.onmouseup = myUp;
    canvas.onmousemove = myMove;

    // call to draw the scene
    draw();

    // draw a single rect
    function rect(x,y,w,h) {
     ctx.beginPath();
     ctx.rect(x,y,w,h);
     ctx.closePath();
     ctx.fill();
    }

    // clear the canvas
    function clear() {
     ctx.clearRect(0, 0, WIDTH, HEIGHT);
    }

    // redraw the scene
    function draw() {
        clear();
        ctx.fillStyle = "#FAF7F8";
        rect(0,0,WIDTH,HEIGHT);
        // redraw each rect in the rects[] array
        for(var i=0;i<rects.length;i++){
            var r=rects[i];
            ctx.fillStyle=r.fill;
            rect(r.x,r.y,r.width,r.height);
        }
    }


    // handle mousedown events
    function myDown(e){

        // tell the browser we're handling this mouse event
        e.preventDefault();
        e.stopPropagation();

        // get the current mouse position
        var mx=parseInt(e.clientX-offsetX);
        var my=parseInt(e.clientY-offsetY);

        // test each rect to see if mouse is inside
        dragok=false;
        for(var i=0;i<rects.length;i++){
            var r=rects[i];
            if(mx>r.x && mx<r.x+r.width && my>r.y && my<r.y+r.height){
                // if yes, set that rects isDragging=true
                dragok=true;
                r.isDragging=true;
            }
        }
        // save the current mouse position
        startX=mx;
        startY=my;
    }


    // handle mouseup events
    function myUp(e){
        // tell the browser we're handling this mouse event
        e.preventDefault();
        e.stopPropagation();

        // clear all the dragging flags
        dragok = false;
        for(var i=0;i<rects.length;i++){
            rects[i].isDragging=false;
        }
    }


    // handle mouse moves
    function myMove(e){
        // if we're dragging anything...
        if (dragok){

          // tell the browser we're handling this mouse event
          e.preventDefault();
          e.stopPropagation();

          // get the current mouse position
          var mx=parseInt(e.clientX-offsetX);
          var my=parseInt(e.clientY-offsetY);

          // calculate the distance the mouse has moved
          // since the last mousemove
          var dx=mx-startX;
          var dy=my-startY;

          // move each rect that isDragging 
          // by the distance the mouse has moved
          // since the last mousemove
          for(var i=0;i<rects.length;i++){
              var r=rects[i];
              if(r.isDragging){
                  r.x+=dx;
                  r.y+=dy;
              }
          }

          // redraw the scene with the new rect positions
          draw();

          // reset the starting mouse position for the next mousemove
          startX=mx;
          startY=my;

        }
    }

}; // end $(function(){});
</script>
</head>
<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

@varunsharma。从桌面上传图像不是问题的一部分。 - markE
3
请注意,现在不再需要在您的代码中计算鼠标移动的距离,MouseEvent API 包含两个新属性 movementXmovementY,它们为您提供了这些数据。更多信息请参见 MDNcaniuse.com - RicoBrassers

-1
<!-- HTML code for the button that opens the popup form -->
<button id="open-popup-btn">Open Popup Form</button>

<!-- HTML code for the popup form -->
<div id="popup-form-container" style="display: none; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #fff; padding: 20px;">
  <label for="name-input">Name:</label>
  <input type="text" id="name-input"><br>

  <label for="email-input">Email:</label>
  <input type="email" id="email-input"><br>

  <label for="phone-input">Phone:</label>
  <input type="tel" id="phone-input"><br>

  <button id="popup-save-btn">Save</button>
</div>

// JavaScript code to handle the button click event
const openPopupBtn = document.getElementById('open-popup-btn');
const popupFormContainer = document.getElementById('popup-form-container');
const popupSaveBtn = document.getElementById('popup-save-btn');

openPopupBtn.addEventListener('click', () => {
  popupFormContainer.style.display = 'block';
});

popupSaveBtn.addEventListener('click', () => {
  const nameInput = document.getElementById('name-input').value;
  const emailInput = document.getElementById('email-input').value;
  const phoneInput = document.getElementById('phone-input').value;

  // Create a JSON object with the field values
  const formData = {
    name: nameInput,
    email: emailInput,
    phone: phoneInput
  };

  // Do something with the JSON object, like send it to a server or save it to local storage
  console.log(formData);

  // Hide the popup form after saving the data
  popupFormContainer.style.display = 'none';
});

1
你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文献,以便他人可以确认你的回答是正确的。您可以在帮助中心找到有关如何撰写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接