JavaScript: How to get the center of a pie slice? - javascript

Hi I am trying to create a simple pie chart using the HTML canvas element.
I found a nice tutorial on the web and starting to learn how it is done.
Now I want to add some text and I need to know how to find the center of each slice in the pie where the text can be added.
Here is the loop code:
for ( i = 0; i < t.data.length; i++ )
{
label = t.data[i].label;
value = t.data[i].value;
color = t.data[i].color;
ctx.lineWidth = t.strokeLineWidth;
ctx.strokeStyle = "#FFFFFF";
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo( centerX, centerY );
ctx.arc( centerX, centerY, radius, lastEnd, lastEnd + ( Math.PI * 2 * ( value / total ) ), false );
ctx.lineTo( centerX, centerY );
ctx.fill();
ctx.stroke();
lastEnd += Math.PI * 2 * ( value / total );
}

Simply treat the slices as triangles, i.e. ignore the arc.
There are a bunch of different ways to define "the center". Have a look at the wikipedia article on how to do this. You'll probably want the intersection of the angle bisectors, which is called the incenter. This is the center of the inscribed circle, and it gives the most space for text.
The coordinates of the incenter is calculated as follows:
Let (xa,ya), (xb,yb), and (xc,yc) be the coordinates of the three corners of the triangle, and let a, b, and c be the lengths of the opposing sides. I.e., a = ||(xb,yb)-(xc,yc)||, etc. Finally, let P=a+b+c. Then the center is
((a xa + b xb + c xc)/P, (a ya + b yb + c yc)/P).
Cheers,

The math is more complicated than I can do quickly. You might try the rgraph library.
http://www.rgraph.net/docs/pie.html

Related

Reflection vector calculation not working properly

I have set up a sort of a reflection vector simulator here: https://jsfiddle.net/ahvonenj/1re5n8jg/
I am using Vectorious for my vector calculations and objects.
The program kind of works:
I am casting rays from the middle of the canvas towards the mouse cursor. I can successfully detect ray intersections with walls and the point of the intersection on the wall (red dots). I am also able to get the middle point of the wall (blue dots). I THINK that when I normalize the middle point vector, that is the normal of the wall.
Here is the part that listens to mouse movement, casts the ray, gets the intersection and tried to calculate the reflection vectors ( I have added some comments regarding the actual calculations for the reflection vector and what I think I am calculating):
Global.$canvas.addEventListener('mousemove', function(e)
{
var ctx = Global.ctx;
var rect = canvas.getBoundingClientRect();
Global.Mouse = new Vector([e.clientX - rect.left, e.clientY - rect.top]);
var v1 = Vector.subtract(Global.Mouse, Global.Canvas.Center).normalize();
var mag = Vector.subtract(Global.Canvas.Center, Global.Mouse).magnitude();
var ray = Vector.scale(v1, mag * 3).add(Global.Canvas.Center);
ctx.clearRect(0, 0, 600, 600);
ctx.beginPath();
for(var i = 0; i < Global.Canvas.Walls.length; i++)
{
var wall = Global.Canvas.Walls[i];
if(rayIntersectsWith(wall, [Global.Canvas.Center, ray]))
{
// x_1' - x_0 = v - 2(v dot ñ)ñ
// Where ñ = Normal of the wall
// and v = Vector from center to the point of intersection with the wall
// http://mathworld.wolfram.com/Reflection.html
// This is the point on wall where the intersection happens
var point = rayIntersectionPoint(wall, [Global.Canvas.Center, ray])
// This is the full ray cast from center towards the mouse
var d = ray;
// This (probably) is the vector from center to the intersection point on the wall
var v = Vector.subtract(point, Global.Canvas.Center);
// This represents the wall vector, or a middle of the wall (blue dot on wall)
var wallVector = Vector.add(wall[0], wall[1]).scale(0.5);
// This is supposed to be the normal of the wall
var wallNormal = Vector.normalize(wallVector);
// This is supposed to be the 2(v dot ñ) part of the equation
var v_dot_n = Vector.dot(v, wallNormal) * 2;
// This is supposed to be the v_dot_n * ñ of the equation
var v_dot_n_scaled_by_n = Vector.scale(wallNormal, v_dot_n);
// This is supposed to be the v - v_dot_n_scale_by_n part of the equation
var dot_vector = Vector.subtract(v, v_dot_n_scaled_by_n);
console.log('w1', wall[0].x, wall[0].y, ", w2", wall[1].x, wall[1].y)
var bounceVector = dot_vector
console.log(wallVector.x, wallVector.y, wallVector.magnitude())
console.log(wallNormal.x, wallNormal.y, wallNormal.magnitude())
ctx.beginPath();
ctx.arc(wallVector.x, wallVector.y, Global.isecRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.lineWidth = 0;
ctx.strokeStyle = 'blue';
ctx.beginPath();
ctx.arc(dot_vector.x, dot_vector.y, Global.isecRadius * 1.5, 0, 2 * Math.PI, false);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.lineWidth = 0;
ctx.strokeStyle = 'blue';
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = '#00FF00';
ctx.moveTo(wall[0].x, wall[0].y);
ctx.lineTo(wall[1].x, wall[1].y);
ctx.stroke();
console.log(bounceVector.x, bounceVector.y)
ctx.beginPath();
ctx.arc(bounceVector.x, bounceVector.y, Global.isecRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();
ctx.lineWidth = 0;
ctx.strokeStyle = 'red';
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = '#000000';
ctx.moveTo(point.x, point.y);
ctx.lineTo(bounceVector.x, bounceVector.y);
ctx.stroke();
ctx.beginPath();
ctx.arc(point.x, point.y, Global.isecRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();
ctx.lineWidth = 0;
ctx.strokeStyle = 'red';
}
}
ctx.stroke();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = '#000000';
ctx.moveTo(Global.Canvas.Center.x, Global.Canvas.Center.y);
ctx.lineTo(ray.x, ray.y);
ctx.stroke();
});
My calculations are based on equations found here: http://mathworld.wolfram.com/Reflection.html
But if you try the fiddle, you will notice that the reflection calculations barely work for the angled wall and currently do not work at all for the outside walls, so this is where I need some help.
The equation looks like this:
x_1'- x_0 = v - 2(v·ñ)ñ.
Where x_1´ - x_0 is the reflection vector from the intersection point of the wall to where ever it should be pointing. Probably the same length as v.
v is the vector from x_1 to the intersection point of the wall, so in my code it is named as v and goes from the center to the wall intersection.
ñ is the normal of the wall.
Rest of the equation should also be commented in my code and the variables named accordingly I hope.
I am a bit confused with the stuff subtracted from v in the equation. v dot ñ returns a scalar, which is then multiplied by 2. However ñ is a vector so 2(v dot ñ) must mean scaling vector ñ by the scalar value of 2(v dot ñ)?
Best guess I have been able to conclude from debugging this thing is that the wall normal is most likely note correctly calculated.
From my own Geom library I have.
// v1, v2 are Vec
// reflected vec for line hitting this
// argument line is the line to be reflected
// retVec is the returned resulting vector.
reflectAsVec : function(line, retVec = new Vec()){ // returns a vector...
v2.x = this.p2.x - this.p1.x;
v2.y = this.p2.y - this.p1.y;
v1.x = line.p2.x - line.p1.x;
v1.y = line.p2.y - line.p1.y;
var len = v1.dot(v2.norm()) * 2;
retVec.x = v2.x * len - v1.x;
retVec.y = v2.y * len - v1.y;
return retVec;
},
this is a line with two points p1,p2 defining the ends. Note the v2 is normalised for the last two lines calculating the reflected vec.
The function v2.norm() converts a Vec to a normalised vector as follows
// u is a number
norm : function(){ // normalises this to be a unit length.
u = Math.hypot(this.x,this.y);
this.x /= u;
this.y /= u;
return this; // returns this
},
And for v1.dot(vec)
dot : function(vec){ // get the dot product of this and {avec}
return this.x * vec.x + this.y * vec.y; // returns number
},
Once you have the reflected vector you can create the reflected line from the intercept point and the reflected vector.

plotting random points in circle sector

I have a pie chart in canvas and I wanted to plot random points in each sector of that pie.
I have got the area of each sector. using the arc sector
var arcsector = Math.PI * (2 * sector / total);
var startAngle = (lastend - offset) * (radius/Math.PI);
var endAngle = (lastend + arcsector - offset) * (radius/Math.PI);
var sectorAngle = arcsector * (radius/Math.PI);
var sectorArea = .5 * (sectorAngle*Math.PI/180) * (radius*radius);
How can I randomly plot points within that area?
A pie is a part of a circle, which, with your notations, starts at startAngle and ends at endAngle.
Most simple way to get a random point is to build a random angle (between
startAngle and endAngle) and a random radius, then you have your point with those lines :
var randAngle = startAngle + Math.random()*( endAngle - startAngle );
var randRadius = Math.random()*radius;
var randX = centerX + randRadius * Math.cos(randAngle);
var randY = centerY + randRadius * Math.sin(randAngle);
ctx.fillRect ( randX, randY, 1, 1 ) ;
repeat the number of times required !
The simple approach is to:
Create a temporary arc shape on path
Create a random point
Hit-test the point against the shape and plot if inside
You can create a temporary arc path by doing something like this (adjust to match your situation) (and no need to stroke/fill):
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.arc(cx, cy, radius, startAngle, endAngle);
ctx.closePath();
Then create random points within the bounds of that arc, or just use a very basic approach (which is probably fast enough in most case unless you would need a lot of points) - and the spread is even compared to using a radius based approach:
var randomX = cx + radius * 2 * Math.random() - radius;
var randomY = cy + radius * 2 * Math.random() - radius;
and finally hit-test:
if (ctx.isPointInPath(randomX, randomY)) {
// plot point, count etc.
}
FIDDLE
Update
An even more efficient way to generate random points in the arc shape (and spread them more even) is to draw directly to an off-screen canvas without using any bound checking and no cos/sin operations, which are expensive, and finally composite that on top of your arc shape (or use arc as clip).
// create off-screen canvas
var ocanvas = document.createElement('canvas');
var octx = ocanvas.getContext('2d');
var d;
d = ocanvas.width = ocanvas.height = 300;
octx.fillStyle = '#fff';
while(count) {
var randomX = d * Math.random();
var randomY = d * Math.random();
octx.fillRect(randomX - 1, randomY - 1, 2, 2);
count--;
}
// composite random points with main arc
ctx.globalCompositeOperation = 'source-atop';
ctx.drawImage(ocanvas, 0, 0);
ctx.globalCompositeOperation = 'source-over';
It can be optimized further by having the off-screen canvas represent only the bounds of the arc shape.
FIDDLE
Demo: http://jsfiddle.net/jv6nP/3/
it's not perfect that points are at border and thus their radius being bigger than zero makes them overlap onto other parts of pie. And this also results in them going over black border.
var can = $('#can')[0].getContext('2d'),
border=2,
x=100,
y=75,
r=60,
sRadius= 0,
leadAngle=null,
points= [],
dotRadius=2,
data = {
water:[30,'#5CC5FA'],
earth:[60,'#F0A71F'],
air:[10,'#26EDE3']
};
function reDraw(){
//making border...
can.beginPath();
can.arc(x,y,r+border,0,2*Math.PI);
can.fillStyle='black';
can.fill();
var newAngle=null;
for (var k in data) { //making piechart..
leadAngle = (2*Math.PI)*(data[k][0]/100);
newAngle = sRadius+leadAngle;
calPoints(sRadius,leadAngle,k);
can.beginPath();
can.arc(x,y,r,sRadius,newAngle);
can.lineTo(x,y);
can.fillStyle=data[k][1];
can.fill();
sRadius= newAngle;
}
//calculating points..
function calPoints(s,e,name) {
if (name!='water') return;
var py,px,rAngle,rRad;
for (var i=0; i<15; i++) {
rAngle=s+Math.random()*(e);
rRad = Math.random()*r;
px = (Math.cos(rAngle) * rRad)+x;
py = (Math.sin(rAngle) * rRad)+y;
points.push([px,py]);
}
}
//plotting dots from data...
points.forEach(function(v){
can.beginPath();
can.arc(v[0],v[1],dotRadius,0,2*Math.PI);
can.fillStyle='fff';
can.fill();
});
points=[];
requestAnimationFrame(reDraw);
}
reDraw();

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:
You can draw the base arc to an off-screen canvas and use drawImage() to erase the old.
You can do as in the following example, just re-draw it with the base color
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.
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).

Finding coordinates after canvas Rotation

0 to 0,-70 by this :
ctx.strokeStyle = "red";
ctx.lineWidth = 2;
ctx.rotate(Math.PI/-10;);
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(0,-70);
ctx.stroke();
And I can rotate that by 'PI/-10', and that works.
How i can get the x,y points of this after using rotate?
Your x and y points will still be 0 and -70 as they are relative to the translation (rotation). It basically means you would need to "reverse engineer" the matrix to get the resulting position you see on the canvas.
If you want to calculate a line which goes 70 pixels at -10 degrees you can use simple trigonometry to calculate it yourself instead (which is easier than going sort of backwards in the matrix).
You can use a function like this that takes your context, the start position of the line (x, y) the length (in pixels) and angle (in degrees) of the line you want to draw. It draw the line and returns an object with x and y for the end point of that line:
function lineToAngle(ctx, x1, y1, length, angle) {
angle *= Math.PI / 180;
var x2 = x1 + length * Math.cos(angle),
y2 = y1 + length * Math.sin(angle);
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
return {x: x2, y: y2};
}
Then just call it as:
var pos = lineToAngle(ctx, 0, 0, 70, -10);
//show result of end point
console.log('x:', pos.x.toFixed(2), 'y:', pos.y.toFixed(2));
Result:
x: 68.94 y: -12.16
Or you can instead extend the canvas' context by doing this:
if (typeof CanvasRenderingContext2D !== 'undefined') {
CanvasRenderingContext2D.prototype.lineToAngle =
function(x1, y1, length, angle) {
angle *= Math.PI / 180;
var x2 = x1 + length * Math.cos(angle),
y2 = y1 + length * Math.sin(angle);
this.moveTo(x1, y1);
this.lineTo(x2, y2);
return {x: x2, y: y2};
}
}
And then use it directly on your context like this:
var pos = ctx.lineToAngle(100, 100, 70, -10);
ctx.stroke(); //we stroke separately to allow this being used in a path
console.log('x:', pos.x.toFixed(2), 'y:', pos.y.toFixed(2));
(0 degrees will point to the right).
So you're asking "after I set a transform, how can I run points through that transform"?
In that case, see HTML5 Canvas get transform matrix? . The question and answers are somewhat old, but seem up-to-date. I can't find anything in the current HTML5 spec that lets you access and use the transform matrix. (I see that it's theoretically accessable through context.currentTransform, but I don't see any functionality to let you use the matrix - you'd have to multiply your point through the matrix yourself, or fake it by creating a full SVGMatrix for your point vector.)
The top answer shows a transform class you can use. Track your changes through that, and use their transformPoint function to get the point you want transformed to its endpoint.

clearing circular regions from HTML5 Canvas

It appears the only way to clear a region from a canvas is to use the clearRect() command - I need to clear a circle (I am masking out areas from a filled canvas, point lights in this specific case) and despite all attempts it does not seem possible.
I tried drawing a circle with an alpha value of 0 but simply nothing would appear unless the alpha was higher (which is counter to the point :P) - I assume because a contex.fill() draws it as an add rather than a replace.
Any suggestions on how I might be able to (quickly) clear circles for mask purposes?
Use .arc to create a circular stroke and then use .clip() to make that the current clipping region.
Then you can use .clearRect() to erase the whole canvas, but only the clipped area will change.
If you're making a game or something where squeezing every bit of performance matters, have a look at how I made this answer: Canvas - Fill a rectangle in all areas that are fully transparent
Specifically, the edit of the answer that leads to this: http://jsfiddle.net/a2Age/2/
The huge plusses here:
No use of paths (slow)
No use of clips (slow)
No need for save/restore (since there's no way to reset a clipping region without clearing all state(1), it means you must use save/restore also)
(1) I actually complained about this and resetClip() has been put in the offical spec because of it, but it will be a while before browsers implement it.
Code
var ctx = document.getElementById('canvas1').getContext('2d'),
ambientLight = 0.1,
intensity = 1,
radius = 100,
amb = 'rgba(0,0,0,' + (1 - ambientLight) + ')';
addLight(ctx, intensity, amb, 200, 200, 0, 200, 200, radius); // First circle
addLight(ctx, intensity, amb, 250, 270, 0, 250, 270, radius); // Second circle
addLight(ctx, intensity, amb, 50, 370, 0, 50, 370, radius, 50); // Third!
ctx.fillStyle = amb;
ctx.globalCompositeOperation = 'xor';
ctx.fillRect(0, 0, 500, 500);
function addLight(ctx, intsy, amb, xStart, yStart, rStart, xEnd, yEnd, rEnd, xOff, yOff) {
xOff = xOff || 0;
yOff = yOff || 0;
var g = ctx.createRadialGradient(xStart, yStart, rStart, xEnd, yEnd, rEnd);
g.addColorStop(1, 'rgba(0,0,0,' + (1 - intsy) + ')');
g.addColorStop(0, amb);
ctx.fillStyle = g;
ctx.fillRect(xStart - rEnd + xOff, yStart - rEnd + yOff, xEnd + rEnd, yEnd + rEnd);
}
canvas {
border: 1px solid black;
background-image: url('http://placekitten.com/500/500');
}
<canvas id="canvas1" width="500" height="500"></canvas>
Given the requirements, these answers are fine. But lets say you're like me and you have additional requirements:
You want to "clear" a part of a shape that may be partially outside the bounds of the shape you're clearing.
You want to see the background underneath the shape instead of clearing the background.
For the first requirement, the solution is to use context.globalCompositeOperation = 'destination-out' The blue is the first shape and the red is the second shape. As you can see, destination-out removes the section from the first shape.
Here's some example code:
explosionCanvasCtx.fillStyle = "red"
drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
Here's the potential problem with this: The second fill() will clear everything underneath it, including the background. Sometimes you'll want to only clear the first shape but you still want to see the layers that are underneath it.
The solution to that is to draw this on a temporary canvas and then drawImage to draw the temporary canvas onto your main canvas. The code will look like this:
diameter = projectile.radius * 2
console.log "<canvas width='" + diameter + "' height='" + diameter + "'></canvas>"
explosionCanvas = $("<canvas width='" + diameter + "' height='" + diameter + "'></canvas>")
explosionCanvasCtx = explosionCanvas[0].getContext("2d")
explosionCanvasCtx.fillStyle = "red"
drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
durationPercent = (projectile.startDuration - projectile.duration) / projectile.startDuration
drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
explosionCanvasCtx.globalCompositeOperation = 'source-over' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
ctx.drawImage(explosionCanvas[0], projectile.pos.x - projectile.radius, projectile.pos.y - projectile.radius) #center
You have a few options.
Firstly, here's a function we'll use to fill a circle.
var fillCircle = function(x, y, radius)
{
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fill();
};
clip()
var clearCircle = function(x, y, radius)
{
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.clip();
context.clearRect(x - radius - 1, y - radius - 1,
radius * 2 + 2, radius * 2 + 2);
};
See this on jsFiddle.
globalCompositeOperation
var clearCircle = function(x, y, radius)
{
context.save();
context.globalCompositeOperation = 'destination-out';
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fill();
context.restore();
};
See this on jsFiddle.
Both gave the desired result on screen, however the performance wasn't sufficient in my case as I was drawing and clearing a lot of circles each frame for an effect. In the end I found a different way to get a similar effect to what I wanted by just drawing thicker lines on an arc, but the above may still be useful to someone having different performance requirements.
Use canvas.getContext("2d").arc(...) to draw a circle over the area with the background colour?
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.arc(x, y, r, 0, 2*Math.PI, false);
context.fillStyle = "#FFFFFF";
context.fill();
Where x = left position, y = right position, r = radius, and ctx = your canvas:
function clearCircle( x , y , r ){
for( var i = 0 ; i < Math.round( Math.PI * r ) ; i++ ){
var angle = ( i / Math.round( Math.PI * r )) * 360;
ctx.clearRect( x , y , Math.sin( angle * ( Math.PI / 180 )) * r , Math.cos( angle * ( Math.PI / 180 )) * r );
}
}

Categories