在UIView(iPhone)中逐步绘制 [英] Drawing incrementally in a UIView (iPhone)

查看:140
本文介绍了在UIView(iPhone)中逐步绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,到目前为止,我每次在drawRect:UIView中绘制内容时,整个上下文都会被删除,然后重新绘制。

As far as I have understood so far, every time I draw something in the drawRect: of a UIView, the whole context is erased and then redrawn.

所以我必须做这样的事情来绘制一系列点:

So I have to do something like this to draw a series of dots:

方法A:在每次通话时绘制所有内容

- (void)drawRect:(CGRect)rect { 

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextDrawImage(context, self.bounds, maskRef);      //draw the mask
    CGContextClipToMask(context, self.bounds, maskRef);     //respect alpha mask
    CGContextSetBlendMode(context, kCGBlendModeColorBurn);  //set blending mode

    for (Drop *drop in myPoints) {
        CGContextAddEllipseInRect(context, CGRectMake(drop.point.x - drop.size/2, drop.point.y - drop.size/2, drop.size, drop.size));
    }

    CGContextSetRGBFillColor(context, 0.5, 0.0, 0.0, 0.8);
    CGContextFillPath(context);
}

这意味着,我必须存储我的所有点(没关系) - 每次我想添加一个新的,一个接一个地把它们全部拉出来。不幸的是,这给了我糟糕的表现,我确信还有其他方法可以做到这一点,效率更高。

Which means, I have to store all my Dots (that's fine) and re-draw them all, one by one, every time I want to add a new one. Unfortunately this gives my terrible performance and I am sure there is some other way of doing this, more efficiently.

编辑:使用MrMage的代码,我做了以下,不幸的是同样慢,颜色混合不起作用。我可以尝试其他任何方法吗?

Using MrMage's code I did the following, which unfortunately is just as slow and the color blending doesn't work. Any other method I could try?

方法B:保存UIImage中的先前绘制并仅绘制新内容和此图像

- (void)drawRect:(CGRect)rect
{
    //draw on top of the previous stuff
    UIGraphicsBeginImageContext(self.frame.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext(); // ctx is now the image's context
    [cachedImage drawAtPoint:CGPointZero];
    if ([myPoints count] > 0)
    {
        Drop *drop = [myPoints objectAtIndex:[myPoints count]-1];
        CGContextClipToMask(ctx, self.bounds, maskRef);         //respect alpha mask
        CGContextAddEllipseInRect(ctx, CGRectMake(drop.point.x - drop.dropSize/2, drop.point.y - drop.dropSize/2, drop.dropSize, drop.dropSize));
        CGContextSetRGBFillColor(ctx, 0.5, 0.0, 0.0, 1.0);
        CGContextFillPath(ctx);
    }
    [cachedImage release];
    cachedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
    UIGraphicsEndImageContext();

    //draw on the current context   
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, self.bounds, maskRef);          //draw the mask
    CGContextSetBlendMode(context, kCGBlendModeColorBurn);      //set blending mode
    [cachedImage drawAtPoint:CGPointZero];                      //draw the cached image
}

编辑:
毕竟我结合了以下提到的方法之一,只在新的rect中重绘。结果是:
快速方法:

- (void)addDotAt:(CGPoint)point
{
    if ([myPoints count] < kMaxPoints) {
        Drop *drop = [[[Drop alloc] init] autorelease];
        drop.point = point;
        [myPoints addObject:drop];
        [self setNeedsDisplayInRect:CGRectMake(drop.point.x - drop.dropSize/2, drop.point.y - drop.dropSize/2, drop.dropSize, drop.dropSize)];      //redraw
    }
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextDrawImage(context, self.bounds, maskRef);                                              //draw the mask
    CGContextClipToMask(context, self.bounds, maskRef);                                             //respect alpha mask
    CGContextSetBlendMode(context, kCGBlendModeColorBurn);                                          //set blending mode

    if ([myPoints count] > 0)
    {
        Drop *drop = [myPoints objectAtIndex:[myPoints count]-1];
        CGPathAddEllipseInRect (dotsPath, NULL, CGRectMake(drop.point.x - drop.dropSize/2, drop.point.y - drop.dropSize/2, drop.dropSize, drop.dropSize));
    }
    CGContextAddPath(context, dotsPath);

    CGContextSetRGBFillColor(context, 0.5, 0.0, 0.0, 1.0);
    CGContextFillPath(context);
}

谢谢大家!

推荐答案

如果您每次绘制时实际上只更改了UIView内容的一小部分(并且其余内容通常保持不变),您可以使用它。不是每次都重绘UIView的所有内容,而是只使用 - [UIView setNeedsDisplayInRect:] 而不是<$ c来标记需要重绘的视图区域$ c> - [UIView setNeedsDisplay] 。您还需要确保在绘图之前不清除图形内容,方法是设置 view.clearsContextBeforeDrawing = YES;

If you are only actually changing a small portion of the UIView's content every time you draw (and the rest of the content generally stays the same), you can use this. Rather than redraw all the content of the UIView every single time, you can mark only the areas of the view that need redrawing using -[UIView setNeedsDisplayInRect:] instead of -[UIView setNeedsDisplay]. You also need to make sure that the graphics content is not cleared before drawing by setting view.clearsContextBeforeDrawing = YES;

当然,所有这些也意味着你的 drawRect:实现需要尊重rect参数,这应该是你的完整视图的rect的一小部分(除非其他东西弄脏了)整个矩形),只绘制那部分。

Of course, all this also means that your drawRect: implementation needs to respect the rect parameter, which should then be a small subsection of your full view's rect (unless something else dirtied the entire rect), and only draw in that portion.

这篇关于在UIView(iPhone)中逐步绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆