如何使HTML5可拖动对象在画布上? [英] How to make HTML5 draggable objects over canvas?

查看:197
本文介绍了如何使HTML5可拖动对象在画布上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始学习html5,我试图用可拖动的船创建一个战舰界面。我需要帮助,使我的拖动方法工作。我故意不使用库,因为我需要使船可拖动在另一个画布界面(战舰板),我不知道如何做的Kinetic库。我觉得我很近,但我不知道最后一点。



这是我的clode:

 <!doctype html> 
< html>
< head>
< meta charset =UTF-8/>
< title>画布拖放测试< / title>
< / head>
< body>
< section>

< div align = center>
< canvas id =canvaswidth =550height =550>
如果您的浏览器不支持HTML5 Canvas,则会显示此文本。
< / canvas>
< / div>

< script type =text / javascript>
var canvas;
var ctx;
var x = 75;
var y = 50;
var WIDTH = 550;
var HEIGHT = 550;
var dragok = false;
var ships = [];
var ship;
var shipFill =#FF0000;
//定义
//可拖动运营商
var caRectX = 100;
var caRectY = 50;
var caRectHeight = 50;
var caRectWidth = 5 * 50;
var carrier = {
x:caRectX,
y:caRectY,
width:caRectWidth,
height:caRectHeight,
fill:shipFill,
dragging:false,
offsetX:0,
offsetY:0,

};
ships.push(carrier);
// Draggable战舰
var bsRectX = 100;
var bsRectY = 150;
var bsRectHeight = 50;
var bsRectWidth = 4 * 50;

var battleship = {
x:bsRectX,
y:bsRectY,
width:bsRectWidth,
height:bsRectHeight,
fill:shipFill,
dragging:false,
offsetX:0,
offsetY:0,

};
ships.push(battleship);

// Draggable Patrolboat
var pbRectX = 100;
var pbRectY = 250;
var pbRectHeight = 50;
var pbRectWidth = 2 * 50;

var patrolboat = {
x:pbRectX,
y:pbRectY,
width:pbRectWidth,
height:pbRectHeight,
fill:shipFill,
dragging:false,
offsetX:0,
offsetY:0,

};
ships.push(patrolboat);

// Draggable潜艇
var suRectX = 100;
var suRectY = 350;
var suRectHeight = 50;
var suRectWidth = 3 * 50;

var submarine = {
x:suRectX,
y:suRectY,
width:suRectWidth,
height:suRectHeight,
fill:shipFill,
dragging:false,
offsetX:0,
offsetY:0,

};
ships.push(submarine);

//可拖动驱逐舰
var deRectX = 100;
var deRectY = 450;
var deRectHeight = 50;
var deRectWidth = 3 * 50;

var destroyer = {
x:deRectX,
y:deRectY,
width:deRectWidth,
height:deRectHeight,
dragging:
fill:shipFill
};
ships.push(destroyer)

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

函数clear(){
ctx.clearRect(0,0,WIDTH,HEIGHT);
}

function init(){
canvas = document.getElementById(canvas);
ctx = canvas.getContext(2d);
return setInterval(draw,10);
}

function draw(){
clear();
ctx.fillStyle =#FAF7F8;
rect(0,0,WIDTH,HEIGHT);
ctx.fillStyle =#444444;
for(var i = 0; i< ships.length; i ++){
rect(ships [i] .x,ships [i] .y,ships [i] .width,ships [ i] .height);
}
}

function myMove(e){
if(ship.dragging){
ship.x = e.pageX - canvas.offsetLeft ;
ship.y = e.pageY - canvas.offsetTop;
draw()
}
}

function myDown(e){
ship = getClickedShip(e.pageX,e.pageY);
if(ship!= null){
ship.x = e.pageX - canvas.offsetLeft;
ship.y = e.pageY - canvas.offsetTop;
ship.dragging = true;
canvas.onmousemove = myMove();
}
}

function myUp(){
ship.dragging = false;
canvas.onmousemove = null;
}

function getClickedShip(sx,sy){
for(var i = 0; i< ships.length; i ++){
if(sx> ;(ships [i] .x)+ canvas.offsetLeft&& sx<(ships [i] .x + ships [i] .width + canvas.offsetLeft)&& .y + canvas.offsetTop)&& sy<(ships [i] .y + ships [i] .height))
return ships [i];
}
}
init();
canvas.onmousedown = myDown
canvas.onmouseup = myUp;

< / script>

< / section>
< / body>
< / html>


解决方案

形状可拖动



请注意,这在SO之前已经回答过了但这个答案说明了新的context.isPointInPath方法来测试一个点是否在一个html画布路径内。



希望这种新的命中测试方法将是新的&对于OP和其他人有用:)



下面是在html canvas中拖动形状的一般过程:



在mouseDown:




  • 将此mouseX位置保存在变量中(lastX)

  • 在变量(lastY)中保存此鼠标Y位置

  • 将mouseIsDown标记设置为true



On mouseUp




  • 将mouseIsDown标记设置为false



在mouseMove




  • 点击测试每艘船是否应该拖动。

  • 如果最后一个X / lastY在船内,则会拖动该船

  • 将拖动的船只移动鼠标刚移动的距离



    • MouseDown处理程式码:

        function handleMouseDown (e){

      //获取相对于画布的当前鼠标位置

      mouseX = parseInt(e.clientX-offsetX);
      mouseY = parseInt(e.clientY-offsetY);

      //保存最后一个mouseX / mouseY

      lastX = mouseX;
      lastY = mouseY;

      //设置mouseIsDown标志

      mouseIsDown = true;
      }

      MouseUp处理程序代码

        function handleMouseUp(e){

      //清除mouseIsDown标志

      mouseIsDown = false ;
      }

      MouseMove处理程序代码



      此代码说明使用 context.isPointInPath 命中测试html画布路径



      这样做的过程是:




      • 定义一个路径(但不能绘制它 - 没有填充, li>
      • 使用 context.isPointInPath(x,y)测试x,y是否在上述路径内。



      这里是使用context.isPointInPath

      的mouseMove处理程序

        handleMouseMove(e){

      //如果mouseIsDown标志没有设置,没有工作

      if(!mouseIsDown){return; }
      // get mouseX / mouseY

      mouseX = parseInt(e.clientX-offsetX);
      mouseY = parseInt(e.clientY-offsetY);

      //在ships数组中的每个ship
      //使用context.isPointInPath测试是否被拖动

      for(var i = 0; i< ships.length; i ++){
      var ship = ships [i];
      drawShip(ship);
      if(ctx.isPointInPath(lastX,lastY)){

      //如果这艘船被拖动,
      //通过鼠标位置从lastXY改变到currentXY

      ship.x + =(mouseX-lastX);
      ship.y + =(mouseY-lastY);
      ship.right = ship.x + ship.width;
      ship.bottom = ship.y + ship.height;
      }
      }

      //将lastXY更新为当前鼠标位置
      lastX = mouseX;
      lastY = mouseY;

      //绘制所有船舶的新位置
      drawAllShips();
      }

      注意增强效果:




      • 在生产中,您需要让mouseMove仅保存鼠标位置。

      • 然后,另一个过程检索保存的位置,




      p>这里是代码和小提琴: http://jsfiddle.net/m1erickson/sEBAC/ p>

       <!doctype html> 
      < html>
      < head>
      < link rel =stylesheettype =text / cssmedia =allhref =css / reset.css/> <! - reset css - >
      < script type =text / javascriptsrc =http://code.jquery.com/jquery.min.js>< / script>

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

      < script>
      $(function(){

      var canvas = document.getElementById(canvas);
      var ctx = canvas.getContext(2d);
      ctx.strokeStyle =lightgray;

      var canvasOffset = $(#canvas)。offset();
      var offsetX = canvasOffset.left;
      var offsetY = canvasOffset .top;

      var mouseIsDown = false;
      var lastX = 0;
      var lastY = 0;

      var ships = [];

      // make some ship
      makeShip(20,30,50,25,skyblue);
      makeShip(20,100,30,25,skyblue);
      makeShip(20,170,50,25,salmon);
      makeShip(20,240,30,25,salmon);

      function makeShip(x,y,width, fill){
      var ship = {
      x:x,
      y:y,
      width:width,
      height:height,
      right:x + width ,
      bottom:y + height,
      fill:fill
      }
      ships.push(ship);
      return(ship);
      }

      drawAllShips();

      function drawAllShips(){
      ctx.clearRect(0,0,canvas.width,canvas.height);
      for(var i = 0; i< ships.length; i ++){
      var ship = ships [i]
      drawShip(ship);
      ctx.fillStyle = ship.fill;
      ctx.fill();
      ctx.stroke();
      }
      }

      function drawShip(ship){
      ctx.beginPath();
      ctx.moveTo(ship.x,ship.y);
      ctx.lineTo(ship.right,ship.y);
      ctx.lineTo(ship.right + 10,ship.y + ship.height / 2);
      ctx.lineTo(ship.right,ship.bottom);
      ctx.lineTo(ship.x,ship.bottom);
      ctx.closePath();
      }

      function handleMouseDown(e){
      mouseX = parseInt(e.clientX-offsetX);
      mouseY = parseInt(e.clientY-offsetY);

      //这里的mousedown东西
      lastX = mouseX;
      lastY = mouseY;
      mouseIsDown = true;

      }

      function handleMouseUp(e){
      mouseX = parseInt(e.clientX-offsetX);
      mouseY = parseInt(e.clientY-offsetY);

      // mouseup stuff here
      mouseIsDown = false;
      }

      function handleMouseMove(e){
      if(!mouseIsDown){return; }

      mouseX = parseInt(e.clientX-offsetX);
      mouseY = parseInt(e.clientY-offsetY);

      //这里的mousemove东西
      for(var i = 0; i< ships.length; i ++){
      var ship = ships [i]
      drawShip(ship);
      if(ctx.isPointInPath(lastX,lastY)){
      ship.x + =(mouseX-lastX);
      ship.y + =(mouseY-lastY);
      ship.right = ship.x + ship.width;
      ship.bottom = ship.y + ship.height;
      }
      }
      lastX = mouseX;
      lastY = mouseY;
      drawAllShips();
      }

      $(#canvas)。mousedown(function(e){handleMouseDown(e);});
      $(#canvas)。mousemove(function(e){handleMouseMove(e);});
      $(#canvas)mouseup(function(e){handleMouseUp(e);});

      }); // end $(function(){});
      < / script>

      < / head>

      < body>
      < canvas id =canvaswidth = 300 height = 300>< / canvas>
      < / body>
      < / html>


      I just started learning html5 and I am trying to create a battleship interface with draggable ships. I need help making my dragging methods work. I am purposely not using a library because I need make the ships draggable over another canvas interface (the battleship board), which I could not figure out how to do with the Kinetic library. I feel like I am close, but I cannot figure out the last bit. The ships should be smoothly dragged but they seem to snap to the location of the mouse when clicked...

      Here is my clode:

      <!doctype html>
      <html>
          <head>
              <meta charset="UTF-8" />
              <title>Canvas Drag and Drop Test</title>
          </head>
          <body>
              <section>
      
                  <div align=center>
                      <canvas id="canvas" width="550" height="550">
                          This text is displayed if your browser does not support HTML5 Canvas.
                      </canvas>
                  </div>
      
                  <script type="text/javascript">
                      var canvas;
                      var ctx;
                      var x = 75;
                      var y = 50;
                      var WIDTH = 550;
                      var HEIGHT = 550;
                      var dragok = false;
                      var ships = [];
                      var ship;
                      var shipFill = "#FF0000";
                      //Definitions
                      //Draggable Carrier
                      var caRectX = 100;
                      var caRectY = 50;
                      var caRectHeight = 50;
                      var caRectWidth = 5 * 50;
                      var carrier = {
                          x : caRectX,
                          y : caRectY,
                          width : caRectWidth,
                          height : caRectHeight,
                          fill : shipFill,
                          dragging : false,
                          offsetX : 0,
                          offsetY : 0,
      
                      };
                      ships.push(carrier);
                      //Draggable Battleship
                      var bsRectX = 100;
                      var bsRectY = 150;
                      var bsRectHeight = 50;
                      var bsRectWidth = 4 * 50;
      
                      var battleship = {
                          x : bsRectX,
                          y : bsRectY,
                          width : bsRectWidth,
                          height : bsRectHeight,
                          fill : shipFill,
                          dragging : false,
                          offsetX : 0,
                          offsetY : 0,
      
                      };
                      ships.push(battleship);
      
                      //Draggable Patrolboat
                      var pbRectX = 100;
                      var pbRectY = 250;
                      var pbRectHeight = 50;
                      var pbRectWidth = 2 * 50;
      
                      var patrolboat = {
                          x : pbRectX,
                          y : pbRectY,
                          width : pbRectWidth,
                          height : pbRectHeight,
                          fill : shipFill,
                          dragging : false,
                          offsetX : 0,
                          offsetY : 0,
      
                      };
                      ships.push(patrolboat);
      
                      //Draggable Submarine
                      var suRectX = 100;
                      var suRectY = 350;
                      var suRectHeight = 50;
                      var suRectWidth = 3 * 50;
      
                      var submarine = {
                          x : suRectX,
                          y : suRectY,
                          width : suRectWidth,
                          height : suRectHeight,
                          fill : shipFill,
                          dragging : false,
                          offsetX : 0,
                          offsetY : 0,
      
                      };
                      ships.push(submarine);
      
                      //Draggable destroyer
                      var deRectX = 100;
                      var deRectY = 450;
                      var deRectHeight = 50;
                      var deRectWidth = 3 * 50;
      
                      var destroyer = {
                          x : deRectX,
                          y : deRectY,
                          width : deRectWidth,
                          height : deRectHeight,
                          dragging : false,
                          fill : shipFill
                      };
                      ships.push(destroyer)
      
                      function rect(x, y, w, h) {
                          ctx.beginPath();
                          ctx.rect(x, y, w, h);
                          ctx.closePath();
                          ctx.fill();
                      }
      
                      function clear() {
                          ctx.clearRect(0, 0, WIDTH, HEIGHT);
                      }
      
                      function init() {
                          canvas = document.getElementById("canvas");
                          ctx = canvas.getContext("2d");
                          return setInterval(draw, 10);
                      }
      
                      function draw() {
                          clear();
                          ctx.fillStyle = "#FAF7F8";
                          rect(0, 0, WIDTH, HEIGHT);
                          ctx.fillStyle = "#444444";
                          for (var i = 0; i < ships.length; i++) {
                              rect(ships[i].x, ships[i].y, ships[i].width, ships[i].height);
                          }
                      }
      
                      function myMove(e) {
                          if (ship.dragging) {
                              ship.x = e.pageX - canvas.offsetLeft;
                              ship.y = e.pageY - canvas.offsetTop;
                              draw()
                          }
                      }
      
                      function myDown(e) {
                          ship = getClickedShip(e.pageX,e.pageY);
                          if (ship!=null) {
                              ship.x = e.pageX - canvas.offsetLeft;
                              ship.y = e.pageY - canvas.offsetTop;
                              ship.dragging = true;
                              canvas.onmousemove = myMove();
                          }
                      }
      
                      function myUp() {
                          ship.dragging = false;
                          canvas.onmousemove = null;
                      }
      
                      function getClickedShip(sx,sy){
                          for (var i = 0; i < ships.length; i++){
                              if(sx > (ships[i].x )+ canvas.offsetLeft && sx < (ships[i].x+ships[i].width+ canvas.offsetLeft) && sy > (ships[i].y + canvas.offsetTop) && sy < (ships[i].y+ships[i].height))
                                  return ships[i];
                          }
                      }
                      init();
                      canvas.onmousedown = myDown;
                      canvas.onmouseup = myUp;
      
                  </script>
      
              </section>
          </body>
      </html> 
      

      解决方案

      This is the procedure for making an html shape draggable

      Note that this has been answered before on SO (many times!)

      But this answer illustrates the new context.isPointInPath method to hit-test whether a point is inside an html canvas path.

      Hopefully, this new hit-testing method will be new & useful to the OP and others :)

      Here's the general procedure for dragging shapes in html canvas:

      On mouseDown:

      • save this mouseX position in a variable (lastX)
      • save this mouseY position in a variable (lastY)
      • set the mouseIsDown flag to true

      On mouseUp

      • set the mouseIsDown flag to false

      On mouseMove

      • Hit-test each ship to see if it should be dragged.
      • If the lastX/lastY was inside a ship, that ship is being dragged
      • Move dragging ships by the distance the mouse has just moved

      MouseDown handler code:

      function handleMouseDown(e){
      
        // get the current mouse position relative to the canvas
      
        mouseX=parseInt(e.clientX-offsetX);
        mouseY=parseInt(e.clientY-offsetY);
      
        // save this last mouseX/mouseY
      
        lastX=mouseX;
        lastY=mouseY;
      
        // set the mouseIsDown flag
      
        mouseIsDown=true;
      }
      

      MouseUp handler code:

      function handleMouseUp(e){
      
        // clear the mouseIsDown flag
      
        mouseIsDown=false;
      }
      

      MouseMove handler code:

      This code illustrates using context.isPointInPath to hit-test an html canvas path

      The procedure to do that is:

      • define a path (but not draw it -- no fill, no stroke)
      • use context.isPointInPath(x,y) to test if x,y are inside the path defined above.

      Here's the mouseMove handler using context.isPointInPath

      function handleMouseMove(e){
      
        // if the mouseIsDown flag is’nt set, no work to do
      
        if(!mouseIsDown){ return; }
        // get mouseX/mouseY
      
        mouseX=parseInt(e.clientX-offsetX);
        mouseY=parseInt(e.clientY-offsetY);
      
        // for each ship in the ships array
        // use context.isPointInPath to test if it’s being dragged
      
        for(var i=0;i<ships.length;i++){
            var ship=ships[i];
            drawShip(ship);
            if(ctx.isPointInPath(lastX,lastY)){ 
      
                // if this ship’s being dragged, 
                // move it by the change in mouse position from lastXY to currentXY
      
                ship.x+=(mouseX-lastX);
                ship.y+=(mouseY-lastY);
                ship.right=ship.x+ship.width;
                ship.bottom=ship.y+ship.height;
            }
        }
      
        // update the lastXY to the current mouse position
        lastX=mouseX;
        lastY=mouseY;
      
        // draw all ships in their new positions
        drawAllShips();
      }
      

      Note about enhancing performance:

      • In production, you'll want to have the mouseMove just save the mouse positions.
      • Then have another procedure retrieve those saved positions and do hit-testing/redrawing.
      • That other procedure will probably be inside a timed loop like requestAnimationFrame.

      Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/sEBAC/

      <!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>
      $(function(){
      
          var canvas=document.getElementById("canvas");
          var ctx=canvas.getContext("2d");
          ctx.strokeStyle="lightgray";
      
          var canvasOffset=$("#canvas").offset();
          var offsetX=canvasOffset.left;
          var offsetY=canvasOffset.top;
      
          var mouseIsDown=false;
          var lastX=0;
          var lastY=0;
      
          var ships=[];
      
          // make some ship
          makeShip(20,30,50,25,"skyblue");
          makeShip(20,100,30,25,"skyblue");
          makeShip(20,170,50,25,"salmon");
          makeShip(20,240,30,25,"salmon");
      
          function makeShip(x,y,width,height,fill){
              var ship={
                x:x,
                y:y,
                width:width,
                height:height,
                right:x+width,
                bottom:y+height,
                fill:fill
              }
              ships.push(ship);
              return(ship);
          }
      
          drawAllShips();
      
          function drawAllShips(){
              ctx.clearRect(0,0,canvas.width,canvas.height);
              for(var i=0;i<ships.length;i++){
                  var ship=ships[i]
                  drawShip(ship);
                  ctx.fillStyle=ship.fill;
                  ctx.fill();
                  ctx.stroke();
              }
          }
      
          function drawShip(ship){
              ctx.beginPath();
              ctx.moveTo(ship.x,ship.y);
              ctx.lineTo(ship.right,ship.y);
              ctx.lineTo(ship.right+10,ship.y+ship.height/2);
              ctx.lineTo(ship.right,ship.bottom);
              ctx.lineTo(ship.x,ship.bottom);
              ctx.closePath();
          }
      
          function handleMouseDown(e){
            mouseX=parseInt(e.clientX-offsetX);
            mouseY=parseInt(e.clientY-offsetY);
      
            // mousedown stuff here
            lastX=mouseX;
            lastY=mouseY;
            mouseIsDown=true;
      
          }
      
          function handleMouseUp(e){
            mouseX=parseInt(e.clientX-offsetX);
            mouseY=parseInt(e.clientY-offsetY);
      
            // mouseup stuff here
            mouseIsDown=false;
          }
      
          function handleMouseMove(e){
            if(!mouseIsDown){ return; }
      
            mouseX=parseInt(e.clientX-offsetX);
            mouseY=parseInt(e.clientY-offsetY);
      
            // mousemove stuff here
            for(var i=0;i<ships.length;i++){
                var ship=ships[i];
                drawShip(ship);
                if(ctx.isPointInPath(lastX,lastY)){ 
                    ship.x+=(mouseX-lastX);
                    ship.y+=(mouseY-lastY);
                    ship.right=ship.x+ship.width;
                    ship.bottom=ship.y+ship.height;
                }
            }
            lastX=mouseX;
            lastY=mouseY;
            drawAllShips();
          }
      
          $("#canvas").mousedown(function(e){handleMouseDown(e);});
          $("#canvas").mousemove(function(e){handleMouseMove(e);});
          $("#canvas").mouseup(function(e){handleMouseUp(e);});
      
      }); // end $(function(){});
      </script>
      
      </head>
      
      <body>
          <canvas id="canvas" width=300 height=300></canvas>
      </body>
      </html>
      

      这篇关于如何使HTML5可拖动对象在画布上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆