2012-03-18 63 views
7

我想在UIView子類中爲UIBeizerPath(在我的示例中爲三角形)繪製動畫。然而,整個子視圖是動畫而不是形狀。如何動畫CoreGraphics使用CAKeyframeAnimation繪製形狀使用CAKeyframeAnimation

有什麼我失蹤的動畫?

- (void)drawRect:(CGRect)rect { 

    CAShapeLayer *drawLayer = [CAShapeLayer layer]; 

    drawLayer.frame   = CGRectMake(0, 0, 100, 100); 
    drawLayer.strokeColor  = [UIColor greenColor].CGColor; 
    drawLayer.lineWidth  = 4.0; 

    [self.layer addSublayer:drawLayer]; 

    UIBezierPath *path = [UIBezierPath bezierPath]; 

    [path moveToPoint:CGPointMake(0,0)]; 
    [path addLineToPoint:CGPointMake(50,100)]; 
    [path addLineToPoint:CGPointMake(100,0)]; 
    [path closePath]; 

    CGPoint center = [self convertPoint:self.center fromView:nil]; 

    [path applyTransform:CGAffineTransformMakeTranslation(center.x, center.y)]; 

    [[UIColor redColor] set]; 

    [path fill]; 

    [[UIColor blueColor] setStroke]; 

    path.lineWidth = 3.0f; 

    [path stroke]; 

    CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 

    pathAnimation.duration  = 4.0f; 
    pathAnimation.path   = path.CGPath; 
    pathAnimation.calculationMode = kCAAnimationLinear; 

    [drawLayer addAnimation:pathAnimation forKey:@"position"]; 
} 
+0

解釋正是 「動畫的UIBezierPath繪圖」 的意思。你希望它能夠一個接一個地繪製各個細分市場嗎? – 2012-03-18 21:31:23

+0

@kurt是的,我想動畫每個點的繪製動畫,所以三角形似乎是動畫 – 2012-03-18 23:31:26

回答

17
  • 您正在創建一個CAShapeLayer,但後來沒有做任何有用的事情。我們來解決這個問題。

  • 請勿在-drawRect:中設置圖層和動畫,因爲這嚴格意味着需要使用CoreGraphics或UIKit API進行繪製。相反,您希望CAShapeLayer繪製三角形 - 這樣您就可以對其進行動畫處理。

  • CAKeyframeAnimation.path是指完全不同的東西(例如沿路徑移動圖層)。

  • 您的動畫是動畫position圖層的值。毫不奇怪,它會移動圖層!您想要改爲創建path值。

  • CAKeyframeAnimation背後的想法是,您提供了一個values的數組來設置圖層的屬性。在關鍵幀之間的時間內,它將在兩個相鄰關鍵幀之間進行插值。所以你需要給它幾條路 - 每一條路。

  • 內插任意路徑很困難。當路徑具有相同數量和類型的元素時,CA的路徑插值效果最佳。所以,我們確保我們所有的路徑具有相同的結構,只是有一些點在彼此之上。

  • 動畫的祕密,也許一般電腦:你必須準確解釋你想要發生的事情。 「我想動畫每個點的繪圖,所以它看起來是動畫」是不夠的信息。

這裏有一個UIView子類,我覺得確實你要求什麼,或至少接近。要動畫,請掛鉤按鈕,直到-animate:動作。

SPAnimatedShapeView.h:

#import <UIKit/UIKit.h> 

@interface SPAnimatedShapeView : UIView 

- (IBAction)animate:(id)sender; 

@end 

SPAnimatedShapeView.m:

#import "SPAnimatedShapeView.h" 
#import <QuartzCore/QuartzCore.h> 

@interface SPAnimatedShapeView() 
@property (nonatomic, retain) CAShapeLayer* shapeLayer; 
@end 

@implementation SPAnimatedShapeView 

@synthesize shapeLayer = _shapeLayer; 

- (void)dealloc 
{ 
    [_shapeLayer release]; 
    [super dealloc]; 
} 

- (void)layoutSubviews 
{ 
    if (!self.shapeLayer) 
    { 
     self.shapeLayer = [[[CAShapeLayer alloc] init] autorelease]; 
     self.shapeLayer.bounds = CGRectMake(0, 0, 100, 100);  // layer is 100x100 in size 
     self.shapeLayer.position = self.center;     // and is centered in the view 
     self.shapeLayer.strokeColor = [UIColor blueColor].CGColor; 
     self.shapeLayer.fillColor = [UIColor redColor].CGColor; 
     self.shapeLayer.lineWidth = 3.f; 

     [self.layer addSublayer:self.shapeLayer]; 
    } 
} 

- (IBAction)animate:(id)sender 
{ 
    UIBezierPath* path0 = [UIBezierPath bezierPath]; 
    [path0 moveToPoint:CGPointZero]; 
    [path0 addLineToPoint:CGPointZero]; 
    [path0 addLineToPoint:CGPointZero]; 
    [path0 addLineToPoint:CGPointZero]; 

    UIBezierPath* path1 = [UIBezierPath bezierPath]; 
    [path1 moveToPoint:CGPointZero]; 
    [path1 addLineToPoint:CGPointMake(50,100)]; 
    [path1 addLineToPoint:CGPointMake(50,100)]; 
    [path1 addLineToPoint:CGPointMake(50,100)]; 

    UIBezierPath* path2 = [UIBezierPath bezierPath]; 
    [path2 moveToPoint:CGPointZero]; 
    [path2 addLineToPoint:CGPointMake(50,100)]; 
    [path2 addLineToPoint:CGPointMake(100,0)]; 
    [path2 addLineToPoint:CGPointMake(100,0)]; 

    UIBezierPath* path3 = [UIBezierPath bezierPath]; 
    [path3 moveToPoint:CGPointZero]; 
    [path3 addLineToPoint:CGPointMake(50,100)]; 
    [path3 addLineToPoint:CGPointMake(100,0)]; 
    [path3 addLineToPoint:CGPointZero]; 

    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];  
    animation.duration = 4.0f; 
    animation.values = [NSArray arrayWithObjects:(id)path0.CGPath, (id)path1.CGPath, (id)path2.CGPath, (id)path3.CGPath, nil]; 
    [self.shapeLayer addAnimation:animation forKey:nil]; 
} 

@end 
+0

非常感謝你的解釋。這真的有幫助。 – 2012-03-19 14:22:43

+5

結果有一個更簡單的方法:使用從0到1的「CABasicAnimation」爲'strokeEnd'屬性設置動畫。[說明和示例代碼](http://oleb.net/blog/2010/12/animating-drawing -of-cgpath與 - cashapelayer /)。 – 2012-03-20 00:52:53

相關問題