2012-03-18 64 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

相关问题