iOS:CoreGraphics - 使用 CGContextClip 和 lineCap = .Round 剪裁弧线

Posted

技术标签:

【中文标题】iOS:CoreGraphics - 使用 CGContextClip 和 lineCap = .Round 剪裁弧线【英文标题】:iOS: CoreGraphics - Clipping an Arc with CGContextClip and lineCap = .Round 【发布时间】:2016-06-22 21:18:23 【问题描述】:

我有一个圆弧,我画的如下:

    func drawBackgroundMask(context: CGContextRef,
                        center: CGPoint,
                        radius: CGFloat,
                        lineWidth: CGFloat,
                        startAngle: CGFloat,
                        endAngle: CGFloat) 
    let adjustedRadius: CGFloat = radius - (lineWidth/2) - 0

    CGContextSetLineWidth(context, lineWidth)
    CGContextSetLineCap(context, .Round)

    CGContextAddArc(context,
                    center.x,
                    center.y,
                    adjustedRadius,
                    startAngle,
                    endAngle,
                    0)

    //CGContextClosePath(context)
    //CGContextClip(context)
    CGContextStrokePath(context)


注释掉以上行后,我可以创建以下内容:

但是,如果我尝试通过取消注释上面的两行代码来将绘制的形状用作蒙版,然后将背景绘制成实体,我会得到不同的结果:

    func drawBackgroundMask(context: CGContextRef,
                        center: CGPoint,
                        radius: CGFloat,
                        lineWidth: CGFloat,
                        startAngle: CGFloat,
                        endAngle: CGFloat) 
    let adjustedRadius: CGFloat = radius - (lineWidth/2) - 0

    CGContextSetLineWidth(context, lineWidth)
    CGContextSetLineCap(context, .Round)

    CGContextAddArc(context,
                    center.x,
                    center.y,
                    adjustedRadius,
                    startAngle,
                    endAngle,
                    0)

    CGContextClosePath(context)
    CGContextClip(context)
    CGContextStrokePath(context)

    CGContextSetRGBFillColor(context, 100.0/255.0, 100.0/255.0, 100.0/255.0, 1.0);
    CGContextFillRect(context, rect);

谁能向我解释为什么使用绘制的弧线作为剪贴蒙版会导致它的处理方式与绘制的不同?另外,谁能告诉我正确的方法来创建一个圆弧形的面具?这个问题是我正在处理的一个更大的控件的一部分,我必须用弧形显示的形状剪辑另一个弧。

【问题讨论】:

【参考方案1】:

在您的第二个示例中,剪辑仅考虑弧的路径。各种描边参数,如线宽、大小等,仅在您实际描边路径时使用,而您并没有这样做。

首先在CGContext 中设置路径,然后将其剪辑。上下文中的路径随后被消耗。正如the documentation 所说:

确定新的剪辑路径后,该函数将上下文的当前路径重置为空路径。

所以当你调用CGContextStrokePath时,它是没有效果的,因为此时CGContext中的当前路径是空的。

听起来您想在剪辑之前使用CGContextReplacePathWithStrokedPath。文档甚至提到了这个确切的用例:

例如,您可以通过调用此函数然后调用函数 CGContextClip 来剪辑到路径的描边版本。

func drawBackgroundMask(context: CGContextRef,
                    center: CGPoint,
                    radius: CGFloat,
                    lineWidth: CGFloat,
                    startAngle: CGFloat,
                    endAngle: CGFloat) 
    let adjustedRadius: CGFloat = radius - (lineWidth/2) - 0

    CGContextSetLineWidth(context, lineWidth)
    CGContextSetLineCap(context, .Round)

    CGContextAddArc(context,
                    center.x,
                    center.y,
                    adjustedRadius,
                    startAngle,
                    endAngle,
                    0)

    CGContextReplacePathWithStrokedPath(context)
    CGContextClip(context)

    CGContextSetRGBFillColor(context, 100.0/255.0, 100.0/255.0, 100.0/255.0, 1.0);
    CGContextFillRect(context, rect);

【讨论】:

谢谢,这很有帮助!这可能对其他人有所帮助:对于那些希望继续对图形上下文执行更多“未剪辑”操作的人,请使用 context.resetClip()

以上是关于iOS:CoreGraphics - 使用 CGContextClip 和 lineCap = .Round 剪裁弧线的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发CoreGraphics核心图形框架之一——CGPath的应用

iOS绘图框架CoreGraphics分析

CoreGraphics 库在 iOS4 而不是 iOS3 中泄漏?

iOS 动画篇 CADisplayLink与CoreGraphics实现动画

书法绘图 IOS Coregraphics

如何在两个单独的图层上绘制iOS,coregraphics