据我所知,到目前为止,我每次在drawRect:UIView中绘制内容时,整个上下文都会被删除,然后重新绘制。
所以我必须做这样的事情来绘制一系列点:
方法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);
}
这意味着,每次我想添加一个新的时候,我必须存储我所有的Dots(这很好)并逐个重新绘制它们。不幸的是,这给了我糟糕的表现,我确信还有其他方法可以更有效地完成这项任务。
编辑:使用MrMage的代码,我做了以下操作,遗憾的是,这一点很慢,并且颜色混合不起作用。我可以尝试其他任何方法吗?
方法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
}
编辑: 毕竟我将下面提到的方法之一与仅在新矩形中重绘相结合。结果是: 快速方法:
- (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);
}
谢谢大家!
答案 0 :(得分:6)
如果您每次绘图时实际上只更改了UIView内容的一小部分(并且其余内容通常保持不变),您可以使用此功能。您不必每次都重绘UIView的所有内容,而只能使用-[UIView setNeedsDisplayInRect:]
而不是-[UIView setNeedsDisplay]
标记需要重绘的视图区域。您还需要通过设置view.clearsContextBeforeDrawing = YES;
当然,所有这些也意味着你的drawRect:
实现需要尊重rect参数,这应该是你的完整视图的rect的一小部分(除非其他东西弄脏整个矩形),并且只绘制在那部分。
答案 1 :(得分:2)
您可以将CGPath保存为班级成员。并且在绘制方法中使用它,您只需要在点改变时创建路径,但不是每次重绘视图时都创建路径,如果点是增量的,只需继续将椭圆添加到路径中。在drawRect方法中,您只需要添加路径
CGContextAddPath(context,dotsPath);
-(CGMutablePathRef)createPath
{
CGMutablePathRef dotsPath = CGPathCreateMutable();
for (Drop *drop in myPoints) {
CGPathAddEllipseInRect ( dotsPath,NULL,
CGRectMake(drop.point.x - drop.size/2, drop.point.y - drop.size/2, drop.size, drop.size));
}
return dotsPath;
}
答案 2 :(得分:1)
如果我正确理解您的问题,我会尝试直接绘制到CGBitmapContext
而不是屏幕。然后在drawRect
中,仅从rect
参数中绘制预渲染位图的一部分。
答案 3 :(得分:0)
你要绘制多少个椭圆?一般来说,Core Graphics应该能够快速绘制很多省略号。
然而,您可以将旧图纸缓存到图像中(但我不知道此解决方案是否更具性能):
UIGraphicsBeginImageContext(self.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext(); // ctx is now the image's context
[cachedImage drawAtPoint:CGPointZero];
// only plot new ellipses here...
[cachedImage release];
cachedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
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
[cachedImage drawAtPoint:CGPointZero];
答案 4 :(得分:0)
如果您能够将图形缓存为图像,则可以利用UIView的CoreAnimation支持。这将比使用Quartz快得多,因为Quartz在软件中绘图。
- (CGImageRef)cachedImage {
/// Draw to an image, return that
}
- (void)refreshCache {
myView.layer.contents = [self cachedImage];
}
- (void)actionThatChangesWhatNeedsToBeDrawn {
[self refreshCache];
}