组合重叠的UIBezierPaths以创建单个掩码

时间:2015-12-01 21:14:25

标签: ios mask uibezierpath

我想在我的视图中创建一个形状像几个圆圈的面具。此处blurView是我希望删除的视图,frames包含这些圈子/椭圆的CGRect帧值。

let holes = UIBezierPath()
 for f in frames {
      let p = UIBezierPath(ovalInRect: f)
      holes.appendPath(p)
}

 let path = UIBezierPath(rect: blurView.bounds)
 path.appendPath(holes)
 path.usesEvenOddFillRule = true
 let mask = CAShapeLayer()
 mask.path = path.CGPath
 mask.fillRule = kCAFillRuleEvenOdd
 blurView.layer.mask = mask

这非常有效,除非圆圈重叠,blurView的内容显示而不是下面的视图。我该如何解决这个问题?

编辑:使用Rob的答案,我到了某个地方,但不是我想去的地方。面具的边缘是粗糙的,它们缺少抗锯齿:

screenshot

有什么方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

基本思想是用不透明的颜色填充位图上下文,然后清除我们想要剪辑的任何内容。抓取该位图上下文的图像并用作掩码。

如果您愿意,可以将其复制到游乐场:

import UIKit

// A couple of overlapping circles to play with
let frames = [
    CGRect(x: 100, y: 100, width: 200, height: 200),
    CGRect(x: 50, y: 50, width: 200, height: 200)
]

let blurView = UIImageView(image: ...) // <== You can drag an image here. Literals are cool.

let size = blurView.bounds.size
let scale = UIScreen.mainScreen().scale

// First, create a bitmap context to work in.
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue | CGBitmapInfo.ByteOrder32Little.rawValue)
let ctx = CGBitmapContextCreate(nil, Int(size.width*scale), Int(size.height*scale),
8, 4 * Int(size.width * scale), CGColorSpaceCreateDeviceRGB(), bitmapInfo.rawValue)
CGContextScaleCTM(ctx, scale, scale)

// iOS draws upsidedown from Core Graphics, so you'll probably want to flip your context:
CGContextConcatCTM(ctx, CGAffineTransformMake(1, 0, 0, -1, 0, size.height))

// Everything we want to draw should be opaque
// Everything we want to clip should be translucent

CGContextSetGrayFillColor(ctx, 1, 1) // white
CGContextFillRect(ctx, blurView.bounds)

// And now we clear all our circles
CGContextSetBlendMode(ctx, .Clear)
CGContextSetGrayFillColor(ctx, 1, 0) // clear
for f in frames {
    CGContextFillEllipseInRect(ctx, f)
}

// Make the masking image
let maskImage = CGBitmapContextCreateImage(ctx)

// For your playground amusement (you can quicklook this line)
UIImage(CGImage: maskImage)

// Create the masking layer
let mask = CALayer()
mask.frame = blurView.layer.frame
mask.contents = maskImage

// And apply it
blurView.layer.mask = mask

// And the final so you can quicklook it
blurView

enter image description here