2010-05-23 32 views
14

我想我必須將CGRect轉換爲一個對象以將它傳遞給fromValue?如何用CABasicAnimation動畫化圖層的框架?

這是我的嘗試,但它不工作:

CABasicAnimation *frameAnimation = [CABasicAnimation animationWithKeyPath:@"frame"]; 
frameAnimation.duration = 2.5; 
frameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
frameAnimation.fromValue = [NSValue valueWithCGRect:myLayer.frame]; 
frameAnimation.toValue = [NSValue valueWithCGRect:theNewFrameRect]; 
[myLayer addAnimation:frameAnimation forKey:@"MLC"]; 

回答

-6

我猜你需要改變你的最後一行,使其工作:

[myLayer addAnimation:frameAnimation forKey:@"frame"]; 

您也可以設置該層的作用,使你的動畫動畫所有幀之間的變化:

CABasicAnimation *frameAnimation = [CABasicAnimation animation]; 
frameAnimation.duration = 2.5; 
frameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

myLayer.actions = [NSDictionary dictionaryWithObjectsAndKeys:frameAnimation, @"frame", nil]; 

在的CALayer的actionForKey:方法參考,您可以找到圖層如何查找動畫來對其屬性進行動畫處理。

+1

謝謝弗拉基米爾。我發現CALayer不能直接爲框架屬性設置動畫。文檔說明在灰色框中。由於某種原因沒有看到它。 – dontWatchMyProfile 2010-05-23 19:18:31

+6

最後一行沒問題 - 你在addAnimation中指定的鍵值可以是任意的NSString。我認爲實際的答案是鈹的低於 – Mattia 2012-01-24 20:52:56

+0

'[myLayer addAnimation:frameAnimation forKey:@「frame」];''frame'只是一個動畫的名稱,並且與實際的動畫無關...... – 2015-11-16 09:53:23

82

CALayer的frame屬性是派生屬性,取決於圖層的位置,anchorPoint,邊界和變換。取而代之的是對框架進行動畫處理,而不是對框架進行動畫處理,而應根據您要實現的效果來設置動畫位置或邊界。

要移動一個層,你可以動畫position

-(void)moveLayer:(CALayer*)layer to:(CGPoint)point 
{ 
    // Prepare the animation from the current position to the new position 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; 
    animation.fromValue = [layer valueForKey:@"position"]; 

    // NSValue/+valueWithPoint:(NSPoint)point is available on Mac OS X 
    // NSValue/+valueWithCGPoint:(CGPoint)point is available on iOS 
    // comment/uncomment the corresponding lines depending on which platform you're targeting 

    // Mac OS X 
    animation.toValue = [NSValue valueWithPoint:NSPointFromCGPoint(point)]; 
    // iOS 
    //animation.toValue = [NSValue valueWithCGPoint:point]; 

    // Update the layer's position so that the layer doesn't snap back when the animation completes. 
    layer.position = point; 

    // Add the animation, overriding the implicit animation. 
    [layer addAnimation:animation forKey:@"position"]; 
} 

要調整層,你會動畫bounds參數:

-(void)resizeLayer:(CALayer*)layer to:(CGSize)size 
{ 
    // Prepare the animation from the old size to the new size 
    CGRect oldBounds = layer.bounds; 
    CGRect newBounds = oldBounds; 
    newBounds.size = size; 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"]; 

    // NSValue/+valueWithRect:(NSRect)rect is available on Mac OS X 
    // NSValue/+valueWithCGRect:(CGRect)rect is available on iOS 
    // comment/uncomment the corresponding lines depending on which platform you're targeting 

    // Mac OS X 
    animation.fromValue = [NSValue valueWithRect:NSRectFromCGRect(oldBounds)]; 
    animation.toValue = [NSValue valueWithRect:NSRectFromCGRect(newBounds)]; 
    // iOS 
    //animation.fromValue = [NSValue valueWithCGRect:oldBounds]; 
    //animation.toValue = [NSValue valueWithCGRect:newBounds]; 

    // Update the layer's bounds so the layer doesn't snap back when the animation completes. 
    layer.bounds = newBounds; 

    // Add the animation, overriding the implicit animation. 
    [layer addAnimation:animation forKey:@"bounds"]; 
} 

您可以使用CAAnimationGroup如果結合這些動畫您需要同時移動和調整圖層大小。

+0

感謝您提供非常有用的鏈接! – RonLugge 2011-05-12 18:56:33

+0

我被接受的答案拋棄了。謝謝! – 2012-04-03 21:51:20

+3

這應該是被接受的答案。 – CodeReaper 2013-03-28 12:27:30

6

我們可以改變屬性「邊界」和「位置」動畫它,如

-(void)handleTap2:(UITapGestureRecognizer *)recognizer { 

    UIImageView *vw = (UIImageView *)[recognizer view]; 

    CGPoint startPoint = CGPointMake(vw.frame.size.width/2+vw.frame.origin.x, vw.frame.size.height/2+vw.frame.origin.y); 
    CGPoint endPoint = CGPointMake(160, 240); 

    CGRect startBounds = vw.bounds; 
    CGRect stopBounds = self.view.bounds; 

    layer = [CALayer layer]; 
    layer.frame = self.view.frame; 
    layer.contents = (id)[vw.image CGImage]; 

    [self.view.window.layer addSublayer:layer]; 

    CABasicAnimation * baseAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; 

    baseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
    baseAnimation.fromValue = [NSValue valueWithCGPoint:startPoint] ; 
    baseAnimation.toValue = [NSValue valueWithCGPoint:endPoint] ; 

    CABasicAnimation * boundsAnimation = [CABasicAnimation animationWithKeyPath:@"bounds"]; 

    boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 
    boundsAnimation.fromValue = [NSValue valueWithCGRect:startBounds] ; boundsAnimation.toValue = [NSValue valueWithCGRect:stopBounds] ; 

    CAAnimationGroup * group =[CAAnimationGroup animation]; 
    group.removedOnCompletion=NO; group.fillMode=kCAFillModeForwards; 
    group.animations =[NSArray arrayWithObjects:baseAnimation, boundsAnimation, nil];  
    group.duration = 0.7; 

    [layer addAnimation:group forKey:@"frame"]; 
} 
3

問題是古董,但我無論如何都會回答。

框架屬性不具動畫性。你必須動畫其他屬性。你也必須禁用隱式動畫。

let updatedBounds = ... 
    let animation = CABasicAnimation(keyPath: "bounds") 
    animation.duration = 0.5 
    //it's better to start animation from presentation layer in case there is already animation going on 
    animation.fromValue = customLayer.presentation()?.bounds 
    animation.toValue = updatedBounds 
    customLayer.add(animation, forKey: nil) 

    //disable implicit animation for thoose properties 
    CATransaction.begin() 
    CATransaction.setDisableActions(true) 
    //update properties so they will be updated at the end of animation 
    customLayer.bounds = updatedBounds 
    customLayer.position = originalRect.origin 
    customLayer.anchorPoint = CGPoint(x: 0, y: 0) 
    CATransaction.commit() 
1

下面是一個簡單的,完全有效的示例,可以幫助某人。

只要在課上打電話.slideUp(),它就會滑動。

class Slidey: YourViewClass { 

    func slideUp() { 

     print("\n\n SLIDE") 

     let FF = layer.position 
     var TT = FF 
     TT.y -= 100 
     print(FF) 
     print(TT) 

     CATransaction.begin() 
     CATransaction.setDisableActions(true) 

     CATransaction.setCompletionBlock{ [weak self] in 

      print("DONE") 
     } 

     let a = CABasicAnimation(keyPath: "position") 

     a.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) 

     a.isCumulative = false 
     a.autoreverses = false 
     a.isRemovedOnCompletion = true 
     a.repeatCount = 0 
     a.fromValue = FF 
     a.toValue = TT 
     a.duration = 0.70 
     layer.add(a, forKey: nil) 

     CATransaction.commit() 
    } 
}