在同一个UIView中绘制两次CGContext

时间:2014-12-11 17:24:14

标签: objective-c uiview core-graphics quartz-graphics cgcontext

我有一个带有自定义UIView方法的drawRect:子类,它会执行一些昂贵的计算来构建路径并使用CGContextStrokePath()在当前上下文中绘制它。

如果我的视图的大小为(x, y),我想在(0, 0), (x/2, y)上执行自定义绘图,然后使用上半部分的镜像图像填充(x/2, 0), (x, y)区域。

除了手动复制要绘制的点之外,最简单/最快的方法是什么?也许将半视图渲染到位图图像上下文并使用该视图在当前图像上下文的两半上渲染?内容是动画的,因此drawRect:大致每秒执行60次。

2 个答案:

答案 0 :(得分:1)

执行此操作的一种有效方法是在CGLayer的上下文上执行绘制操作,然后使用该图层绘制当前UIView的上下文。

有关详细信息,请参阅Core Graphics Layer Drawing on the Quartz 2D Programming Guide

基本上你会这样做:

- (void)drawRect:(CGRect)rect
{
    const CGFloat viewWidth = view.bounds.size.width;
    const CGFloat viewHeight = view.bounds.size.height;
    CGContextRef viewContext = UIGraphicsGetCurrentContext();
    CGLayerRef layer = CGLayerCreateWithContext(viewContext, CGSizeMake(viewWidth/2, viewHeight), 0);
    CGContextRef layerContext = CGLayerGetContext(layer);
    // Draw to the layerContext
    // using CGContextStrokePath() or whatever
    CGContextDrawLayerAtPoint(viewContext, CGPointZero, layer);
    CGContextTranslateCTM(viewContext, viewWidth, 0);
    CGContextScaleCTM(viewContext, -1, 1);
    CGContextDrawLayerAtPoint(viewContext, CGPointZero, layer);
    CGLayerRelease(layer);
}

此外,您可以将CGLayerRef存储为UIView ivar ,这样您就不会每帧都重新创建它。


这个解决方案在我的案例中效果很好,但有两点需要注意:

  • 似乎Apple不再建议使用CGLayers,如here所述。
  • 为了使用CGLayers正确呈现视网膜屏幕,您必须遵循steps detailed here

答案 1 :(得分:0)

您可以计算CGPath一次,您可以通过将整个路径构建为CGPath而不是将其构建为CGContext的一部分来执行此操作,或者您可以使用CGContextCopyPath在上下文中创建CGPath后获取CGPath。然后你可以抚摸一次这条路。然后使用CGContextCGContextAddPath重新放回CGContext并更改(-1, 0, 0, 1, width, 0)上的转换更改,以使您的镜像具有类似width的转换,-1执行关于x轴的反射,{{1}}应该将其移回正确位置,并再次描边路径。