最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dragging Shapes using mouse after creating them with html5 canvas - Stack Overflow

programmeradmin4浏览0评论

I had drawn some circles on a html canvas my codes looks like this:

Html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>WebTunings</title>
    <link href="index.css" rel="stylesheet">
    <script src="index.js"></script>
</head>

<body>
<canvas id="canvas" width="600" height="600"></canvas>

<div id="controls">
    <p><label>Fill: <input id="fillBox" type="checkbox" checked="checked"></label></p>

    <div class="lightBorder">
        <p><input type="radio" name="shape" value="circle" checked="checked">Circle</p>
    </div>

    <p><input id="clearCanvas" type="button" value="reset"></p>
</div>

</body>
</html>

Javascript:

var canvas,
    context,
    dragging = false,
    dragStartLocation,
    snapshot;


function getCanvasCoordinates(event) {
    var x = event.clientX - canvas.getBoundingClientRect().left,
        y = event.clientY - canvas.getBoundingClientRect().top;

    return {x: x, y: y};
}

function takeSnapshot() {
    snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
}

function restoreSnapshot() {
    context.putImageData(snapshot, 0, 0);
}

function drawCircle(position) {
    var radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2));
    context.beginPath();
    context.arc(dragStartLocation.x, dragStartLocation.y, radius, 0, 2 * Math.PI, false);
    context.fillStyle = getRndColor();
}


function draw(position) {

    var fillBox = document.getElementById("fillBox"),
        shape = document.querySelector('input[type="radio"][name="shape"]:checked').value;
    if (shape === "circle") {
        drawCircle(position);
    }

    if (fillBox.checked) {
        context.fill();
    } else {
        context.stroke();
    }
}

function dragStart(event) {
    dragging = true;
    dragStartLocation = getCanvasCoordinates(event);
    takeSnapshot();
}

function drag(event) {
    var position;
    if (dragging === true) {
        restoreSnapshot();
        position = getCanvasCoordinates(event);
        draw(position, "polygon");
    }
}

function dragStop(event) {
    dragging = false;
    restoreSnapshot();
    var position = getCanvasCoordinates(event);
    draw(position, "polygon");
}

function getRndColor() {
    var r = 255*Math.random()|0,
        g = 255*Math.random()|0,
        b = 255*Math.random()|0;
    return 'rgb(' + r + ',' + g + ',' + b + ')';
}

function eraseCanvas(){
    context.clearRect(0, 0, canvas.width, canvas.height);
}


function init() {
    canvas = document.getElementById("canvas");
    context = canvas.getContext('2d');
    context.strokeStyle = 'green';
    context.lineWidth = 4;
    context.lineCap = 'round';
    clearCanvas = document.getElementById("clearCanvas");

    canvas.addEventListener('mousedown', dragStart, false);
    canvas.addEventListener('mousemove', drag, false);
    canvas.addEventListener('mouseup', dragStop, false);
    clearCanvas.addEventListener("click", eraseCanvas, false);

}

window.addEventListener('load', init, false);

Now what i wanted to do is whenever i draw multiple circles i wanted to select one random circle and drag it to another place on the canvas, applicable for each of the circles. I want to use only html5 and javascript no other third party libraries. Is there any way to do this ?? any help would be great......

I had drawn some circles on a html canvas my codes looks like this:

Html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>WebTunings</title>
    <link href="index.css" rel="stylesheet">
    <script src="index.js"></script>
</head>

<body>
<canvas id="canvas" width="600" height="600"></canvas>

<div id="controls">
    <p><label>Fill: <input id="fillBox" type="checkbox" checked="checked"></label></p>

    <div class="lightBorder">
        <p><input type="radio" name="shape" value="circle" checked="checked">Circle</p>
    </div>

    <p><input id="clearCanvas" type="button" value="reset"></p>
</div>

</body>
</html>

Javascript:

var canvas,
    context,
    dragging = false,
    dragStartLocation,
    snapshot;


function getCanvasCoordinates(event) {
    var x = event.clientX - canvas.getBoundingClientRect().left,
        y = event.clientY - canvas.getBoundingClientRect().top;

    return {x: x, y: y};
}

function takeSnapshot() {
    snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
}

function restoreSnapshot() {
    context.putImageData(snapshot, 0, 0);
}

function drawCircle(position) {
    var radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2));
    context.beginPath();
    context.arc(dragStartLocation.x, dragStartLocation.y, radius, 0, 2 * Math.PI, false);
    context.fillStyle = getRndColor();
}


function draw(position) {

    var fillBox = document.getElementById("fillBox"),
        shape = document.querySelector('input[type="radio"][name="shape"]:checked').value;
    if (shape === "circle") {
        drawCircle(position);
    }

    if (fillBox.checked) {
        context.fill();
    } else {
        context.stroke();
    }
}

function dragStart(event) {
    dragging = true;
    dragStartLocation = getCanvasCoordinates(event);
    takeSnapshot();
}

function drag(event) {
    var position;
    if (dragging === true) {
        restoreSnapshot();
        position = getCanvasCoordinates(event);
        draw(position, "polygon");
    }
}

function dragStop(event) {
    dragging = false;
    restoreSnapshot();
    var position = getCanvasCoordinates(event);
    draw(position, "polygon");
}

function getRndColor() {
    var r = 255*Math.random()|0,
        g = 255*Math.random()|0,
        b = 255*Math.random()|0;
    return 'rgb(' + r + ',' + g + ',' + b + ')';
}

function eraseCanvas(){
    context.clearRect(0, 0, canvas.width, canvas.height);
}


function init() {
    canvas = document.getElementById("canvas");
    context = canvas.getContext('2d');
    context.strokeStyle = 'green';
    context.lineWidth = 4;
    context.lineCap = 'round';
    clearCanvas = document.getElementById("clearCanvas");

    canvas.addEventListener('mousedown', dragStart, false);
    canvas.addEventListener('mousemove', drag, false);
    canvas.addEventListener('mouseup', dragStop, false);
    clearCanvas.addEventListener("click", eraseCanvas, false);

}

window.addEventListener('load', init, false);

Now what i wanted to do is whenever i draw multiple circles i wanted to select one random circle and drag it to another place on the canvas, applicable for each of the circles. I want to use only html5 and javascript no other third party libraries. Is there any way to do this ?? any help would be great......

Share Improve this question asked Feb 2, 2015 at 18:56 ProloyProloy 3631 gold badge3 silver badges15 bronze badges 2
  • can you give jsfiddle link?? – AL-zami Commented Feb 2, 2015 at 19:15
  • this is the jsfiddle link – Proloy Commented Feb 2, 2015 at 19:32
Add a comment  | 

1 Answer 1

Reset to default 25

Canvas does not "remember" where it drew your circles or rectangles, so you must do the remembering. This is typically done by defining each circle or rect in a javascript object and saving all those shapes in a shapes[] array.

// an array of objects that define different shapes
var shapes=[];
// define 2 rectangles
shapes.push({x:10,y:100,width:30,height:30,fill:"#444444",isDragging:false});
shapes.push({x:80,y:100,width:30,height:30,fill:"#ff550d",isDragging:false});
// define 2 circles
shapes.push({x:150,y:100,r:10,fill:"#800080",isDragging:false});
shapes.push({x:200,y:100,r:10,fill:"#0c64e8",isDragging:false});

Then you can listen for mouse events in javascript. When the browser issues a mouse event you can call a function in response. This is how to tell the browser you want to listen to mouse events:

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

You can use the mouse event functions (myDown, myUp, myMove) to do your dragging.

  • Upon a mousedown event (handled by the myDown function), you test each shape to see if the mouse is inside one of the shapes in your array. If the mouse is inside 1+ shapes, set an isDragging flag on those 1+ shapes and also set a dragok flag to indicate that you need to track the mouse for dragging purposes.

  • Upon a mousemove event (handled by the myMove function), you move any shape that is being dragged by the distance the mouse has dragged since the previous mousemove.

  • Upon a mouseup event (handled by the myUp function), you stop the dragging operation by clearing the dragok flag.

Here's annotated example code and a Demo:

// 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 shapes
var shapes=[];
// define 2 rectangles
shapes.push({x:10,y:100,width:30,height:30,fill:"#444444",isDragging:false});
shapes.push({x:80,y:100,width:30,height:30,fill:"#ff550d",isDragging:false});
// define 2 circles
shapes.push({x:150,y:100,r:10,fill:"#800080",isDragging:false});
shapes.push({x:200,y:100,r:10,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(r) {
  ctx.fillStyle=r.fill;
  ctx.fillRect(r.x,r.y,r.width,r.height);
}

// draw a single rect
function circle(c) {
  ctx.fillStyle=c.fill;
  ctx.beginPath();
  ctx.arc(c.x,c.y,c.r,0,Math.PI*2);
  ctx.closePath();
  ctx.fill();
}

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

// redraw the scene
function draw() {
  clear();
  // redraw each shape in the shapes[] array
  for(var i=0;i<shapes.length;i++){
    // decide if the shape is a rect or circle
    // (it's a rect if it has a width property)
    if(shapes[i].width){
      rect(shapes[i]);
    }else{
      circle(shapes[i]);
    };
  }
}


// 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 shape to see if mouse is inside
  dragok=false;
  for(var i=0;i<shapes.length;i++){
    var s=shapes[i];
    // decide if the shape is a rect or circle               
    if(s.width){
      // test if the mouse is inside this rect
      if(mx>s.x && mx<s.x+s.width && my>s.y && my<s.y+s.height){
        // if yes, set that rects isDragging=true
        dragok=true;
        s.isDragging=true;
      }
    }else{
      var dx=s.x-mx;
      var dy=s.y-my;
      // test if the mouse is inside this circle
      if(dx*dx+dy*dy<s.r*s.r){
        dragok=true;
        s.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<shapes.length;i++){
    shapes[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<shapes.length;i++){
      var s=shapes[i];
      if(s.isDragging){
        s.x+=dx;
        s.y+=dy;
      }
    }

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

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

  }
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<h4>Drag one or more of the shapes</h4>
<canvas id="canvas" width=300 height=300></canvas>

发布评论

评论列表(0)

  1. 暂无评论