我遵循为fillRule
属性提供的winding rules documentation,该属性用于尝试识别某个点是否位于区域内。
我的问题是尝试在以下路径中添加多个路径排除项。我试图在操场上调试它,但无法确定它是如何工作的以及实现结果所需的条件。当我在同一行中添加多个弧时,就会出现问题。
结果很有趣:
let maskView = UIView(frame: UIScreen.main.bounds)
view.addSubview(maskView)
maskView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
//
let path = CGMutablePath()
path.addArc(center: CGPoint(x: 20, y: 20),
radius: 10,
startAngle: 0, endAngle: 2 * .pi,
clockwise: false)
path.addArc(center: CGPoint(x: 220, y: 20),
radius: 10,
startAngle: 0, endAngle: 2 * .pi,
clockwise: false)
path.addArc(center: CGPoint(x: 100, y: 300),
radius: 12,
startAngle: 0, endAngle: 2 * .pi,
clockwise: false)
path.addRect(CGRect(origin: .zero, size: UIScreen.main.bounds.size))
let maskLayer = CAShapeLayer()
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.path = path
maskLayer.fillRule = .evenOdd
maskView.layer.mask = maskLayer
Apple提供的代码在这里很容易做到: Flower pattern
答案 0 :(得分:1)
您没有描述您真正想要实现的目标。我假设您想要一个带有三个圆孔的矩形。
主要要理解的是,路径可以包含多个 subpaths 。每个子路径可以 closed (在开始处结束)或 open (在与开始处不同的点处结束)。在子路径中,所有线段均已连接。
您要实现的目标需要几个封闭的子路径。否则,您将无法获得断开的形状。
在您的一个示例中,很明显三个圆圈已自动通过线连接起来,从而产生了琐碎的事情。 documation of addArc
提到了这一点:
如果路径已经包含子路径,则此方法添加一行 将当前点连接到圆弧的起点。
要创建新的子路径,请移动到下一个子路径的开头(使用move
)或 close 上一个子路径(使用{ {1}})。因此,代码的中间部分应如下所示:
closeSubpath
答案 1 :(得分:0)
在您的示例中,您仅设置了一条路径。但是,为了看到fillRule
有效,您需要多个子路径。
尝试执行以下操作:
CGMutablePath.addPath
)。maskLayer
有关工作示例,请参见以下游乐场代码:
import UIKit
import PlaygroundSupport
class MaskView: UIView {
override static var layerClass: AnyClass {
return CAShapeLayer.self
}
var highlightedAreas = [CGPath]() {
didSet {
setNeedsLayout()
}
}
func setMaskColor(_ color: UIColor) {
(layer as? CAShapeLayer)?.fillColor = color.cgColor
(layer as? CAShapeLayer)?.fillRule = CAShapeLayerFillRule.evenOdd
}
override func layoutSubviews() {
super.layoutSubviews()
frame = superview?.bounds ?? .zero
let path = makePath()
(layer as? CAShapeLayer)?.path = path
}
private func makePath() -> CGPath {
let path = CGMutablePath()
path.addRect(bounds)
for subPath in highlightedAreas {
path.addPath(subPath)
}
return path
}
}
class DemoViewController: UIViewController {
private var mask: MaskView!
override func viewDidLoad() {
super.viewDidLoad()
mask = MaskView()
mask.backgroundColor = .clear
view.addSubview(mask)
mask.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
mask.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
mask.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
mask.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.backgroundColor = .green
let path1 = CGMutablePath()
path1.addRect(CGRect(x: 50, y: 50, width: 120, height: 80))
let path2 = CGMutablePath()
path2.addRect(CGRect(x: 150, y: 110, width: 80, height: 120))
mask.highlightedAreas = [path1, path2]
mask.setMaskColor(UIColor(white: 0, alpha: 0.7))
}
}
let demoController = DemoViewController()
demoController.preferredContentSize = CGSize(width: 300, height: 300)
PlaygroundPage.current.liveView = demoController
它产生的视图如下所示:
视图背景为绿色。深色是路径的填充色。 该路径包括一个与视图大小相同的大矩形和2个矩形的重叠子路径。如果有一条子路径重叠,则不会填充该路径(奇数填充规则,两条路径重叠)。但是,路径和两个子路径与填充颜色重叠的区域是可见的(3个路径重叠)。