使用鼠标事件在HTML5画布上绘制圆/椭圆

时间:2014-02-06 05:27:35

标签: javascript canvas

我想在画布中使用类似椭圆选项的东西来绘制画布。我已经部分实现了这一点。问题是我无法获得圆的半径,目前我已将其硬编码为15.此外,我想绘制椭圆(与油漆相同)不是精确的圆。 这是我使用鼠标事件在画布上绘制圆圈的代码。请帮助我使用代码来实现我上面提到的要求。

 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();
            }
        };
    }

3 个答案:

答案 0 :(得分:6)

我会像markE的回答一样,但是使用Bezier曲线会绘制椭圆,但它不会给你你可能需要的确切半径。

为此需要绘制手动椭圆的函数,而且它非常简单 -

此函数将采用角点起点和终点,并在该边界内绘制一个完全的椭圆:

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);
}

提示可以在主画布顶部创建顶部画布,并在那里进行绘制。释放鼠标按钮后,将绘图传输到主画布。这样,在绘制新形状时,您无需重绘所有内容。

希望这有帮助!

答案 1 :(得分: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>

答案 2 :(得分: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);
	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);
	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>