简体   繁体   English

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

[英]Drawing circle/ellipse on HTML5 canvas using mouse events

I want something like ellipse option in paint for drawing on my canvas.我想要在画布上绘制类似椭圆选项的油漆。 I have achieved this partially.我已经部分实现了这一点。 The problem is I am not able to get radius of circle;问题是我无法获得圆的半径; currently I have hard coded it to 15. Also I want to draw an ellipse (like in paint) not exact circle.目前我已将其硬编码为 15。此外,我想绘制一个椭圆(如油漆中)而不是精确的圆。

This is my code for drawing circle on canvas using mouse events.这是我使用鼠标事件在画布上绘制圆圈的代码。 Please help me with code to achieve my above mentioned requirements.请帮助我编写代码以实现我上述要求。

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

I would something similar as with markE's answer however, using Bezier curve will draw ellipses but it won't give you the exact radius that you probably would need.我会与markE的答案类似,但是,使用贝塞尔曲线会绘制椭圆,但不会为您提供您可能需要的确切半径。

For that a function to draw a manual ellipse is needed, and it's rather simple -为此,需要一个手动绘制椭圆的函数,而且相当简单——

This function will take a corner start point and and end point and draw an ellipse exactly within that boundary:此函数将取一个角起点和终点,并在该边界内精确绘制一个椭圆:

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

The demo marks the rectangle area too to show that the ellipse is exactly within it.该演示也标记了矩形区域,以显示椭圆正好在其中。

Draw

To handle mouse operation that will let you draw the ellipse you can do:要处理让您绘制椭圆的鼠标操作,您可以执行以下操作:

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

A tip can be to create a top canvas on top of your main canvas and do the drawing itself there.一个提示可以是在主画布上创建一个顶部画布并在那里进行绘图。 When mouse button is released then transfer the drawing to your main canvas.释放鼠标按钮后,将绘图传输到主画布。 This way you don't have to redraw everything when drawing a new shape.这样,您在绘制新形状时不必重新绘制所有内容。

Hope this helps!希望这可以帮助!

Here's an example of how to drag-draw an oval.下面是如何拖动绘制椭圆的示例。

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

在此处输入图片说明

Example code using 2 Bezier curves to drag-draw an oval:使用 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>

Here's my way of drawing an ellipse onto a canvas with mouse drag.这是我通过鼠标拖动在画布上绘制椭圆的方法。

It uses radius of 1, but dynamic scaling to get the ellipse effect :)它使用半径为 1,但动态缩放以获得椭圆效果:)

https://jsfiddle.net/richardcwc/wdf9cocz/ 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>

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

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