Drawing animation

走远了吗. 提交于 2019-12-03 05:20:07

问题


I'm creating a simple app where when the user presses a button, a series of lines will be drawn on the screen and the user will be able to see these lines drawn in real time (almost like an animation).

My code looks something like this (has been simplified):

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();

My problem is that:

1) As soon as the user presses the button, the UIThread blocks until the drawing is done.

2) I can't get the lines to be drawn on the screen one at a time - I've tried setting the UIImage directly inside the loop and also tried setting a layer content inside the loop.

How do I get around these problems?


回答1:


You say "just like an animation". Why not do an actual animation, a la Core Graphics' CABasicAnimation? Do you really need to show it as a series of lines, or is a proper animation ok?

If you want to animate the actual drawing of the line, you could do something like:

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

Then all you have to do is create the UIBezierPath for your line, e.g.:

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

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

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

    return path;
}

If you want, you can patch a bunch of lines together into a single path, e.g. here is a roughly sine curve shaped series of lines:

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

And these don't block the main thread.

By the way, you'll obviously have to add the CoreGraphics.framework to your target's Build Settings under Link Binary With Libraries.



来源:https://stackoverflow.com/questions/12808084/drawing-animation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!