2010-05-23 21 views
14

Tôi đoán tôi phải chuyển đổi CGRect thành một đối tượng để chuyển nó sang fromValue?Làm thế nào để tạo hiệu ứng khung của một lớp với CABasicAnimation?

Đây là cách tôi thử nó, nhưng nó không hoạt động:

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"]; 

Trả lời

-6

Tôi đoán bạn cần thay đổi dòng cuối cùng của bạn để làm cho nó hoạt động:

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

Bạn cũng có thể thiết lập một hành động đối với lớp để làm cho tất cả các thay đổi của khung hình hoạt ảnh với hoạt ảnh của bạn:

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

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

Trong CALayer'sTham chiếu phương phápbạn có thể tìm thấy cách lớp tìm kiếm các hành động để làm nổi bật các thuộc tính của nó.

+1

Cảm ơn Vladimir. Tôi đã thấy rằng CALayer không thể sinh động trực tiếp thuộc tính khung. Tài liệu nói rằng trong một hộp màu xám. Đã không nhìn thấy nó vì một lý do nào đó. – dontWatchMyProfile

+6

Dòng cuối cùng là tốt vì nó là - chìa khóa bạn chỉ định trong addAnimation có thể là một NSString tùy ý. Tôi nghĩ câu trả lời thực sự là beryllium bên dưới – Mattia

+0

'[myLayer addAnimation: frameAnimation forKey: @" frame "];' 'frame' chỉ là tên cho hoạt hình và không có gì để làm với thuộc tính thực tế đang hoạt hình ... –

82

Thuộc tính khung của một CALayer là thuộc tính bắt nguồn, phụ thuộc vào vị trí, anchorPoint, giới hạn và biến đổi của lớp. Thay vì làm động khung hình, bạn nên thay thế animate vị trí hoặc giới hạn, tùy thuộc vào hiệu ứng bạn đang cố gắng thực hiện.

Để di chuyển một lớp, bạn có thể animate 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"]; 
} 

Để thay đổi kích thước một lớp, bạn sẽ animate bounds tham số:

-(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"]; 
} 

Bạn có thể kết hợp các hình ảnh động sử dụng một CAAnimationGroup nếu bạn cần phải di chuyển và thay đổi kích thước một lớp cùng một lúc.

+0

Cảm ơn bạn đã cung cấp liên kết cực kỳ hữu ích đó! – RonLugge

+0

Tôi đã bị loại bỏ bởi câu trả lời được chấp nhận. Cảm ơn bạn! –

+3

Đây phải là câu trả lời được chấp nhận. – CodeReaper

6

chúng ta có thể thay đổi các thuộc tính của "giới hạn" và "vị trí" để animate nó, chẳng hạn như

-(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

Câu hỏi đặt ra là cổ, nhưng tôi sẽ trả lời nó anyway.

Thuộc tính khung hình không thể hoạt ảnh. Bạn phải làm sống động các thuộc tính khác. Ngoài ra, bạn phải tắt hoạt ảnh ngầm.

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

Đây là một ví dụ đơn giản, đầy đủ làm việc có thể giúp ai đó.

Chỉ cần gọi .slideUp() trên lớp học và nó sẽ trượt lên.

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() 
    } 
} 
Các vấn đề liên quan