HTML5: Fill circle/arc by percentage - html

Here is my pseudo code:
var percentage = 0.781743; // no specific length
var degrees = percentage * 360.0;
var radians = degrees * Math.PI / 180.0;
var x = 50;
var y = 50;
var r = 30;
var s = 1.5 * Math.PI;
var context = canvas.getContext('2d');
context.beginPath();
context.lineWidth = 5;
context.arc(x, y, r, s, radians, false);
context.closePath();
context.stroke();
I'm using the KineticJS library to control the shapes I make and redraw them as necessary. My problem is that the above code does not work at all. I assume I have the math incorrect, because if I change radians to something like 4.0 * Math.PI is draws the entire circle.
I've been using HTML5 Canvas Arc Tutorial for reference.

Your code works just fine, but you have a starting angle that ought to be zero to get what you expect. Here's working code:
http://jsfiddle.net/HETvZ/
I think your confusion is from what starting angle does. It does not mean that it starts at that point and then adds endAngle radians to it. It means that the angle starts at that point and ends at the endAngle radians point absolutely.
So if you startAngle was 1.0 and endAngle was 1.3, you'd only see an arc of 0.3 radians.
If you want it to work the way you're thinking, you're going to have add the startAngle to your endAngle:
context.arc(x, y, r, s, radians+s, false);
Like in this example: http://jsfiddle.net/HETvZ/5/

Your code is just fine. you need to have:
s=0 i.e. starting point must be zero.
and if you want circle to start drawing at top you can use:
context.rotate(-90 * Math.PI / 180);
but after rotating you will have to check arc()'s x,y arguments. i used it like:
context.rotate(-90 * Math.PI / 180);
context.arc(-200, 200, 150, startPoint, radian, false);
context.lineWidth = 20;
context.strokeStyle = '#b3e5fc';
context.stroke();
context.closePath();
after this i needed to display percentage in text form so i did:
context.rotate(90 * Math.PI / 180);
context.fillStyle = '#1aa8ff';
context.textAlign = 'center';
context.font = "bold 76px Verdana";;
context.textBaseline = "middle";
context.fillText("50%", 200, 200);

Related

Draw a Pentagon with HTML 5 canvas

I need to draw a Pentagon with html 5 canvas in Javascript. Not much else to write here. I have tried looking it up, but a lot of the examples don't work correctly.
The pentagon starts at the 3oclock pos use rotation to change the start position in radians. ie To start at the top rotation is -90deg = -Math.PI / 2
function pentagon(x, y, radius, rotation){
for(var i = 0; i < 5; i ++){
const ang = (i / 5) * Math.PI * 2 + rotation;
ctx.lineTo(
Math.cos(ang) * radius + x,
Math.sin(ang) * radius + y
);
}
ctx.closePath();
}
ctx.beginPath();
pentagon(100,100,50,-Math.PI / 2);
ctx.fill();
ctx.stroke();

Animate a Fill Circle using Canvas

Basically I want to be able to Fill a Circle using canvas, but it animate to a certain percentage.
I.e only have the circle fill up 80% of the way.
My canvas knowledge isn't amazing, Here is an image i made in photoshop to display what i want.
I want the circle to start empty and then Fill up to say 70% of the circle.
Is this possible with Canvas, if so? can anyone shed some light on how to do it?
Here is a fiddle of what I've managed
http://jsfiddle.net/6Vm67/
var canvas = document.getElementById('Circle');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 80;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = '#13a8a4';
context.fill();
context.lineWidth = 10;
context.strokeStyle = '#ffffff';
context.stroke();
Any help would be massively appreciated
Clipping regions make this very easy. All you have to do is make a circular clipping region and then fill a rectangle of some size to get a "partial circle" worth of fill. Here's an example:
var canvas = document.getElementById('Circle');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 80;
var full = radius*2;
var amount = 0;
var amountToIncrease = 10;
function draw() {
context.save();
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.clip(); // Make a clipping region out of this path
// instead of filling the arc, we fill a variable-sized rectangle
// that is clipped to the arc
context.fillStyle = '#13a8a4';
// We want the rectangle to get progressively taller starting from the bottom
// There are two ways to do this:
// 1. Change the Y value and height every time
// 2. Using a negative height
// I'm lazy, so we're going with 2
context.fillRect(centerX - radius, centerY + radius, radius * 2, -amount);
context.restore(); // reset clipping region
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.lineWidth = 10;
context.strokeStyle = '#000000';
context.stroke();
// Every time, raise amount by some value:
amount += amountToIncrease;
if (amount > full) amount = 0; // restart
}
draw();
// Every second we'll fill more;
setInterval(draw, 1000);
http://jsfiddle.net/simonsarris/pby9r/
This is a little more dynamic, object-oriented version, so you can configure the options as the circle radius, border width, colors, duration and step of animation, you can also animate the circle to a certain percentage. It was quite fun to write this.
<canvas id="Circle" width="300" height="300"></canvas>
<script>
function Animation( opt ) {
var context = opt.canvas.getContext("2d");
var handle = 0;
var current = 0;
var percent = 0;
this.start = function( percentage ) {
percent = percentage;
// start the interval
handle = setInterval( draw, opt.interval );
}
// fill the background color
context.fillStyle = opt.backcolor;
context.fillRect( 0, 0, opt.width, opt.height );
// draw a circle
context.arc( opt.width / 2, opt.height / 2, opt.radius, 0, 2 * Math.PI, false );
context.lineWidth = opt.linewidth;
context.strokeStyle = opt.circlecolor;
context.stroke();
function draw() {
// make a circular clipping region
context.beginPath();
context.arc( opt.width / 2, opt.height / 2, opt.radius-(opt.linewidth/2), 0, 2 * Math.PI, false );
context.clip();
// draw the current rectangle
var height = ((100-current)*opt.radius*2)/100 + (opt.height-(opt.radius*2))/2;
context.fillStyle = opt.fillcolor;
context.fillRect( 0, height, opt.width, opt.radius*2 );
// clear the interval when the animation is over
if ( current < percent ) current+=opt.step;
else clearInterval(handle);
}
}
// create the new object, add options, and start the animation with desired percentage
var canvas = document.getElementById("Circle");
new Animation({
'canvas': canvas,
'width': canvas.width,
'height': canvas.height,
'radius': 100,
'linewidth': 10,
'interval': 20,
'step': 1,
'backcolor': '#666',
'circlecolor': '#fff',
'fillcolor': '#339999'
}).start( 70 );
</script>

Object doesn't support property or method 'getContext' in below IE 9 versions

I am using canvas element to draw curve along with text. It is working fine in chrome, Firefox, IE 9. But in IE 8,7 this is not working. Showing the error like:
SCRIPT438: Object doesn't support property or method 'getContext'
I searched in Google then i found Excanvas.js will figure out this problem, but I am getting the same error.
Thank you.
<head><!--[if IE]><script src="js/excanvas.js"></script><![endif]--></head>
My html canvas code:
<canvas id="myCanvas" width="679" height="290"></canvas>
My js code:
function drawTextAlongArc(context, str, centerX, centerY, radius, angle) {
var len = str.length, s;
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / len) / 2);
for(var n = 0; n < len; n++) {
context.rotate(angle / len);
context.save();
context.translate(0, -1 * radius);
s = str[n];
context.fillText(s, 0, 0);
context.restore();
}
context.restore();
}
var canvas = document.getElementById('myCanvas'),
context = canvas.getContext('2d'),
centerX = canvas.width / 2,
centerY = canvas.height + 40,
angle = Math.PI * 0.8,
radius = 250;
context.font = 'bold 30pt Ubuntu';
context.textAlign = 'center';
context.fillStyle = 'orange';
context.strokeStyle = '#336699';
context.lineWidth = 10;
drawTextAlongArc(context, 'Sustainable Skill Solutions', centerX, centerY, radius, angle);
// draw circle underneath text
context.arc(centerX, centerY, radius +70, 0, 2 * Math.PI, false);
context.stroke();
You need to run your JS only when document is ready.
This may not be necessary for browsers supporting <canvas>, but for IE<9, excanvas.js works after document loaded, so you'll need to run your JS after that.
Change your JS to:
function drawTextAlongArc()
{
/* ... */
}
function onLoad()
{
var canvas=document.getElementById("myCanvas"),
context=canvas.getContext("2d");
/* ... */
}
if(window.addEventListener)
{
window.addEventListener("load",onLoad,false);
}
else if(window.attachEvent)
{
window.attachEvent("onload",onLoad);
}

Circle Animation

Can someone help me a little bit with thath canvas, i am learning it and cant manage to make a circle which when r comes to 100 it goes back to 0 animation. So its some kind of a zooming image.
I draw a circle like this:
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
</script>
Now how i can animate this now with canvas thath when it radius reaches 100 it goes instantly back to 0 and then it goes again to 100.
Thanks
Look at math sinus function http://www.digitalmedia.cz/shared/clanky/438/graf.gif
Lets take advantage on that its value is going to 1 and then goes back to 0 for angles between 0 and PI
var period = 500; // [miliseconds]
var linearMod = Date.now() % period / period; // this goes from 0 to 1
var mod = Math.sin(linearMod * Math.PI); // and here with simple easing we create
// bouncing
var r = someRadius * mod; // voila
With this approach you are additionally gaining simple sinusoidal easing which feels much more dynamic.
Here is a little fiddle for you http://jsfiddle.net/rezoner/6acF9/
You dont have to base linearMod upon time - you can assign it to a slider control or whatever you wish.

HTML canvas fill difference on Firefox vs Chrome

Consider the snippet below - available on jsFiddle: http://jsfiddle.net/Xqu5U/2/
ctx = document.getElementById('canvas').getContext('2d');
ctx.beginPath();
ctx.fillStyle = '#FF0000';
for (var i = 0; i < 20; i++) {
ctx.arc(i * 10, 50 + Math.sin(i * 0.5) * 15, 2, 0, Math.PI * 2);
}
ctx.fill();
It works as expected on Google Chrome, but Firefox renders a fill from the last arc to the first one.
How can the snippet above be updated to get Firefox drawing the arcs exactly like Chrome?
I found a way to get it working: http://jsfiddle.net/Xqu5U/3/.
Basically just add ctx.closePath() inside the for loop. Not sure if this is the best solution though...
I know this is old question but for the future reference:
ctx = document.getElementById('canvas').getContext('2d');
ctx.beginPath()
ctx.fillStyle = '#FF0000'
for (var i = 0; i < 20; i++) {
ctx.arc(i * 10, 50 + Math.sin(i * 0.5) * 15, 2, 0, Math.PI * 2)
ctx.closePath()
}
ctx.fill()
It's really old, but someone just pointed me to here.
The problem was a chrome bug (now fixed since an undetermined long time). FF behavior was correct.
arc() method doesn't include a moveTo(x, y) call, but a lineTo one.
So in order to get your desired result, you just have to call ctx.moveTo(nextCX + radius, nextCY) where nextCX and nextCY are the center x and y coordinates of your next arc to be drawn. We add radius to the x position because, when the arc's starting angle is set to 0, the arc is being drawn from 3 o'clock, without this + radius, we would still have an internal lineTo(cx + radius, cy) being added, visible when calling stroke().
var ctx = document.getElementById('canvas').getContext('2d');
ctx.beginPath();
ctx.fillStyle = '#FF0000';
for (var i = 0; i < 20; i++) {
// you need to moveTo manually.
ctx.moveTo(i * 10 + 2, 50 + Math.sin(i * 0.5) * 15)
ctx.arc(i * 10, 50 + Math.sin(i * 0.5) * 15, 2, 0, Math.PI * 2);
}
ctx.fill();
<canvas id="canvas"></canvas>
You don't have really something to do about it...
It's the way both browser's work...
You can always design it with CSS with the right commands to make it the same...
Go to http://w3schools.com and find what you need for doing that :)
Good luck !