2013-07-29 75 views
4

我正在繪製一個漸漸增加並且變成圓的弧。完成動畫(弧轉成一個圓)後,我想繪製另一個增加半徑的圓,前一個圓持續,第二個動畫繼續。繪製半徑增加的弧線?

Arc to circle fiddle

圈之後被繪製時,它就會衝出來這是一件好事,我不希望繼續第二動畫。 完成後出現一些不必要的動畫。

我該怎麼辦?

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:何時需清除的時間間隔,以節省一些CPU週期,爲什麼動畫會減慢對第三圈?

回答

2

首先,關於閃爍:您正在使用setInterval,並且未對下一個draw()進行清除。所以就是這樣。

但我想用completely different approach;只需檢查自啓動以來的時間,然後使用循環繪製適當數量的圓圈。

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(); 
+0

我有一些JSON數據,我必須根據這些畫我的圈子不按日期.. + 1 – user2617915

+0

@ user2617915:好了,所以不是使用時間,使用任何在你的JSON。 't'很靈活。 – Ryan

+1

你能評論你的代碼嗎? – user2617915

4

這段代碼存在一些缺陷。

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

draw()的遞歸調用將延續第一圈完全抽出後運行。這就是爲什麼表演會立即放緩。你需要以某種方式阻止它。

我做了一個簡單的修復,你可以拋光它,如果你喜歡。 FIDDLE DEMO

我的解決方法是刪除context.clearRect(0, 0, 500, 400);並更換新的圓形繪圖邏輯:

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. 
} 

在這個計算器thread,它提到如何使它更加流暢。由於優化需要大量工作,因此最好使用一些繪圖框架。

+0

它的工作原理,但其損失銳度和整體表現糟糕.. – user2617915

+0

它的工作原理。那麼這是你的答案。 –

+0

什麼時候應該清除保存一些cpu週期的時間間隔以及爲什麼動畫在第三個圓上變慢? – user2617915

1

什麼時候應該清除間隔以節省一些CPU週期?

更重要的是不使用的時間間隔在所有的有幾個原因:

  • 間隔,是無法同步到顯示器的VBLANK差距,所以你會得到抽搐不時。
  • 如果您使用setInterval,則會有堆疊調用的風險(在這種情況下風險不高)。

一個更好的方法是你可能已經知道使用​​。它不太需要CPU,可以同步監視並使用更少的資源,即使當前標籤頁/窗口未激活時也更少。

爲什麼動畫會減慢對第三圈?

您的繪圖調用正在累積,導致所有操作變慢(setInterval未被清除)。

這是一種不同的方法來此。這是一個簡化的方式,並使用差異繪畫。

ONLINE DEMO

正選賽函數這裏有兩個參數,圈指數和這個圈子當前角度。圓半徑被存儲在一個陣列:

..., 
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, ... 

的函數存儲舊角度和僅汲取舊角和新的角度之間的新段與0.5加上補償由於抗混疊毛刺,舍入誤差等

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; 
} 

循環增加角度,如果高於或等於結束角度,它將重置角度並增加當前的圓圈計數器。噹噹前計數器已經達到最後一圈結束循環:

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); 
}