Reputation: 45
I'm doing some demo web pages as part of a portfolio to show potential employers.
One page is the simulation of a plasma arc in a 'plasma ball' which then rotates to view the 'arc' through 360 degrees.
The redraw of the arc through each of the rotations ONLY works if I put an 'alert' after each redraw and then cancel the alerts when the script runs. Without the alert, nothing happens.
Does anyone have an explanation/solution for this? Here's the redraw function:
function reDraw(yAngle) //work in progress - redraw the arc through 360 degrees to see the path
{
var xCs;
var yCs;
for(degrees=10; degrees<360; degrees+=1)//spin sphere through 360 degrees
{
context1 = document.getElementById("canvas1").getContext("2d");
context1.clearRect(0,0,600,600);
radialGrad(1,'canvas1',300,300,300,300,300,0,0,1,colour1,colour2,0,0,600,600);
firstMove=true;
for(moves=0; moves<axisMove; moves++)
{
if(firstMove)//start at centre of sphere for each re-draw
{
xCs=300;
yCs=300;
firstMove=false;
}
context1.beginPath();
context1.moveTo(xCs,yCs);
spinAngle=(degrees/180*Math.PI);
//we are spinning in the X-Z plane so resolve X-Z moves only - retrieve each positive or negative move from the axis move arrays
xCs=xCs+(zCStep[moves]*Math.sin(spinAngle))+(xCStep[moves]*Math.cos(spinAngle));
yCs=yCs+yCStep[moves];
context1.lineTo(xCs,yCs);
context1.shadowBlur=2;
context1.shadowColor="grey";
context1.strokeStyle="white";
context1.stroke();
}
alert();
}
}
Upvotes: 3
Views: 595
Reputation: 14665
Due to their (historically) single-threaded nature, Webbrowsers re-draw content when a (javascript) function(handler) ends (same problem with progress bars, ajax-loading gif, etc).
So, even when one iteration of your loop would take a full second (resulting in 1FPS), the canvas still wouldn't redraw (same goes for the rest of the page's content) until your javascript ends.
Small side note: one of the biggest advantages of HTML5 web-workers is that they run in their own thread so they don't 'block the browser'.
The (historically) common solution to the above problems is to use a timer (setInterval
seems best for your particular case, or setTimeout
) in order to have the browser redraw the content (in this case the canvas-element).
EDIT:
Stefano Ortisi reminded me in his comment below about requestAnimationFrame
and provided an excellent link: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
Basically it's main reason for existence is so we don't need to keep using the same timers, having a browser-optimised implementation (vs timers) and ideally to use it together with webworkers (yay, extra thread).
At first this API was quite a 'living' specification (which is why I forgot about it), but by now the dust seems to have settled enough to create a nice polyfill (see above link).
I agree that anno dec. 2013 this is a better solution then defining your own timer, since "if you’re running the animation loop in a tab that’s not visible, the browser won’t keep it running, which means less CPU, GPU, and memory usage, leading to much longer battery life."
Upvotes: 1
Reputation: 27480
By its definition the <canvas>
element uses bitmap buffer. You can think about the <canvas>
as of <img>
with modifiable bitmap.
Script draws in that bitmap (but not on the screen). And browser renders that bitmap when it has the chance.
To give the browser a chance to draw your bitmap at some step you should yield execution from your script to the browser in some way: call alert()
, setTimeout/Interval or do your drawing in animation frames ( requestAnimationFrame
).
requestAnimationFrame
is pretty much a request to redraw the browser view that will happen after next 16ms (60 fps max in browsers) or so.
Upvotes: 0