简体   繁体   English

使用html5画布创建形状后使用鼠标拖动形状

[英]Dragging Shapes using mouse after creating them with html5 canvas

I had drawn some circles on a html canvas my codes looks like this: 我在html画布上绘制了一些圆圈,我的代码如下所示:

Html: 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: 使用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. 我想只使用html5javascript没有其他第三方库。 Is there any way to do this ?? 有没有办法做到这一点? any help would be great...... 任何帮助都会很棒......

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. 这通常通过在javascript对象中定义每个圆或矩形并将所有这些形状保存在shapes []数组中来完成。

// 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. 然后你可以在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. 您可以使用鼠标事件功能(myDown,myUp,myMove)进行拖动。

  • 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. 在mousedown事件(由myDown函数处理)时,您测试每个形状以查看鼠标是否在阵列中的一个形状内。 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. 如果鼠标位于1+形状内,则在这些1+形状上设置isDragging标志,并设置dragok标志以指示您需要跟踪鼠标以进行拖动。

  • 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. 在鼠标移动事件(由myMove函数处理)后,您可以移动任何被拖动的形状,即自上一次鼠标移动后鼠标拖动的距离。

  • Upon a mouseup event (handled by the myUp function), you stop the dragging operation by clearing the dragok flag. 在mouseup事件(由myUp函数处理)时,您可以通过清除dragok标志来停止拖动操作。

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(rx,ry,r.width,r.height); } // draw a single rect function circle(c) { ctx.fillStyle=c.fill; ctx.beginPath(); ctx.arc(cx,cy,cr,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>sx && mx<s.x+s.width && my>sy && my<s.y+s.height){ // if yes, set that rects isDragging=true dragok=true; s.isDragging=true; } }else{ var dx=sx-mx; var dy=sy-my; // test if the mouse is inside this circle if(dx*dx+dy*dy<sr*sr){ 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM