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

javascript - Drawing circleellipse on HTML5 canvas using mouse events - Stack Overflow

programmeradmin1浏览0评论

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.

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 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.

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();
        }
    };
}
Share Improve this question edited Dec 8, 2020 at 3:56 Elijah M 83511 silver badges24 bronze badges asked Feb 6, 2014 at 5:27 hampi2017hampi2017 7213 gold badges14 silver badges36 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 10

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.

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/

Example code using 2 Bezier curves to drag-draw an oval:

<!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 :)

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>

发布评论

评论列表(0)

  1. 暂无评论