如何在HTML5中使画布上的绘图可拖动

时间:2014-05-04 00:27:26

标签: javascript html5 canvas

我是HTML5和JavaScript的新手,我知道有很多图书馆可以做到这一点,但我想知道是否有办法只使用普通的javascript。

我有一个画布,当某个地方点击画布时,用户点击的位置会出现一个小红点。我想让每个小点都可拖动,有什么想法吗?感谢。

这是我的代码:

HTML中的

<div id="primal_plane" style="position:absolute; top:100px; left:10px;">
    <canvas id="canvas_prime" onclick="drawDot('canvas_prime')" width="700" height="500"></canvas>
</div>
JS文件中的

function drawDot(plane) {
    var canvas = document.getElementById(plane);
    var context = canvas.getContext("2d");

    context.beginPath();
    context.arc(mouseX * 50, mouseY * 50, 4, 0, 2 * Math.PI, false);

    context.fillStyle = 'green';
    context.fill();

    context.lineWidth = 1;
    context.strokeStyle = 'yellow';
    context.stroke();
}

2 个答案:

答案 0 :(得分:4)

概述您的解决方案:

  • 监听mousedown事件,并且(1)如果鼠标不在圆圈上,则创建一个新圆圈;或者(2)如果鼠标在圆圈上方,则在圆圈上开始拖动操作。
  • 收听mousemove事件,并将拖动的圈子移动自上次mousemove事件后鼠标移动的距离
  • 侦听鼠标事件并停止拖动操作

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

<!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(){

    // canvas related variables
    // references to canvas and its context and its position on the page
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var scrollX=$canvas.scrollLeft();
    var scrollY=$canvas.scrollTop();
    var cw=canvas.width;
    var ch=canvas.height;

    // flag to indicate a drag is in process
    // and the last XY position that has already been processed
    var isDown=false;
    var lastX;
    var lastY;

    // the radian value of a full circle is used often, cache it
    var PI2=Math.PI*2;

    // variables relating to existing circles
    var circles=[];
    var stdRadius=10;
    var draggingCircle=-1;

    // clear the canvas and redraw all existing circles
    function drawAll(){
        ctx.clearRect(0,0,cw,ch);
        for(var i=0;i<circles.length;i++){
            var circle=circles[i];
            ctx.beginPath();
            ctx.arc(circle.x,circle.y,circle.radius,0,PI2);
            ctx.closePath();
            ctx.fillStyle=circle.color;
            ctx.fill();
        }
    }

    function handleMouseDown(e){
      // tell the browser we'll handle this event
      e.preventDefault();
      e.stopPropagation();

      // save the mouse position
      // in case this becomes a drag operation
      lastX=parseInt(e.clientX-offsetX);
      lastY=parseInt(e.clientY-offsetY);

      // hit test all existing circles
      var hit=-1;
      for(var i=0;i<circles.length;i++){
          var circle=circles[i];
          var dx=lastX-circle.x;
          var dy=lastY-circle.y;
          if(dx*dx+dy*dy<circle.radius*circle.radius){
              hit=i;
          }
      }

      // if no hits then add a circle
      // if hit then set the isDown flag to start a drag
      if(hit<0){
          circles.push({x:lastX,y:lastY,radius:stdRadius,color:randomColor()});
          drawAll();
      }else{
          draggingCircle=circles[hit];
          isDown=true;
      }

    }

    function handleMouseUp(e){
      // tell the browser we'll handle this event
      e.preventDefault();
      e.stopPropagation();

      // stop the drag
      isDown=false;
    }

    function handleMouseMove(e){

      // if we're not dragging, just exit
      if(!isDown){return;}

      // tell the browser we'll handle this event
      e.preventDefault();
      e.stopPropagation();

      // get the current mouse position
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // calculate how far the mouse has moved
      // since the last mousemove event was processed
      var dx=mouseX-lastX;
      var dy=mouseY-lastY;

      // reset the lastX/Y to the current mouse position
      lastX=mouseX;
      lastY=mouseY;

      // change the target circles position by the 
      // distance the mouse has moved since the last
      // mousemove event
      draggingCircle.x+=dx;
      draggingCircle.y+=dy;

      // redraw all the circles
      drawAll();
    }

    // listen for mouse events
    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseUp(e);});

    //////////////////////
    // Utility functions

    function randomColor(){ 
        return('#'+Math.floor(Math.random()*16777215).toString(16));
    }


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

答案 1 :(得分:0)

您必须存储创建的点列表,但您必须检查点是否已存在。如果是这样,设置一个布尔标志,用于标识mousedown事件发生时的拖动行为,另一个用于标识被拖动的点。在mouseup事件上清除标志。 mousemove方法应更新存储当前鼠标位置的变量,并更新当前拖动点的位置。使用jQuery。