admin管理员组

文章数量:1333392

I need to have a function to draw several circles on canvas starting with mousedown at center=x,y and dragging mouse to deltaX,deltaY thus creating radius r, for each circle. The circles cannot have a fill (need them transparent) so the user can see clearly where the circles intercept. My current code draws circles WHILE the mouse is dragged, and that's expected, but it also LEAVES those extra circles behind. I need to leave only the circle on mouseup. Any help is appreciated. Thank you :).

<html>

<head>

</head>

<body style="margin:0">
<canvas id="canvas" width="500" height="500" style="border:1px solid"></canvas>

<script>

var canvas=document.getElementById('canvas');
var context=canvas.getContext('2d');
var radius=50;
var nStartX = 0;
var nStartY = 0;
var bIsDrawing = false;
var putPoint = function(e){
  nStartX = e.clientX;nStartY = e.clientY;
  bIsDrawing = true;
  radius = 0;
}
var drawPoint = function(e){
  if(!bIsDrawing)
    return;
  
  var nDeltaX = nStartX - e.clientX;
  var nDeltaY = nStartY - e.clientY;
  radius = Math.sqrt(nDeltaX * nDeltaX + nDeltaY * nDeltaY)
  context.beginPath();
  context.arc(nStartX, nStartY, radius, 0, Math.PI*2);
  context.strokeStyle="#000000";
  //context.fillStyle="#FFFFFF";
  context.fillStyle = 'rgba(0, 0, 0, 0)';
  context.stroke();
  context.fill();
}
var stopPoint = function(e){
  //context.clip();
  //context.clearRect(0, 0, canvas.width, canvas.height);
  bIsDrawing = false;
}
canvas.addEventListener('mousedown',putPoint);
canvas.addEventListener('mousemove',drawPoint);
canvas.addEventListener('mouseup',stopPoint);

</script>
</body>

</html>

I need to have a function to draw several circles on canvas starting with mousedown at center=x,y and dragging mouse to deltaX,deltaY thus creating radius r, for each circle. The circles cannot have a fill (need them transparent) so the user can see clearly where the circles intercept. My current code draws circles WHILE the mouse is dragged, and that's expected, but it also LEAVES those extra circles behind. I need to leave only the circle on mouseup. Any help is appreciated. Thank you :).

<html>

<head>

</head>

<body style="margin:0">
<canvas id="canvas" width="500" height="500" style="border:1px solid"></canvas>

<script>

var canvas=document.getElementById('canvas');
var context=canvas.getContext('2d');
var radius=50;
var nStartX = 0;
var nStartY = 0;
var bIsDrawing = false;
var putPoint = function(e){
  nStartX = e.clientX;nStartY = e.clientY;
  bIsDrawing = true;
  radius = 0;
}
var drawPoint = function(e){
  if(!bIsDrawing)
    return;
  
  var nDeltaX = nStartX - e.clientX;
  var nDeltaY = nStartY - e.clientY;
  radius = Math.sqrt(nDeltaX * nDeltaX + nDeltaY * nDeltaY)
  context.beginPath();
  context.arc(nStartX, nStartY, radius, 0, Math.PI*2);
  context.strokeStyle="#000000";
  //context.fillStyle="#FFFFFF";
  context.fillStyle = 'rgba(0, 0, 0, 0)';
  context.stroke();
  context.fill();
}
var stopPoint = function(e){
  //context.clip();
  //context.clearRect(0, 0, canvas.width, canvas.height);
  bIsDrawing = false;
}
canvas.addEventListener('mousedown',putPoint);
canvas.addEventListener('mousemove',drawPoint);
canvas.addEventListener('mouseup',stopPoint);

</script>
</body>

</html>

Share Improve this question asked Apr 14, 2016 at 12:20 SobraSobra 631 silver badge4 bronze badges 2
  • 3 Use two canvas. On the top one you draw the circle that's currently handled, clearing it on interval. On the bottom one you draw the final result without clearing. Or else keep track of all circles and repaint constantly. – Yoshi Commented Apr 14, 2016 at 12:24
  • I also have a fiddle for that if your circle can be ellipse jsfiddle/xXqsu/2 – Hugo S. Mendes Commented Apr 14, 2016 at 12:34
Add a ment  | 

2 Answers 2

Reset to default 4

You need to keep track of the circles (and other objects) that you've drawn - one way would be to push them into an array on mouseup. Then each draw should be preceded by a canvas clear and redraw of the saved circles.

var circles = [];
...

Clearing the canvas

...
radius = Math.sqrt(nDeltaX * nDeltaX + nDeltaY * nDeltaY)
context.clearRect(0, 0, canvas.width, canvas.height);
...

Drawing saved circles

...
context.fill();
// drawing saved circles
circles.forEach(function(circle){
    context.beginPath();
    context.arc(circle.nStartX, circle.nStartY, circle.radius, 0, Math.PI*2);
    context.strokeStyle="#000000";
    context.fillStyle="#FFFFFF";
    context.fillStyle = 'rgba(0, 0, 0, 0)';
    context.stroke();
    context.fill();
})
...

Saving pleted circles

...
bIsDrawing = false;
// saving pleted circles
var nDeltaX = nStartX - e.clientX;
var nDeltaY = nStartY - e.clientY;
radius = Math.sqrt(nDeltaX * nDeltaX + nDeltaY * nDeltaY);
circles.push({ nStartX: nStartX, nStartY: nStartY, radius: radius });
...

Fiddle - https://jsfiddle/9x77sg2h/

To build on my ment, here's an example of keeping track of all circles. It's basically the same as potatopeelings answer, though I wanted to show the usage of requestAnimationFrame to redraw independently of user-behavior.

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var circles = [];
var currentCircle = null;

requestAnimationFrame(function draw() {
    drawCircles();
    requestAnimationFrame(draw);
});

function putPoint(e){
    currentCircle = {
        center: {
            x: e.clientX - this.offsetLeft + window.scrollX,
            y: e.clientY - this.offsetTop + window.scrollY
        }
    };
}

function drawPoint(e)
{
    if (null !== currentCircle) {
        currentCircle.radius = Math.sqrt(
              Math.pow(currentCircle.center.x - e.clientX + this.offsetLeft - window.scrollX, 2)
            + Math.pow(currentCircle.center.y - e.clientY + this.offsetTop - window.scrollY, 2)
        );
    }
}

function drawCircles()
{
    // clear canvas
    context.clearRect(0, 0, canvas.width, canvas.height);

    // previous
    circles.forEach(drawCircle);

    // current
    if (null !== currentCircle) {
        drawCircle(currentCircle);
    }
}

function drawCircle(circle)
{
    context.save();
    context.beginPath();
    context.arc(circle.center.x, circle.center.y, circle.radius, 0, 2 * Math.PI);
    context.strokeStyle= '#000000';
    context.fillStyle = 'rgba(0, 0, 0, 0)';
    context.stroke();
    context.fill();
    context.restore();
}

function stopPoint()
{
    if (null !== currentCircle) {
        circles.push(currentCircle);
        currentCircle = null;
    }
}

canvas.addEventListener('mousedown', putPoint, false);
canvas.addEventListener('mousemove', drawPoint, false);
canvas.addEventListener('mouseup', stopPoint, false);
<canvas id="canvas" width="500" height="500" style="border:1px solid"></canvas>

本文标签: htmlJavascript HTML5 Canvas drawing transparent circlesStack Overflow