2014-02-06 176 views
2

我想要绘制在画布上的绘画中的椭圆选项。我已经部分实现了这一点。问题是我不能得到圆的半径,目前我已经硬编码到15。我也想绘制椭圆(与油漆相同)不是确切的圆。 这是我使用鼠标事件在画布上绘制圆的代码。请帮我用代码实现我上面提到的要求。使用鼠标事件在HTML5画布上绘制圆/椭圆

function tool_circle() { 
     var tool = this; 
     this.started = false; 

     this.mousedown = function (ev) { 
      tool.started = true; 
      tool.x0 = ev._x; 
      tool.y0 = ev._y; 
     }; 

     this.mousemove = function (ev) { 
      if (!tool.started) { 
       return; 
      } 

      context.fillStyle = 'red'; 

      var distance = Math.sqrt(Math.pow(tool.x0 - ev._x, 2) + Math.pow(tool.y0 - ev._y)); 
      context.beginPath(); 

      context.arc(tool.x0, tool.y0,15, 0, Math.PI * 2, false); 
      context.stroke(); 
      context.fill(); 
     }; 

     this.mouseup = function (ev) { 
      if (tool.started) { 
       tool.mousemove(ev); 
       tool.started = false; 
       img_update(); 
      } 
     }; 
    } 

回答

2

下面是如何拖动绘制椭圆的示例。

演示:http://jsfiddle.net/m1erickson/3SFJy/

enter image description here

使用2条贝塞尔曲线来拖动绘制一个椭圆示例代码:

<!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; padding:0px;} 
#canvas{ border:1px solid blue; } 
</style> 

<script> 
$(function(){ 

    var canvas=document.getElementById("canvas"); 
    var ctx=canvas.getContext("2d"); 
    var canvasOffset=$("#canvas").offset(); 
    var offsetX=canvasOffset.left; 
    var offsetY=canvasOffset.top; 
    var startX; 
    var startY; 
    var isDown=false; 

    function drawOval(x,y){ 
     ctx.clearRect(0,0,canvas.width,canvas.height); 
     ctx.beginPath(); 
     ctx.moveTo(startX, startY + (y-startY)/2); 
     ctx.bezierCurveTo(startX, startY, x, startY, x, startY + (y-startY)/2); 
     ctx.bezierCurveTo(x, y, startX, y, startX, startY + (y-startY)/2); 
     ctx.closePath(); 
     ctx.stroke(); 
    } 

    function handleMouseDown(e){ 
     e.preventDefault(); 
     e.stopPropagation(); 
     startX=parseInt(e.clientX-offsetX); 
     startY=parseInt(e.clientY-offsetY); 
     isDown=true; 
    } 

    function handleMouseUp(e){ 
     if(!isDown){ return; } 
     e.preventDefault(); 
     e.stopPropagation(); 
     isDown=false; 
    } 

    function handleMouseOut(e){ 
     if(!isDown){ return; } 
     e.preventDefault(); 
     e.stopPropagation(); 
     isDown=false; 
    } 

    function handleMouseMove(e){ 
     if(!isDown){ return; } 
     e.preventDefault(); 
     e.stopPropagation(); 
     mouseX=parseInt(e.clientX-offsetX); 
     mouseY=parseInt(e.clientY-offsetY); 
     drawOval(mouseX,mouseY); 
    } 

    $("#canvas").mousedown(function(e){handleMouseDown(e);}); 
    $("#canvas").mousemove(function(e){handleMouseMove(e);}); 
    $("#canvas").mouseup(function(e){handleMouseUp(e);}); 
    $("#canvas").mouseout(function(e){handleMouseOut(e);}); 

}); // end $(function(){}); 
</script> 
</head> 
<body> 
    <h4>Drag to create a circle or oval</h4> 
    <canvas id="canvas" width=300 height=300></canvas> 
</body> 
</html> 
+0

@markE你好,我想做同样的事情了移动应用程序(Phonegap包裹)触摸事件。我试过你的代码,只是通过替换mouseup,mousemove与touchstart,touchmove事件。这些事件正在触发,因为我可以看到日志,但不会绘制椭圆/圆。我需要为触摸事件做些什么特别的事情?在此先感谢(我第一次使用画布:)) – hashcoder

5

我会与坊间的答案类似然而,使用贝塞尔曲线将绘制椭圆,但它不会给你你可能需要的确切半径。

对于绘制手动椭圆函数是必要的,而且是相当简单 -

此功能需要一个拐角起点和和终点,并绘制一个椭圆正是该边界内:

Live demo

Snapshot from demo

function drawEllipse(x1, y1, x2, y2) { 

    var radiusX = (x2 - x1) * 0.5, /// radius for x based on input 
     radiusY = (y2 - y1) * 0.5, /// radius for y based on input 
     centerX = x1 + radiusX,  /// calc center 
     centerY = y1 + radiusY, 
     step = 0.01,     /// resolution of ellipse 
     a = step,     /// counter 
     pi2 = Math.PI * 2 - step; /// end angle 

    /// start a new path 
    ctx.beginPath(); 

    /// set start point at angle 0 
    ctx.moveTo(centerX + radiusX * Math.cos(0), 
       centerY + radiusY * Math.sin(0)); 

    /// create the ellipse  
    for(; a < pi2; a += step) { 
     ctx.lineTo(centerX + radiusX * Math.cos(a), 
        centerY + radiusY * Math.sin(a)); 
    } 

    /// close it and stroke it for demo 
    ctx.closePath(); 
    ctx.strokeStyle = '#000'; 
    ctx.stroke(); 
} 

演示也将矩形区域标记为表示椭圆完全位于其中。

绘制

要处理的鼠标操作,可以让你画椭圆,你可以这样做:

var canvas = document.getElementById('myCanvas'), 
    ctx = canvas.getContext('2d'), 
    w = canvas.width, 
    h = canvas.height, 
    x1,     /// start points 
    y1, 
    isDown = false;  /// if mouse button is down 

/// handle mouse down  
canvas.onmousedown = function(e) { 

    /// get corrected mouse position and store as first point 
    var rect = canvas.getBoundingClientRect(); 
    x1 = e.clientX - rect.left; 
    y1 = e.clientY - rect.top; 
    isDown = true; 
} 

/// clear isDown flag to stop drawing 
canvas.onmouseup = function() { 
    isDown = false; 
} 

/// draw ellipse from start point 
canvas.onmousemove = function(e) { 

    if (!isDown) return; 

    var rect = canvas.getBoundingClientRect(), 
     x2 = e.clientX - rect.left, 
     y2 = e.clientY - rect.top; 

    /// clear canvas 
    ctx.clearRect(0, 0, w, h); 

    /// draw ellipse 
    drawEllipse(x1, y1, x2, y2); 
} 

小费可以创建你的主画布上方的顶部帆布做绘图在那里。当鼠标按钮被释放后,将绘图转移到您的主画布。这样,您在绘制新形状时不必重绘所有内容。

希望这会有所帮助!

+0

我看到演示,它很好。但是,它只允许我们画一个圆圈。我可以在画布上绘制尽可能多的圈子吗? – Pawan

+1

@ user130004当然,只需在顶部添加一个用于拖动和绘制的画布。当mouseup将该画布拖回到已存在的主画布上时。如果你想重绘一切,你可以将圆形数据存储在一个数组(中心x,t和半径)中,并从中重绘。 – K3N

+1

@ user130004这里是对上述代码的修改:http://jsfiddle.net/37vge/21/ – K3N

0

下面是我用鼠标拖动画一个椭圆到画布上的方法。

它采用了1半径,而是动态调整,以获得椭圆效果:)

https://jsfiddle.net/richardcwc/wdf9cocz/

//Canvas 
 
var canvas = document.getElementById('canvas'); 
 
var ctx = canvas.getContext('2d'); 
 
//Variables 
 
var scribble_canvasx = $(canvas).offset().left; 
 
var scribble_canvasy = $(canvas).offset().top; 
 
var scribble_last_mousex = scribble_last_mousey = 0; 
 
var scribble_mousex = scribble_mousey = 0; 
 
var scribble_mousedown = false; 
 

 
//Mousedown 
 
$(canvas).on('mousedown', function(e) { 
 
    scribble_last_mousex = parseInt(e.clientX-scribble_canvasx); 
 
\t scribble_last_mousey = parseInt(e.clientY-scribble_canvasy); 
 
    scribble_mousedown = true; 
 
}); 
 

 
//Mouseup 
 
$(canvas).on('mouseup', function(e) { 
 
    scribble_mousedown = false; 
 
}); 
 

 
//Mousemove 
 
$(canvas).on('mousemove', function(e) { 
 
    scribble_mousex = parseInt(e.clientX-scribble_canvasx); 
 
\t scribble_mousey = parseInt(e.clientY-scribble_canvasy); 
 
    if(scribble_mousedown) { 
 
     ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas 
 
     //Save 
 
     ctx.save(); 
 
     ctx.beginPath(); 
 
     //Dynamic scaling 
 
     var scalex = 1*((scribble_mousex-scribble_last_mousex)/2); 
 
     var scaley = 1*((scribble_mousey-scribble_last_mousey)/2); 
 
     ctx.scale(scalex,scaley); 
 
     //Create ellipse 
 
     var centerx = (scribble_last_mousex/scalex)+1; 
 
     var centery = (scribble_last_mousey/scaley)+1; 
 
     ctx.arc(centerx, centery, 1, 0, 2*Math.PI); 
 
     //Restore and draw 
 
     ctx.restore(); 
 
     ctx.strokeStyle = 'black'; 
 
     ctx.lineWidth = 5; 
 
     ctx.stroke(); 
 
    } 
 
    //Output 
 
    $('#output').html('current: '+scribble_mousex+', '+scribble_mousey+'<br/>last: '+scribble_last_mousex+', '+scribble_last_mousey+'<br/>mousedown: '+scribble_mousedown); 
 
});
canvas { 
 
    cursor: crosshair; 
 
    border: 1px solid #000000; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<canvas id="canvas" width="800" height="500"></canvas> 
 
<div id="output"></div>