2015-06-13 61 views
11

所以,我對iOS編程相當陌生,並且繼承了一位前同事的項目。我們正在構建一個包含量表UI的應用程序。當數據進入時,我們想要平滑地將我們的「圖層」(這是針圖像)從當前角度旋轉到新的目標角度。這裏是我們所擁有的,與較慢的數據行之有效:如何重置/重新啓動動畫並使它看起來連續?

-(void) MoveNeedleToAngle:(float) target 
{ 
    static float old_Value = 0.0; 
    CABasicAnimation *rotateCurrentPressureTick = [CABasicAnimation animationWithKeyPath:@"transform.rotation"); 
    [rotateCurrentPressureTick setDelegate:self]; 
    rotateCurrentPressureTick.fromValue = [NSSNumber numberWithFloat:old_value/57.2958]; 
    rotateCurrentPressureTick.removedOnCompletion=NO; 
    rotateCurrentPressureTick.fillMode=kCAFillModeForwards; 
    rotateCurrentPressureTick.toValue=[NSSNumber numberWithFloat:target/57.2958]; 
    rotateCurrentPressureTick.duration=3; // constant 3 second sweep 

    [imageView_Needle.layer addAnimation:rotateCurrentPressureTick forKey:@"rotateTick"]; 
    old_Value = target; 
} 

的問題是,我們有一個新的數據方案,其中新數據可以進來(並呼籲上述方法)更快,前動畫完成。我認爲發生的事情是動畫從舊目標重新啓動到新目標,這使得它非常激動。

所以我想知道如何修改上面的功能添加一個連續/重新啓動的行爲,具體如下:

  1. 檢查當前動畫正在進行中,
  2. 如果是這樣,找出其中的當前的動畫角,然後
  3. 取消當前,並開始從當前旋轉一個新的動畫到新的目標旋轉

是否有可能建立一個可進入上述功能的行爲?

謝謝。對不起,如果這個問題似乎不知情,我已經研究和理解上述對象/方法,但我不是專家。

回答

3

是您可以使用現有的方法,如果您添加的神奇該位做到這一點:

- (void)removeAnimationsFromView:(UIView*)view { 
     CALayer *layer = view.layer.presentationLayer; 
     CGAffineTransform transform = layer.affineTransform; 
     [layer removeAllAnimations]; 
     view.transform = transform; 
    } 

表示層封裝了動畫的實際狀態。視圖本身不包含動畫狀態屬性,基本上當您設置動畫結束狀態時,只要觸發動畫,視圖就會獲取該狀態。它是在動畫過程中「看到」的表示層。

此方法在取消動畫的同時捕獲表示層的狀態,然後將該狀態應用於視圖。

現在你可以在你的動畫方法使用此方法,這將是這個樣子:

-(void) MoveNeedleToAngle:(float) target{ 
    [self removeAnimationsFromView:imageView_Needle]; 
    id rotation = [imageView_Needle valueForKeyPath:@"layer.transform.rotation.z"]; 
    CGFloat old_value = [rotation floatValue]*57.2958; 

    // static float old_value = 0.0; 
    CABasicAnimation *rotateCurrentPressureTick = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 
    [rotateCurrentPressureTick setDelegate:self]; 
    rotateCurrentPressureTick.fromValue = [NSNumber numberWithFloat:old_value/57.2958]; 
    rotateCurrentPressureTick.removedOnCompletion=NO; 
    rotateCurrentPressureTick.fillMode=kCAFillModeForwards; 
    rotateCurrentPressureTick.toValue=[NSNumber numberWithFloat:target/57.2958]; 
    rotateCurrentPressureTick.duration=3; // constant 3 second sweep 

    [imageView_Needle.layer addAnimation:rotateCurrentPressureTick forKey:@"rotateTick"]; 

    old_value = target; 

} 

(我已經做最小的改動,以你的方法:有幾個編碼風格變化我也將做,但它們與您的問題無關)

順便說一句,我建議您以弧度而非度數餵食您的方法,這意味着您可以移除這些57.2958常量。

1

您可以從表示層獲取當前的旋轉角度,並設置toValue角度。沒有必要繼續OLD_VALUE

-(void) MoveNeedleToAngle:(float) targetRadians{ 

    CABasicAnimation *animation =[CABasicAnimation animationWithKeyPath:@"transform.rotation"]; 
    animation.duration=5.0; 
    animation.fillMode=kCAFillModeForwards; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 
    animation.removedOnCompletion=NO; 

    animation.fromValue = [NSNumber numberWithFloat: [[layer.presentationLayer valueForKeyPath: @"transform.rotation"] floatValue]]; 
    animation.toValue = [NSNumber numberWithFloat:targetRadians]; 
    // layer.transform= CATransform3DMakeRotation(rads, 0, 0, 1); 
    [layer addAnimation:animation forKey:@"rotate"]; 
} 

的另一種方式,我發現(上面的註釋行)是不是使用fromValue和toValue只需設置層改造。這將產生相同的動畫,但presentationLayer和模型將同步。