2010-10-12 1175 views
1

我在我的智慧結尾試圖想出一個這種範例的設計模式。我在這個網站上沒有多少運氣,但在這個階段我會嘗試任何事情。UIView無限循環動畫在每個重複循環後調用一個方法

我試圖實現一個雷達類型的動畫,因此我旋轉的視圖360度來表示半徑周圍的圓旋轉。我已經在這個圓周上放置了點,並且能夠使用標準的trig來計算圓心的角度。

作爲圍繞圓半徑掃描,如果它與一個點相交(例如,點的角等於掃半徑+公差的角度)的點上閃爍。

現在,我已經在很多的方式來實現這種模式,但都沒有取得理想的解決方案。這是我嘗試過的。

FIRST:iOS4動畫塊。我會一次旋轉半徑10度,持續時間爲0.1秒,在完成方法中,檢查與點的交點。這裏的問題是,如果您將該選項設置爲重複,則不會調用完成方法。調用完成方法的唯一時間是整個動畫終止時,而不是每個重複循環之後,因此此解決方案不起作用。

SECOND:嘗試使用CABasicAnimation顯式動畫。與上述方法相同,每0.1秒旋轉10度,並將委託設置爲自我並實現animationDidFinish方法。在animationDidFinish方法中,我檢查了與點的交點。我將動畫設置爲累積並重復拍攝以獲得巨大價值。該raduis旋轉,但再次,animationDidFinish不會被調用,除非我將repeatCount設置爲一個小數字,然後它只在repeatCount結束時被調用,而不是在每個重複循環之後。

第三:使用的NSTimer和這種方法確實有效,但動畫可以根據是什麼在屏幕周圍發生的是生澀。我使用0.1秒的計時器刻度,並啓動10度的單個動畫以及每次刻度的交叉檢查。這種方法的問題在於,由於處理器在後臺執行其他動畫,因此在啓動每個動畫時容易受到阻礙。請注意,我沒有其他兩種方法的問題!

第四:我嘗試使用兩者的組合。點上的CABasicAnimation和點上的NSTimer。這裏的問題是,如果iDevice進入休眠狀態,然後恢復,它們可能會不同步併發生。

FIFTH:使用iOS3.0風格動畫塊並用.1sec持續時間旋轉10度。使用animationDidStop方法設置委託和animationDidStopSelector,再次調用動畫方法以及檢查與點的交集。這也起作用,但很像第三種解決方案,當滾動和其他動畫發生時,它很乾。這很可能是由動畫的停止啓動性質引起的。

基本上是有沒有辦法無限動畫視圖但要調用每一個重複週期後的方法?或者有沒有辦法讓第三個解決方案更順利?

請幫助,我已經用盡了設計模式。

+0

我認爲你的應用程序是opengles的好選擇,它會處理你想要做的很棒的性能。如果你想使用框架,你甚至不需要3D以便更容易看看cocos2D。 – Ben 2010-10-13 01:08:51

+0

是的,我聽到你說,問題是我到目前爲止已經學到了很多,我不知道我想重新開始。 – 2010-10-13 03:31:55

+0

我想我正在接近答案,使用第二種解決方案,我可以保留CABasicAnimation對象並在animationDidStop方法中重新應用它。它肯定不是生澀的,但我在累積部分遇到麻煩。 – 2010-10-13 06:15:53

回答

1

OK,我已經走過了漫長的道路,因爲我張貼了這個問題。

接受的設計模式是實際生成的時鐘滴答(通常使用CADisplayLink),其以每秒或60取決於任一30幀運行在要如何光滑和快動畫是。在每一幀回調中,您都可以修改視圖/圖層上的變換並使用事務來顯示它。

一些關鍵的注意事項: 構建以測試交叉線和點的方法:

-(BOOL)intersectWithAngle:(CGFloat)rad {   
    return (rad <= angle && rad >= angle - angleIncrement); 
} 

試圖修改屬性是動畫,以防止層/瀏覽動畫新時,必須使用交易價值本身。 (你不想動畫它兩次)

[CATransaction begin]; 
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 

self.transform = rotationTransform; 

[CATransaction commit]; 

沒有必要不斷創建每一幀新的變換,這只是浪費和消耗資源。最好創建一個名爲rotationTransform的實例變量/屬性,並修改每一幀並將其重新應用到圖層/視圖。

-(void)displayFrame { 
    rotationTransform.a = cos(angle); 
    rotationTransform.b = sin(angle); 
    rotationTransform.c = -sin(angle); 
    rotationTransform.d = cos(angle); 

    [CATransaction begin]; 
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 

    self.transform = rotationTransform; 

    [CATransaction commit]; 
} 

接下來,創建方法來實際設置的角度,使用一個實例變量/屬性來存儲角度並定義角度增量(I使用3度),還預定義2-π,使你並不總是重新計算它。

-(void)processFrame { 
    angle += angleIncrement; 
    if (angle >= M_2PI) { 
     angle -= M_2PI; 
    } 

    if ([self intersectWithAngle:point.angle]) { 
     [point animate]; 
    } 
} 

最後,構建由CADisplayLink調用的方法,該方法設置框架並在保持幀同步的同時顯示框架。

-(void)displayLinkDidTick { 
    // get the time now 
    NSTimeInterval timeNow = [NSDate timeIntervalSinceReferenceDate]; 

    if (timeOfLastDraw == 0) { 
     numberOfTicks = 1; 
    } else { 
     NSTimeInterval timeSinceLastDraw = timeNow - timeOfLastDraw; 
     NSTimeInterval desiredTimeInterval = kFrameDuration; 

     numberOfTicks = (NSUInteger)(timeSinceLastDraw/desiredTimeInterval);  
    } 

    if (numberOfTicks > 4) { 
     numberOfTicks = 4; 
     timeOfLastDraw = timeNow; 
    } else { 
     timeOfLastDraw += numberOfTicks * kFrameDuration; 
    } 


    while(numberOfTicks--) { 

     [self processFrame]; 
     if (spriteState == SpriteStateIdle) 
      break; 
     } 

    [self displayFrame]; 

} 

此代碼提取物已被大幅修改了這個帖子,其實在其實我做了掃描線的動畫,並在同一CADisplayLink實例點的blipping。

0

我不知道這會工作:

UIView* yourView = ...; 
// preparing the callbacks: 
void(^)(void) animations = ...; // the animation would rotate 10 degrees 
void(^)(BOOL) completion = ^(BOOL finished) { 
    // do your radar stuff 
    [UIView animateWithDuration:0.1 animations:animations completion:completion]; 
} 

// the first call to start it all 
[UIView animateWithDuration:0.1 animations:animations completion:completion]; 

的想法是每一次再次調用動畫序列整理你的雷達活動後,假設雷達檢查是不是一個沉重一個它應該光滑。

+0

我認爲保持動畫平滑的問題是在它完成之前抓住它,這樣你就不會刪除動畫層並且不得不重新創建它。但是,我會在去掉動畫層之前先給它調用這個方法,並且有智慧重用對象而不是創建一個新對象。 – 2010-10-13 05:50:07

+0

其實我越想越多,我覺得這更像我的第五個解決方案,但你永遠不知道。 – 2010-10-13 05:54:14

+0

我不確定。聽起來很相似,但這是更多的iOS 4.0風格。 :-)無論如何,你應該檢查你的其他動畫屬性,如果它太生澀 - 也許動畫曲線是錯誤的,或者你應該設置「從當前位置開始動畫」或什麼的。 – 2010-10-13 19:36:41

2

讓它完美地工作。

這裏是我所做的:

1 /應用一個CABasicAnimation旋轉對象到層旋轉每2秒360度。 (不需要使其累計這種方式)

2 /設置一個計時器來調用每0.1秒層表示層。

3 /計算從3D角度變換存儲在表示層。 Click here爲我的答案如何做到這一點。

4 /檢查相交角度。

完成:-)

觀光注意:基於180名-180度和不爲0到360度 使用ATAN2和不ATAN作爲後只會給之間的角度 三維變換第一象限內的角度。