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

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

问题描述

据我目前所知,每次我在 UIView 的 drawRect: 中绘制一些东西时,整个上下文都会被擦除然后重新绘制.

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
}

毕竟我将下面提到的方法之一与仅在新矩形中重绘结合起来.结果是:快速方法:

After all I combined one of the methods mention below with redrawing only in the new rect. The result is: FAST METHOD:

- (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 setNeedsDisplayInRect:] 而不是 -[UIView setNeedsDisplay]<来标记需要重绘的视图区域,而不是每次都重绘 UIView 的所有内容/代码>.您还需要通过设置 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 的一小部分(除非其他东西弄脏了整个 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天全站免登陆