需要帮助在drawRect中设置动画内容

时间:2012-08-30 21:14:17

标签: ios5 core-animation core-graphics

我试图理解如何在我的UIView子类(称为MyView)中的 - (void)drawRect:(CGRect)rect中为简单对象设置动画。我是核心动画的新手,并且不确定最好的方法来做这样的事情。

我基本上希望能够捕捉触摸坐标并将它们表示为移动物体。我可以使用NSMutableArray保存触摸就好了。

我花了很多时间阅读“核心动画编程指南”和“Quartz2D编程指南”。我熟悉使用子层和层,所以请指出我正确的方向,如果这是我应该用于这样的事情。

我的主要目标是能够捕捉触摸点并将其表示为任何可以移动的形状。任何帮助表示赞赏。

#import "MyView.h"

@implementation MyView

@synthesize lastPoint;

NSMutableArray *myPoints;
CADisplayLink *theTimer;
float position = 0;

- (void) initializeTimer 
{   
    theTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(animateStuff:)];
    theTimer.frameInterval = 2; // run every other frame (ie 30fps)
    [theTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void) animateStuff:(NSTimer *)theTimer 
{
    position++;
    [self setNeedsDisplay];

}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code             
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)decoder
{
    if ((self = [super initWithCoder:decoder])) {

        // init array
        myPoints = [NSMutableArray array];

        position = 1;

        [self initializeTimer];

    }
    return self; 
}


- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{            
    // store point in array
    UITouch *touch = [touches anyObject];
    lastPoint = [touch locationInView:self];
    [myPoints addObject:[NSValue valueWithCGPoint:lastPoint]]; // store CGPoint as NSValue

}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(context, 2.0);
    CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);    
    CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);

    // draw all points in array
    NSUInteger pointCount = [myPoints count];
    for (int i = 0; i < pointCount; i++) {
        NSValue *v = [myPoints objectAtIndex:i];
        CGPoint p = v.CGPointValue;

        CGRect currentRect = CGRectMake(p.x-10+position, p.y-10, 20, 20);    
        CGContextAddRect(context, currentRect);  
    }
    CGContextDrawPath(context, kCGPathFillStroke);         
}

@end

2 个答案:

答案 0 :(得分:1)

drawRect中的动画绝对是绝对错误的方法。这迫使图形硬件每次都重新渲染整个视图。它将非常缓慢和生涩。您希望尽可能避免触发drawRect。

相反,你应该使用某种形式的动画。有很多选择。

您可以将每个对象视为一个视图,并使用UIView动画方法,如animateWithDuration:completion:或其中一个变体。

您可以制作每个想要为图层设置动画的内容,将这些图层添加为视图的子图层,并使用隐式动画为其设置动画(您只需更改图层的位置属性或其他“动画”属性,以及系统为您设置动画或显式动画(您可以在其中创建不同类型的CAAnimation对象并将其添加到图层中。)

最后,您可以使用CAShapeLayer,并为图层中安装的路径设置动画。只要在动画步骤之间的路径中保留相同数量和类型的控制点,就可以使用形状图层一次为一大堆形状设置动画。您还可以通过复杂的方式和许多其他有趣的效果来改变曲线的动画。在CAShapeLayer中设置动画曲线意味着使用CGPath对象和CAAnimation对象。

UIView动画是迄今为止最容易使用的动画,它针对性能进行了优化。如果您可以使用视图动画来执行您想要的操作,那么您可能应该这样做。

接下来的复杂程度是隐式图层动画。

使用CAAnimation对象的显式动画是最复杂的,但也是最强大的。

答案 1 :(得分:0)

你真正需要的是绘制一个简单的CALayer,你想要的任何形状 - 例如,20x20 Rect,每当你触摸时 - 你说,你可以抓住位置,只需更改该层的位置 - 这就是你所需要的,只是:

layer.position = newPosition;

它会暗含动画。