2012-03-02 97 views
13

我已經使用CAKeyframeAnimations爲圖層的transform.rotationtransform.translation.x屬性設置動畫效果,但我無法隱式動畫設置transform屬性。我有一個必須在兩個狀態之間動畫的圖層,而CABasicAnimation的默認插值完全不正確,並且不遵循我想要的路徑。 CAKeyframeAnimation來拯救,或者我想。任何使用CAKeyframeAnimation動畫transform的嘗試都會導致該視圖在其他動畫運行時立即捕捉到最終變換。如果我刪除了以下函數的前半部分,並讓我的「變形」事件在底部使用了CABasicAnimation,則它的動畫效果非常好 - 儘管沿途有不正確的插值變換。如何使用CAKeyframeAnimation爲CATransform3D設置動畫效果?

我的層代表已經實現了以下內容:

- (id <CAAction>) actionForLayer:(CALayer *)layer forKey:(NSString *)event 
{  
    if ([event isEqualToString:@"transform"]) 
    { 
     CGSize startSize = ((CALayer *)self.layer.presentationLayer).bounds.size; 
     CGSize endSize = self.layer.bounds.size; 

     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:event]; 
     animation.duration = 0.25; 

     NSMutableArray *values = [NSMutableArray array]; 

     int stepCount = 10; 
     for (int i = 0; i < stepCount; i++) 
     { 
      CGFloat p = i/(float)(stepCount - 1); 
      CGSize size = [self interpolateBetweenSize:startSize andSize:endSize percentage:p]; 
      CATransform3D transform = [self transformForSize:size]; 
      [values addObject:[NSValue valueWithCATransform3D:transform]]; 
     } 

     animation.values = values; 
     return animation; 
    } 

    // All other animations use this basic animation 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event]; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    animation.removedOnCompletion = YES; 
    animation.fillMode = kCAFillModeForwards; 
    animation.duration = 0.25; 
    return animation; 
} 

我的變換是平移再旋轉,但我認爲有獨立的關鍵幀動畫,動畫通過平移和旋轉會導致瘋狂的一組動畫鎮。我已經確認,&變換的大小對於我通過的所有p值都是正確的,並且p的嚴格範圍從0到1.

我試過設置非默認定時功能,我試過設置一組定時函數,我省略了關鍵時間,我設置了一個0的重複計數,removedOnCompletion = YES,以及一個fillMode的轉發並且沒有任何效果。我沒有正確創建變換關鍵幀動畫?

+1

你能否澄清你試圖達到的確切效果?你將它描述爲一個翻譯後跟一個旋轉,但是從你的代碼看,它的邊界也是動畫 - 這是否正確?您希望圖層移動,然後旋轉,邊界在移動/旋轉動畫的兩個階段中不斷增大或縮小? – GSnyder 2012-03-11 01:01:41

+0

它爲什麼需要隱含?這段代碼看起來很拙劣。如果你想細粒度的控制,爲什麼不創建動畫並直接將其添加到圖層,你說你已經工作了?如果你想要使用默認動畫,只需從該委託方法返回'nil'即可。 – 2012-03-12 01:08:48

回答

0

這種技術可以在iOS 3中工作,但似乎在iOS 5.0中被破壞了。

5.1'神奇地'修復了這個問題,它似乎是iOS 5.0中的一個bug。我會提交一個雷達,但它現在在5.1中工作。

@Gsnyder:一些背景:我正在嘗試使用Clear-like UI(與Clear完全無關),並且提出了這個問題:http://blog.massivehealth.com/post/18563684407/clear。這應該解釋需要旋轉&翻譯。

我從此創建了一個快門過渡,將視圖細分爲N層(而不是僅僅2個),從側面看時看起來像這樣://///。

我的代碼不是動畫邊界,它使用每一步的大小來確定必要的變換。

@ Paul.s:隱式允許我在層類本身中保留這種抽象,而不污染擁有它的視圖控制器。視圖控制器應該只是改變周圍的邊界,並且圖層應該適當地移動。當視圖本身可以處理它時,我不是擁有許多自定義動畫的視圖控制器的粉絲。

我需要使用關鍵幀動畫,因爲層之間的默認動畫通過不正確的角度轉換/和_動畫,所以/// \層在整個轉換中不排隊。關鍵幀動畫確保邊緣在所有動畫都正確排列。

我在考慮這封閉,這似乎是iOS 5.0中的一個錯誤,並已被修復。感謝大家。

0
(void)animateViewWith3DCurrentView:(UIView *)currentView withPoing:(CGPoint)movePoint 
{ 
    //flip the view by 180 degrees in its place first. 
    currentView.layer.transform =   CATransform3DRotate(currentView.layer.transform,myRotationAngle(180), 0, 1, 0); 

    //set the anchor point so that the view rotates on one of its sides. 
    currentView.layer.anchorPoint = CGPointMake(0.5, 0.5); 

    //Set up scaling 

    CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:kResizeKey]; 

    //we are going to fill the screen here. So 423,337 
    [resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(423, 337)]]; 
    resizeAnimation.fillMode   = kCAFillModeForwards; 
    resizeAnimation.removedOnCompletion = NO; 

    // Set up path movement 

    UIBezierPath *movePath = [UIBezierPath bezierPath]; 

    //the control point is now set to centre of the filled screen. Change this to make the path different. 
    // CGPoint ctlPoint  = CGPointMake(0.0, 0.5); 
    CGPoint ctlPoint  = CGPointMake(1024/2, 768/2); 

    //This is the starting point of the animation. This should ideally be a function of the frame of the view to be animated. Hardcoded here. 

    // Set here to get the accurate point.. 
    [movePath moveToPoint:movePoint]; 

    //The anchor point is going to end up here at the end of the animation. 
    [movePath addQuadCurveToPoint:CGPointMake(1024/2, 768/2) controlPoint:ctlPoint]; 

    CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:kPathMovement]; 

    moveAnim.path    = movePath.CGPath; 
    moveAnim.removedOnCompletion = YES; 

    // Setup rotation animation 

    CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:kRotation]; 
    //start from 180 degrees (done in 1st line) 
    CATransform3D fromTransform  = CATransform3DMakeRotation(myRotationAngle(180), 0, 1, 0); 
    //come back to 0 degrees 
    CATransform3D toTransform   = CATransform3DMakeRotation(myRotationAngle(0), 0, 1, 0); 

    //This is done to get some perspective. 
    CATransform3D persp1 = CATransform3DIdentity; 
    persp1.m34 = 1.0/-3000; 

    fromTransform = CATransform3DConcat(fromTransform, persp1); 
    toTransform = CATransform3DConcat(toTransform,persp1); 

    rotateAnimation.toValue    = [NSValue valueWithCATransform3D:toTransform]; 
    rotateAnimation.fromValue   = [NSValue valueWithCATransform3D:fromTransform]; 
    //rotateAnimation.duration   = 2; 
    rotateAnimation.fillMode   = kCAFillModeForwards; 
    rotateAnimation.removedOnCompletion = NO; 


    // Setup and add all animations to the group 

    CAAnimationGroup *group = [CAAnimationGroup animation]; 

    [group setAnimations:[NSArray arrayWithObjects:moveAnim,rotateAnimation, resizeAnimation, nil]]; 

    group.fillMode   = kCAFillModeForwards; 
    group.removedOnCompletion = NO; 
    group.duration   = 0.7f; 
    group.delegate   = self; 

    [group setValue:currentView forKey:kGroupAnimation]; 

    [currentView.layer addAnimation:group forKey:kLayerAnimation]; 
} 
相關問題