0

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

我基本上希望能够捕获触摸坐标并将它们表示为移动对象。我可以很好地使用 NSMutableArray 保存触摸。

我花了很多时间阅读 Core Animation Programming Guide 和 Quartz2D Programming Guide。我熟悉使用子图层和图层,所以如果这是我应该使用的,请指出正确的方向。

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

#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
4

2 回答 2

1

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

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

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

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

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

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

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

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

于 2012-09-07T01:44:34.313 回答
0

您真正需要的是绘制一个简单的 CALayer,具有您想要的任何形状-例如,20x20 Rect,并且每次触摸发生时-您说,您已经可以抓取位置,只需更改该图层的位置-您就可以了需要,只是:

layer.position = newPosition;

它会隐含地动画。

于 2012-09-01T22:20:11.827 回答