2012-10-09 82 views
6

我正在创建一个简单的应用程序,当用户按下按钮时,屏幕上会绘制一系列线条,用户将能够看到实时绘制的这些线条(几乎就像动画一样) 。绘图动画

我的代码看起来像这样(被简化):

UIGraphicsBeginImageContext(CGSizeMake(300,300)); 
CGContextRef context = UIGraphicsGetCurrentContext(); 

for (int i = 0; i < 100; i++) { 
    CGContextMoveToPoint(context, i, i); 
    CGContextAddLineToPoint(context, i+20, i+20); 
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
    CGContextStrokePath(context); 
} 

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 

UIGraphicsEndImageContext(); 

我的问题是:

1)只要用户按下按钮时,UIThread块,直到图纸是完成。

2)我无法在屏幕上一次画出线条 - 我尝试在循环内直接设置UIImage,并尝试在循环内设置图层内容。

我该如何解决这些问题?

+0

这有帮助吗? http://stackoverflow.com/questions/9245954/mo​​ving-an-image-along-a-series-of-cgpoints –

+0

你想要什么样的延迟? – nielsbot

+0

可定制的延迟会很好 - 我认为Rob有我在找的东西......感谢您的帮助! – HHHH

回答

16

你说“就像动画”。为什么不做一个实际的动画,la Core Graphics'CABasicAnimation?你真的需要将它展示为一系列线条,或者是一个适当的动画吗?

如果你想动画线路的实际绘图,你可以这样做:

#import <QuartzCore/QuartzCore.h> 

- (void)drawBezierAnimate:(BOOL)animate 
{ 
    UIBezierPath *bezierPath = [self bezierPath]; 

    CAShapeLayer *bezier = [[CAShapeLayer alloc] init]; 

    bezier.path   = bezierPath.CGPath; 
    bezier.strokeColor = [UIColor blueColor].CGColor; 
    bezier.fillColor  = [UIColor clearColor].CGColor; 
    bezier.lineWidth  = 5.0; 
    bezier.strokeStart = 0.0; 
    bezier.strokeEnd  = 1.0; 
    [self.view.layer addSublayer:bezier]; 

    if (animate) 
    { 
     CABasicAnimation *animateStrokeEnd = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 
     animateStrokeEnd.duration = 10.0; 
     animateStrokeEnd.fromValue = [NSNumber numberWithFloat:0.0f]; 
     animateStrokeEnd.toValue = [NSNumber numberWithFloat:1.0f]; 
     [bezier addAnimation:animateStrokeEnd forKey:@"strokeEndAnimation"]; 
    } 
} 

然后,所有你需要做的就是创建UIBezierPath为您的线路,如:

- (UIBezierPath *)bezierPath 
{ 
    UIBezierPath *path = [UIBezierPath bezierPath]; 

    [path moveToPoint:CGPointMake(0.0, 0.0)]; 

    [path addLineToPoint:CGPointMake(200.0, 200.0)]; 

    return path; 
} 

如果你愿意,你可以将一堆线连成一条线,例如这里是一条粗略正弦曲线形状的系列线条:

- (UIBezierPath *)bezierPath 
{ 
    UIBezierPath *path = [UIBezierPath bezierPath]; 
    CGPoint point = self.view.center; 

    [path moveToPoint:CGPointMake(0, self.view.frame.size.height/2.0)]; 

    for (CGFloat f = 0.0; f < M_PI * 2; f += 0.75) 
    { 
     point = CGPointMake(f/(M_PI * 2) * self.view.frame.size.width, sinf(f) * 200.0 + self.view.frame.size.height/2.0); 
     [path addLineToPoint:point]; 
    } 

    return path; 
} 

而这些不会阻塞主线程。

顺便问一下,你会明显地必须将CoreGraphics.framework添加到您的目标的Build SettingsLink Binary With Libraries下。

+1

非常好 - 谢谢! 只是另一个问题 - 我打电话[路径addLineToPoint]多次(也许1000+)。在我实现了你的方法之后,我发现我的应用程序和运行的设备变得非常慢/不稳定。我对应用程序进行了描述,似乎并没有使用大量的CPU - 你知道这是为什么吗? – HHHH

+0

@HHHH我很容易想象这会对设备征税。一旦您开始超过每秒30个线段,应用程序就会更加紧跟动画。我不知道截止点在哪里(是30秒/秒?60?100?我不知道),但是在某一时刻,绘制给定帧的路径所花费的时间量动画,每个框架需要更长的时间。而且一旦动画速度减慢到每秒不到30帧,它就会变得越干。你必须以某种方式减少每秒需要绘制的线段数量。叹。 – Rob

+1

@HHHH也许您可以将动画的持续时间设置为_x/y_,其中_x_是线段的数量,_y_是您将支持的每秒的片段数量(您可能想要尝试的数字,找出你可以避免任何匆忙,也许30或60或100或...)。 – Rob