Draw an arc with increasing radius?

I draw an arc that gradually grows and turns into a circle. At the end of the animation (an arc turning towards a circle) I want to draw another circle with a larger radius, preserving the previous circle and continuing the second animation.

Circle violin

After the circle is drawn, it is washed off, which I do not want and continue the second animation. After completion, an unnecessary animation appears.

What should I do?

MyCode:

setInterval(function(){ context.save(); context.clearRect(0,0,500,400); context.beginPath(); increase_end_angle=increase_end_angle+11/500; dynamic_end_angle=end_angle+increase_end_angle; context.arc(x,y,radius,start_angle,dynamic_end_angle,false); context.lineWidth=6; context.lineCap = "round"; context.stroke(); context.restore(); if(dynamic_end_angle>3.5*Math.PI){ //condition for if circle completion draw(radius+10);//draw from same origin and increasd radius } },66); window.onload=draw(30); 

UPDATE : when do I need to clear the interval to save some processor cycles and why does the animation slow down on the third lap?

+4
source share
3 answers

First of all, about flickering: you use setInterval and do not clear it for the next draw() . So it is.

But Id takes a completely different approach ; just check the elapsed time from the start and draw the appropriate number of laps using a loop.

 var start = new Date().getTime(); var timePerCircle = 2; var x = 190, y = 140; function draw() { requestAnimationFrame(draw); g.clearRect(0, 0, canvas.width, canvas.height); var t = (new Date().getTime() - start) / 1000; var circles = t / timePerCircle; var r = 30; do { g.beginPath(); g.arc(x, y, r, 0, Math.PI * 2 * Math.min(circles, 1)); g.stroke(); r += 10; circles--; } while(circles > 0); } draw(); 
+2
source

This piece of code has some flaw.

 if(dynamic_end_angle>3.5*Math.PI){ //condition for if circle completion draw(radius+10);//draw from same origin and increased radius } 

The recursive call to draw() will continue to work after the first circle is fully drawn. This is why performance will be immediately reduced. You need to somehow block it.

I made a simple fix, you can polish it if you want. FIDDLE DEMO

My fix is ​​to delete context.clearRect(0, 0, 500, 400); and changing the new circle drawing logic to:

 if (dynamic_end_angle > 3.5 * Math.PI) { //condition for if circle completion increase_end_angle = 0; // this will prevent the draw() from triggering multiple times. draw(radius + 10); //draw from same origin. } 

This stackoverflow mentions how to make it smoother . You are better off using some drawing structure, since optimization requires a lot of work.

+4
source

When should I clear the interval to save some processor cycles?

It’s better not to use the interval at all for several reasons:

  • Intervals cannot be synchronized to track the VBLANK gap, so from time to time you will be jerky.
  • If you use setInterval, you run the risk of stacking calls (in this case, not a high risk).

And it’s much better, as you already know, to use requestAnimationFrame . This is a less processor hunger, able to synchronize and control fewer resources in general, even if the current tab / window is not active.

Why does animation slow down in the third lap?

Your drawing calls accumulate, which slows everything down ( setInterval not cleared).

Here is a different approach to this. This is a simplified method and uses differential coloring.

ONLINE DEMO

The main draw function here takes two arguments, the index of the circle and the current angle for this circle. The radius of the circles is stored in the array:

 ..., sa = 0, // start angle ea = 359, // end angle angle = sa, // current angle oldAngle = sa, // old angle steps = 2, // number of degrees per step current = 0, // current circle index circles = [70, 80, 90], // the circle radius numOfCircles = circles.length, ... 

The function saves the old angle and only draws a new segment between the old angle and the new angle with 0.5 added to compensate for failures due to smoothing, rounding errors, etc.

 function drawCircle(circle, angle) { angle *= deg2rad; // here: convert to radians /// draw arc from old angle to new angle ctx.beginPath(); ctx.arc(0, 0, circles[circle], oldAngle, angle + 0.5); ctx.stroke(); /// store angle as old angle for next round oldAngle = angle; } 

The cycle increases the angle; if it is higher than or equal to the final angle, it will reset the angle and increase the counter of the current circle. When the current counter reaches the last lap, the loop ends:

 function loop() { angle += steps; /// check angle and reset, move to next circle if (angle >= ea - steps) { current++; angle = sa; oldAngle = angle; } drawCircle(current, angle); if (current < numOfCircles) requestAnimationFrame(loop); } 
+1
source

Source: https://habr.com/ru/post/1494107/


All Articles