html5 canvas venn 3 circles - javascript

Working on a venn diagram creation in canvas. I'm attempting to have different colors for each intersection and each circle. While I can do this with overlapping circles, I need to have each intersection be it's own piece so I can manipulate colors for each as I will be doing this on hover.
The problem is that I can get all sections complete but the final overlap. Here's an image of the existing solution: venn diagram image. Need to mark/show the overlap from the yellow and blue circles without effecting the bottom circle overlaps. Here's what I have so far (I realize this isn't the cleanest, working on simplifying):
<script>
window.LENS = {};
LENS.init = function(){
var self = this;
this.canvas = document.getElementById('canvas');
this.ctx = canvas.getContext('2d');
this.width = window.innerWidth;
this.height = window.innerHeight;
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight+50; //compensate for margin
this.drawLens(this.ctx, this.width, this.height);
}
LENS.drawLens = function (ctx, windowWidth, windowHeight){
var self = this;
var radius=windowWidth/5.25;
var circle1={x:windowWidth/2.5, y:windowHeight/3, r:radius, color: 'rgb(130,205,240)'};
var circle2={x:windowWidth/1.75, y:windowHeight/3, r:radius, color: 'rgb(255,240,180)'};
var circle3={x:circle1.x+circle1.r/2, y:circle1.y+circle1.r/1.2, r:radius, color: 'rgb(245,120,125)'}; //dividing by 1.2 for visual purposes. radius would be centered, but provides optical illusiion
var intersect1={color:'rgb(0,170,145)'};
var intersect2={color:'rgb(130,70,110)'};
var intersect3={color:'rgb(255,160,75)'};
var intersectCenter={color:'rgb(55,55,55)'};
//draw circle1
//ctx.save(); //important or we lose the context and will hold all drawing
ctx.beginPath();
ctx.arc(circle1.x, circle1.y, circle1.r, 0, 2*Math.PI, false);
ctx.fillStyle=circle1.color;
ctx.strokeStyle=circle1.color;
ctx.stroke();
ctx.fill();
//intersection1 top
ctx.beginPath();
ctx.fillStyle=intersect1.color;
ctx.strokeStyle=intersect1.color;
ctx.globalCompositeOperation='source-atop';
ctx.arc(circle2.x,circle2.y,circle2.r, 0, 2*Math.PI, false);
ctx.fill();
//intersection2 top
ctx.beginPath();
ctx.fillStyle=intersect2.color;
ctx.strokeStyle=intersect2.color;
ctx.globalCompositeOperation='source-atop';
ctx.arc(circle3.x,circle3.y,circle3.r, 0, 2*Math.PI, false);
ctx.fill();
//intersect Center
ctx.beginPath();
ctx.globalCompositeOperation='source-atop'
ctx.arc(circle2.x, circle2.y, circle2.r, 0, 2*Math.PI, false);
ctx.fillStyle=intersectCenter.color;
ctx.strokeStyle=intersectCenter.color;
ctx.stroke();
ctx.fill();
//draw intersection3 bottom
ctx.beginPath();
ctx.fillStyle=intersect3.color;
ctx.strokeStyle=intersect3.color;
ctx.globalCompositeOperation='destination-over';
ctx.arc(circle2.x, circle2.y, circle2.r, 0, 2*Math.PI, false);
ctx.fill();
ctx.stroke();
//intersection 3
ctx.beginPath();
ctx.fillStyle=intersect3.color;
ctx.strokeStyle=intersect3.color;
ctx.globalCompositeOperation='destination-in';
ctx.arc(circle3.x, circle3.y, circle3.r, 0, 2*Math.PI, false);
ctx.fill();
ctx.stroke();
//circle3
ctx.beginPath();
ctx.fillStyle=circle3.color;
ctx.globalCompositeOperation='destination-over';
ctx.arc(circle3.x,circle3.y,circle3.r, 0, 2*Math.PI, false);
ctx.fill();
//redraw circle 1
ctx.beginPath();
ctx.globalCompositeOperation='destination-over';
ctx.arc(circle1.x, circle1.y, circle1.r, 0, 2*Math.PI, false);
ctx.fillStyle=circle1.color;
ctx.strokeStyle=circle1.color;
ctx.stroke();
ctx.fill();
//redraw circle 2
ctx.beginPath();
ctx.globalCompositeOperation='destination-over'
ctx.arc(circle2.x, circle2.y, circle2.r, 0, 2*Math.PI, false);
ctx.fillStyle=circle2.color;
ctx.strokeStyle=circle2.color;
ctx.stroke();
ctx.fill();
}
</script>

You can use an offscreen canvas that uses compositing to create your Venn unions.
If compositing is set to "source-in" then any new drawings will display only where the existing and new drawings overlap. Everything else will be cleared (made transparent).
"source-in" compositing is ideal for drawing Venn unions because only the intersection of 2 circles will survive.
If compositing is set to "destination-out" then any new drawings will clear drawings where the new drawings overlap. (This is like an "erase" action)
This pseudo-code will display the union of your blue and yellow circles (everything but the union will be erased):
Draw the blue circle
Set compositing to "source-in"
Draw the yellow circle
This pseudo-code will display that top blue-yellow union that you're having trouble with:
Draw the blue circle
Set compositing to "source-in"
Draw the yellow circle
Set compositing to "destination-out"
Draw the red circle
Code and a Demo: http://jsfiddle.net/m1erickson/XLhT9/
<!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: white; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvas1=document.createElement("canvas");
var ctx1=canvas1.getContext("2d");
var circleBlue={x:50,y:50,r:40};
var circleYellow={x:100,y:50,r:40};
var circleRed={x:75,y:85,r:40};
drawCircle(ctx,circleRed,"salmon");
drawCircle(ctx,circleYellow,"lemonchiffon");
drawCircle(ctx,circleBlue,"lightblue");
$r=$("#r")[0];
$y=$("#y")[0];
$b=$("#b")[0];
$by=$("#by")[0];
$br=$("#br")[0];
$yr=$("#yr")[0];
$byNotR=$("#byNotR")[0];
$brNotY=$("#brNotY")[0];
$yrNotB=$("#yrNotB")[0];
$yrb=$("#yrb")[0];
$r.checked=true;
$y.checked=true;
$b.checked=true;
$(":checkbox").change(function(){drawAll()});
function drawIntersect(a,b,c,notC,color){
ctx1.clearRect(0,0,canvas1.width,canvas1.height);
ctx1.save();
// a
drawCircle(ctx1,a,color);
// b
ctx1.globalCompositeOperation="source-in";
drawCircle(ctx1,b,color);
// c
if(c){drawCircle(ctx1,c,color); }
// notC
ctx1.globalCompositeOperation="destination-out";
if(notC){ drawCircle(ctx1,notC,color); }
ctx1.restore();
ctx.drawImage(canvas1,0,0);
}
function drawCircle(ctx,circle,color){
ctx.beginPath();
ctx.arc(circle.x,circle.y,circle.r,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=color;
ctx.fill();
}
function drawAll(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if($r.checked){drawCircle(ctx,circleRed,"salmon");}
if($y.checked){drawCircle(ctx,circleYellow,"lemonchiffon");}
if($b.checked){drawCircle(ctx,circleBlue,"lightblue");}
if($by.checked){drawIntersect(circleBlue,circleYellow,null,null,"green");}
if($br.checked){drawIntersect(circleBlue,circleRed,null,null,"blue");}
if($yr.checked){drawIntersect(circleYellow,circleRed,null,null,"red");}
if($byNotR.checked){drawIntersect(circleBlue,circleYellow,null,circleRed,"green");}
if($brNotY.checked){drawIntersect(circleBlue,circleRed,null,circleYellow,"blue");}
if($yrNotB.checked){drawIntersect(circleYellow,circleRed,null,circleBlue,"red");}
if($yrb.checked){drawIntersect(circleYellow,circleRed,circleBlue,null,"black");}
}
}); // end $(function(){});
</script>
</head>
<body>
<input type="checkbox" id="r">Red Circle<br>
<input type="checkbox" id="y">Yellow Circle<br>
<input type="checkbox" id="b">Blue Circle<br>
<input type="checkbox" id="by">Blue+Yellow<br>
<input type="checkbox" id="br">Blue+Red<br>
<input type="checkbox" id="yr">Yellow+Red<br>
<input type="checkbox" id="byNotR">Blue+Yellow-Red<br>
<input type="checkbox" id="brNotY">Blue+Red-Yellow<br>
<input type="checkbox" id="yrNotB">Yellow+Red-Blue<br>
<input type="checkbox" id="yrb">Yellow+Red+Blue<br>
<canvas id="canvas" width=150 height=150></canvas>
</body>
</html>

Related

How can I cut out a shape if it goes outside of a canvas with javascript?

I want to create a circle and cut out a part of it if it goes outside another shape.
For example, if half of the circle goes outside a square, cut out everything on the outside but not on the inside. Something like this snippet, except the part outside the square is hidden. I prefer to avoid masking it since this will go on top of another canvas, which covers the whole screen.
Code
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(70, 90, 60, 0, Math.PI * 2, false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
You can clip() the circle, like so;
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.clip(); // clip circle
ctx.beginPath();
ctx.arc(70, 90, 60, 0, Math.PI * 2, false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
This is the dimensions I've adjusted for cropping the outside part of sqaure
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(70, 90, 60, 10, -4*Math.PI * .05 , false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

Canvas - Rotating Paths

I want to know how to rotate a line in canvas.
Say I have the canvas set-up.
ctx.beginPath();
ctx.strokeStyle = "#000000";
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
ctx.closePath();
How do I rotate this line?
Thanks,
Alex
Here's how to rotate a line segment between p1 & p2 around that segment's midpoint:
The idea is to:
Save the unrotated state of the context using context.save
Set the rotation point at the midpoint of the line using context.translate
Rotate to a specified radian angle using context.rotate
Draw the line. This is the tricky part...Since the canvas is already rotated and since the canvas origin is now the line's midpoint, you must moveTo minus the line's length/2 and lineTo the lines length/2: context.moveTo(-length/2,0); and context.lineTo(length/2,0);
Restore the context to its unrotated state with context.restore
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var p1={x:75,y:75};
var p2={x:150,y:150};
var dx=p2.x-p1.x;
var dy=p2.y-p1.y;
var length=Math.sqrt(dx*dx+dy*dy);
var angle=Math.atan2(dy,dx);
var midX=(p2.x+p1.x)/2;
var midY=(p2.y+p1.y)/2;
console.log(midX,midY);
draw(angle);
requestAnimationFrame(animate);
function animate(time){
requestAnimationFrame(animate);
draw(angle);
angle+=Math.PI/30;
}
function draw(radianAngle){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(midX,midY);
ctx.rotate(radianAngle);
ctx.beginPath();
ctx.strokeStyle='red';
ctx.moveTo(-length/2,0);
ctx.lineTo(length/2,0);
ctx.stroke();
ctx.restore();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>
Note: This code shows rotation around your line's midpoint, but you can rotate around any point by using context.translate(anyRotationPointX,anyRotationPointY);
To rotate anything you can use context method - rotate().
We can't rotate line like object (like in SVG), but we can - redraw canvas with new rotated line.
var canvas = document.getElementById("example"),
ctx = example.getContext('2d'),
canvasWidth = canvas.width,
canvasHeight = canvas.height,
p1 = {x:canvasWidth/2+50,y:canvasHeight/2},
p2 = {x:p1.x,y:p1.y+100},
middlePoint = {x:(p1.x+p2.x)/2,y:(p1.y+p2.y)/2};
function rotate(degree,rotatePoint,drFunc) {
rotatePoint = rotatePoint || {x:canvasWidth/2,y:canvasHeight/2};
// Clear the canvas
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Move registration point to the center of the canvas
ctx.translate(rotatePoint.x, rotatePoint.y);
// Rotate 1 degree
ctx.rotate((Math.PI / 180)*degree);
// Move registration point back to the top left corner of canvas
ctx.translate(-rotatePoint.x, -rotatePoint.y);
drFunc();
}
function drFunc(){
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
ctx.closePath();
}
rotate(1,middlePoint,drFunc);
Fiddle

HTML5 Cut out circle from previous drawn strokes

How can you cut out a circle on a previous drawn canvas in html5?
I tried filling it transparent, and of course it did not work, I can fill it with a color but I really need it to be cut out of the canvas revealing the layer beneath.
This is what I tried.
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "rgba(0, 0, 0, 0)";
context.fill();
and
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "rgba(255, 255, 255, 1)";
context.fill();
You can use compositing to do a 'reveal' of an image underneath the canvas.
Position a canvas directly over an image using CSS positioning.
Fill the top canvas with a solid color.
Listen for mousedown events.
In the event handler, set compositing to 'destination-out' which will use any new drawings to "cut" out any existing pixels.
Draw on the canvas (causing the img underneath to be revealed where the new drawings were drawn.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var radius=30;
ctx.fillStyle='skyblue';
ctx.fillRect(0,0,canvas.width,canvas.height);
function cut(x,y,radius){
ctx.save();
ctx.globalCompositeOperation='destination-out';
ctx.beginPath();
ctx.arc(x,y,radius, 0, 2 * Math.PI, false);
ctx.fill();
ctx.restore();
}
function handleMouseDown(e){
e.preventDefault();
e.stopPropagation();
x=parseInt(e.clientX-offsetX);
y=parseInt(e.clientY-offsetY);
cut(x,y,radius);
}
$("#canvas").mousedown(function(e){handleMouseDown(e);});
body{ background-color: ivory; }
#canvas{border:1px solid red;}
#wrapper{position:relative;}
#bk,#canvas{position:absolute;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Click on the canvas to cut a circle<br>and reveal the img underneath.</h4>
<img id=bk src='https://dl.dropboxusercontent.com/u/139992952/stackoverflow/KoolAidMan.png'>
<canvas id="canvas" width=300 height=300></canvas>

Display text over Canvas only onmouseover

I have created a triangle shaped image mask with the Canvas element. I have a field of text which I want to display at the bottom line of this triangle when mouse over. I can´t figure out how to make the text display only when hovering.
I am a beginner at this... Any help appriciated!
This is the code I got so far:
HTML code:
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
Javascript:
function masks() {
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=function(){
draw(ctx,img,"Hello!");
}
img.src="canvas01.png";
function draw(ctx,img,text){
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.clip();
ctx.drawImage(img,0,0);
if(text){
ctx.fillStyle = "#f30";
ctx.fillRect(0,canvas.height-20,canvas.width,20);
ctx.fillStyle = "black";
ctx.font="14pt Verdana";
var textWidth=ctx.measureText(text).width;
ctx.fillText(text,(canvas.width-textWidth)/2,canvas.height-3);
}
}
};
Here's how...
You can draw your text when the user's mouse is over the canvas element using:
canvas.addEventListener("mouseover",function(){
draw(ctx,img,"Hello!");
});
You can clear the text when the user's mouse has moved outside the canvas element using:
canvas.addEventListener("mouseout",function(){
draw(ctx,img);
});
Note that your draw function now clears the canvas in preparation for redrawing:
function draw(ctx,img,text){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.clip();
ctx.drawImage(img,0,0);
if(text){
ctx.fillStyle = "#f30";
ctx.fillRect(0,canvas.height-20,canvas.width,20);
ctx.fillStyle = "black";
ctx.font="14pt Verdana";
var textWidth=ctx.measureText(text).width;
ctx.fillText(text,(canvas.width-textWidth)/2,canvas.height-3);
}
ctx.restore();
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/Q4TKC/
<!doctype html>
<html>
<head>
<style>
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid lightgray;}
</style>
<script>
window.onload=function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=function(){
canvas.addEventListener("mouseover",function(){
draw(ctx,img,"Hello!");
});
canvas.addEventListener("mouseout",function(){
draw(ctx,img);
});
draw(ctx,img);
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/sky-bg2.jpg";
function draw(ctx,img,text){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.clip();
ctx.drawImage(img,0,0);
if(text){
ctx.fillStyle = "#f30";
ctx.fillRect(0,canvas.height-20,canvas.width,20);
ctx.fillStyle = "black";
ctx.font="14pt Verdana";
var textWidth=ctx.measureText(text).width;
ctx.fillText(text,(canvas.width-textWidth)/2,canvas.height-3);
}
ctx.restore();
}
}; // end window.onload
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

How to draw doughnut with HTML5 canvas

I would like to draw doughnut within HTML5 canvas.If the background color of the canvas is a solid color, I was able to draw it. But it's gradient color, I can't draw it.
I would like to know how to draw the doughnut, when the backgroud color of the canvas is gradient color.
Like:
Source
This is my code:
function background(context, coordinate, properties) {
var x = coordinate.x //起始点x
, y = coordinate.y //起始点 y
, w = coordinate.w //宽度(终点-起始点之间的宽度)
, h = coordinate.h //高度(终点-起始点之间的高度)
, gradientFactor, gradientColor; //渐变因子, 渐变色
context.save();
switch( properties["background-fill-type"] ) {
case "solid":
context.fillStyle = properties["background-color"];
break;
case "gradient":
gradientFactor = properties["background-gradient-factor"];
gradientColor = context.createLinearGradient(x, y, x + w, y);
gradientColor.addColorStop(gradientFactor, properties["background-first-color"]);
gradientColor.addColorStop(1 - gradientFactor, properties["background-second-color"]);
context.fillStyle = gradientColor;
break;
case "image":
break;
}
context.fillRect(x, y, w, h);
context.restore();
}
If the background color of the canvas is solid color:
var context = canvas.getContext("2d")
, properties = {
"background-fill-type": "solid", //solid color
"background-color": "#FFFFFF",
"background-first-color": "#008B8B",
"background-second-color": "#F5DEB3",
"background-gradient-factor": 0.5,
"border-color": "#FFFFFF",
"border-thickness": 0
};
//draw canvas background (solid color)
background(context, {
x: 0,
y: 0,
w: properties["width"],
h: properties["height"]
}, properties);
//draw doughnut
context.save();
context.beginPath();
context.translate(centerX, centerY);
context.arc(0, 0, Radius, 0, dpi, false); //外部圆
context.fillStyle = "blue";
context.fill();
context.closePath();
context.beginPath();
context.arc(0, 0, radius, 0, dpi, false); //内部圆
context.fillStyle = properties["background-color"];
context.fill();
context.closePath();
context.restore();
If the background color of the canvas is gradient color:
var context = canvas.getContext("2d")
, properties = {
"background-fill-type": "gradient", //gradient color
"background-color": "#FFFFFF",
"background-first-color": "#008B8B",
"background-second-color": "#F5DEB3",
"background-gradient-factor": 0.5,
"border-color": "#FFFFFF",
"border-thickness": 0
};
//draw canvas background (gradient color)
background(context, {
x: 0,
y: 0,
w: properties["width"],
h: properties["height"]
}, properties);
//draw doughnut
context.save();
context.beginPath();
context.translate(centerX, centerY);
context.arc(0, 0, Radius, 0, dpi, false); //外部圆
context.fillStyle = "blue";
context.fill();
context.closePath();
context.beginPath();
context.arc(0, 0, radius, 0, dpi, false); //内部圆
//context.fillStyle = properties["background-color"];
// *----------------------------------------------------------------------*
// | How to solve internal circle and canvas background color consistent? |
// |
// *----------------------------------------------------------------------*
context.fill();
context.closePath();
context.restore();
This is an effect diagram.( A little crooked, - -! ):
Drawing a data-donut with gradient background
Your donut is just a circle with the center cut out.
So draw an outer circle and then draw an inner circle to cut a donut.
To display data, the outer circle can be assembled from arcs whose sweeps indicate your data ( called wedges).
You can draw individual wedges by supplying the starting and ending angles of an arc (in radians).
ctx.arc(cX, cY, radius, startRadians, endRadians, false);
Fill both the canvas and the inner circle with your same gradient to display a consistent gradient.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/ENZD9/
<!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; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// define the donut
var cX = Math.floor(canvas.width / 2);
var cY = Math.floor(canvas.height / 2);
var radius = Math.min(cX,cY)*.75;
// the datapoints
var data=[];
data.push(67.34);
data.push(28.60);
data.push(1.78);
data.push(.84);
data.push(.74);
data.push(.70);
// colors to use for each datapoint
var colors=[];
colors.push("teal");
colors.push("rgb(165,42,42)");
colors.push("purple");
colors.push("green");
colors.push("cyan");
colors.push("gold");
// track the accumulated arcs drawn so far
var totalArc=0;
// draw a wedge
function drawWedge2(percent, color) {
// calc size of our wedge in radians
var WedgeInRadians=percent/100*360 *Math.PI/180;
// draw the wedge
ctx.save();
ctx.beginPath();
ctx.moveTo(cX, cY);
ctx.arc(cX, cY, radius, totalArc, totalArc+WedgeInRadians, false);
ctx.closePath();
ctx.fillStyle = color;
ctx.fill();
ctx.restore();
// sum the size of all wedges so far
// We will begin our next wedge at this sum
totalArc+=WedgeInRadians;
}
// draw the donut one wedge at a time
function drawDonut(){
for(var i=0;i<data.length;i++){
drawWedge2(data[i],colors[i]);
}
// cut out an inner-circle == donut
ctx.beginPath();
ctx.moveTo(cX,cY);
ctx.fillStyle=gradient;
ctx.arc(cX, cY, radius*.60, 0, 2 * Math.PI, false);
ctx.fill();
}
// draw the background gradient
var gradient = ctx.createLinearGradient(0,0,canvas.width,0);
gradient.addColorStop(0, "#008B8B");
gradient.addColorStop(0.75, "#F5DEB3");
ctx.fillStyle = gradient;
ctx.fillRect(0,0,canvas.width,canvas.height);
// draw the donut
drawDonut();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=300></canvas>
</body>
</html>

Categories