简体   繁体   中英

How to clear part of canvas?

Here is an example!

I am trying to reset the green arc inside drawValueArc() so that each time you click the change button, the green arc is removed and redrawn. How can I remove it without removing the entire canvas? Also, as an aside, I have noticed that Math.random() * 405 * Math.PI / 180 doesn't actually always result in an arc that fits inside the gray arc, sometimes it is larger than the gray arc, why is this?

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var cx = 150;
var cy = 150;
var startRadians = 135 * Math.PI / 180;
var endRadians = 405 * Math.PI / 180;

//main arc
ctx.beginPath();
ctx.arc(cx, cy, 58, startRadians, endRadians, false);
ctx.strokeStyle="rgb(220,220,220)";
ctx.lineWidth = 38;
ctx.stroke();

$('#setRandomValue').click(function(){
  drawValueArc(Math.random() * 405 * Math.PI / 180);
});


function drawValueArc(val){
  //ctx.clearRect(0, 0, W, H);
  ctx.beginPath();
  ctx.arc(cx, cy, 58, startRadians, val, false);
  ctx.strokeStyle = "green";
  ctx.lineWidth = 38;
  ctx.stroke();
}

Drawing past boundary

The problem you are facing is in first instance the fact you are drawing before and after a 0-degree on the circle. This can be complicated to handle as you need to split in two draws: one for the part up to 0 (360) and one 0 to the remaining part.

There is a simple trick you can use to make this easier to deal with and that is to deal with all angles from 0 and use an offset when you draw.

Demo using redraw base (I moved it to jsfiddle as jsbin did not work for me):

http://jsfiddle.net/3dGLR/

Demo using off-screen canvas

http://jsfiddle.net/AbdiasSoftware/Dg9Jj/

First, some optimizations and settings for the offset:

var startRadians = 0;        //just deal with angles
var endRadians = 300;
var deg2rad = Math.PI / 180; //pre-calculate this to save some cpu cycles
var offset = 122;            //adjust this to modify rotation

We will now let the main function, drawArc() do all calculations for us so we can focus on the numbers - here we also offset the values:

function drawArc(color, start, end) {
    ctx.beginPath();

    ctx.arc(cx, cy, 58,
        (startRadians + offset) * deg2rad,
        (end + offset) * deg2rad, false);

    ctx.strokeStyle = color;
    ctx.lineWidth = 38;
    ctx.stroke();
}

Clearing the previous arc

There are several techniques to clear the previous drawn arc:

  1. You can draw the base arc to an off-screen canvas and use drawImage() to erase the old.
  2. You can do as in the following example, just re-draw it with the base color
  3. As with 2. but subtracting the green arc and draw the base color from the end of the green arc to the end of the base arc.
  4. clearing the whole canvas with fillRect or clearRect .

1 and 3 are the fastest, while 4 is the slowest.

With out re-factored function ( drawArc ) it's as easy as this:

function drawValueArc(val) {
    drawArc("rgb(220,220,220)", startRadians, endRadians);
    drawArc("green", startRadians, val);
}

As everything now is 0-based concerning start we really don't need to give any other argument than 0 to the drawArc instead of startRadians . Use the new offset to offset the start position and adjust the endRadians to where you want it to stop.

As you can see in the demo, using this technique keeps everything in check without the need to draw in split.

Tip: if you notice green artifacts on the edges: this is due to anti-alias. Simply reduce the line width for the green color by 2 pixels (see demo 2, off-screen canvas).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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