Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Circle(ARC) gradient fill with canvas JS

I need to draw a dynamic donut chart - something similar to -

http://194.90.28.56/~dev1/t.jpg

The green part indicates the percentage (in this case 27%) - it must be dynamic.

I think I need to do something like - Android - How to draw an arc based gradient

But with JS..

Thanks.

like image 739
user2288183 Avatar asked Dec 06 '22 08:12

user2288183


1 Answers

Great question. Gradients along paths in canvas are hard. The easiest way is to fudge it.

Instead of thinking of your image as a gradient that follows a circular path, think of it as two linear gradients.

  • One on the left side, going from green to gray, top to bottom.
  • The other on the right side, going from white to gray, top to bottom.

Imagine a square made of those two gradients:

enter image description here

Now imagine a circle cutting through:

enter image description here

That's all you gotta do.

To "cut" through like that its easiest to use clipping regions, so I've made an example doing that.

Here's the live example: http://jsfiddle.net/simonsarris/Msdkv/

Code below! Hope that helps.

var greenPart = ctx.createLinearGradient(0,0,0,100);
greenPart.addColorStop(0, 'palegreen');
greenPart.addColorStop(1, 'lightgray');

var whitePart = ctx.createLinearGradient(0,0,0,100);
whitePart.addColorStop(0, 'white');
whitePart.addColorStop(1, 'lightgray');


var width = 20;
ctx.lineWidth = width;

// First we make a clipping region for the left half
ctx.save();
ctx.beginPath();
ctx.rect(-width, -width, 50+width, 100 + width*2);
ctx.clip();

// Then we draw the left half
ctx.strokeStyle = greenPart;
ctx.beginPath();
ctx.arc(50,50,50,0,Math.PI*2, false);
ctx.stroke();

ctx.restore(); // restore clipping region to default

// Then we make a clipping region for the right half
ctx.save();
ctx.beginPath();
ctx.rect(50, -width, 50+width, 100 + width*2);
ctx.clip();

// Then we draw the right half
ctx.strokeStyle = whitePart;
ctx.beginPath();
ctx.arc(50,50,50,0,Math.PI*2, false);
ctx.stroke();

ctx.restore(); // restore clipping region to default
like image 137
Simon Sarris Avatar answered Dec 22 '22 11:12

Simon Sarris