【问题标题】:How to Animate CoreGraphics Drawing of Shape Using CAKeyframeAnimation如何使用 CAKeyframeAnimation 对形状的 CoreGraphics 绘图进行动画处理
【发布时间】:2012-03-18 20:59:45
【问题描述】:

我正在尝试为 UIView 子类中的 UIBeizerPath(在我的示例中为三角形)的绘制设置动画。但是,整个子视图是动画而不是形状。

我的动画有什么遗漏吗?

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

【问题讨论】:

  • 准确解释“动画绘制 UIBezierPath”的含义。您希望它一个接一个地绘制各个片段,还是什么?
  • @kurt 是的,我想为每个点的绘图设置动画,以便三角形看起来像动画

标签: uiview core-animation core-graphics cakeyframeanimation


【解决方案1】:
  • 您正在创建一个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

【讨论】:

  • 非常感谢您的解释。这真的很有帮助。
  • 原来还有一种更简单的方法:使用 CABasicAnimation 从 0 到 1 为 strokeEnd 属性设置动画。Explanation and sample code here
猜你喜欢
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多