如何绘制内层的蒙版?
How to draw inside layer's mask?
我正在使用以下代码生成此代码(在 drawRect 内):
let path = CGMutablePath()
path.addArc(center: self.circleCenter, radius: radius, startAngle: 0.0, endAngle: 2 * 3.14, clockwise: false)
let whitePath = UIBezierPath(cgPath: path)
UIColor.white.setStroke()
whitePath.lineWidth = 3
whitePath.stroke()
path.addRect(CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
let maskLayer = CAShapeLayer()
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.path = path
maskLayer.fillRule = kCAFillRuleEvenOdd
layer.mask = maskLayer
但是,我想把圆圈的顶部涂白,这样整个圆圈里面都是白色的,但我不知道该怎么做,因为我已经设置了 layer.mask
成为 CAShape 层,所以我在这个圆圈内所做的任何绘图都不会显示出来。
掩码需要是一个圆圈,因为实际上对于我的大多数用例,对于这个自定义 UIView,它不会剪切另一个视图的顶部,所以使用圆圈效果很好。如何绘制圆的顶部区域?
编辑:我希望这部分(我用红色圈出的地方)填充为白色:
所以我希望最终图像看起来像(抱歉质量不好,在我的 iPad 上手动绘制):
面具不是画的,它是面具。如果你想强制你的圆圈的一部分变成白色,你需要画成白色。如果您要覆盖 drawRect,只需在绘制图像后绘制您想要的白色区域。
如果您想创建一个视图来执行您想要的操作而不覆盖 drawRect,这通常是更好的方法,您可以在视图层上设置一个遮罩层,并在顶部添加另一个形状层包含白色形状的图像视图。
你说:
... the "Messaging" is from a view underneath. The dark shadow view is a UIView on top, and I have a mask in the dark shadow view so I can see through underneath it.
这里有两种方法:
如果你真的想使用掩码,你需要一个复杂的视图层次结构,它有四个主要视图:根视图(白色),chrome视图(包含所有视图的视图) chrome 添加圆形遮罩时将被遮罩;例如,您需要遮罩的圆的顶部),添加您的 UI 元素视图时不会被遮罩chrome 和调光视图的遮罩)和调光视图(也将被遮罩)。后三个需要是主视图的子视图(不要将消息按钮放在 chrome 视图上,而是使其成为自己的视图,所以当你屏蔽 chrome 时,这些 UI 元素不会被屏蔽掉)。
你最终会得到类似下面的结果(这是在添加蒙版后显示的):
然后您可以使调光视图可见并屏蔽它和背景视图:
@IBAction func didTapButton(_ sender: Any) {
dimmingView.alpha = 0.5
let center = messagingView.center
let radius = messagingView.frame.width * 0.7
mask(center: center, radius: radius, in: messagingView.superview!, on: dimmingView)
mask(center: center, radius: radius, in: messagingView.superview!, on: backgroundView)
}
private func mask(center: CGPoint, radius: CGFloat, in view: UIView, on viewToMask: UIView) {
let point = view.convert(center, to: viewToMask)
let path = UIBezierPath(rect: viewToMask.bounds)
path.addArc(withCenter: point, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true)
let mask = CAShapeLayer()
mask.fillColor = UIColor.white.cgColor
mask.path = path.cgPath
mask.fillRule = kCAFillRuleEvenOdd
viewToMask.layer.mask = mask
}
因此,在调光视图不可见且没有遮罩的情况下,您可以看到之前的视图:
然后在调暗视图可见并且它和 "chrome" 视图都被屏蔽后:
恕我直言,更简单的方法是:
- 截取消息视图快照;
- 添加调光视图(模糊消息视图);
- 在调光视图的顶部添加圆形视图(不透明和白色);和
- 在圆圈顶部添加消息视图的快照(或其他再现)。
这会产生一种感觉,就像您是 "revealing" 消息按钮一样,但您真正在做的是添加变暗视图、一个圆圈和消息按钮的另一种形式。这避免了向各种视图添加蒙版的所有笨拙。
我正在使用以下代码生成此代码(在 drawRect 内):
let path = CGMutablePath()
path.addArc(center: self.circleCenter, radius: radius, startAngle: 0.0, endAngle: 2 * 3.14, clockwise: false)
let whitePath = UIBezierPath(cgPath: path)
UIColor.white.setStroke()
whitePath.lineWidth = 3
whitePath.stroke()
path.addRect(CGRect(x: 0, y: 0, width: frame.width, height: frame.height))
let maskLayer = CAShapeLayer()
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.path = path
maskLayer.fillRule = kCAFillRuleEvenOdd
layer.mask = maskLayer
但是,我想把圆圈的顶部涂白,这样整个圆圈里面都是白色的,但我不知道该怎么做,因为我已经设置了 layer.mask
成为 CAShape 层,所以我在这个圆圈内所做的任何绘图都不会显示出来。
掩码需要是一个圆圈,因为实际上对于我的大多数用例,对于这个自定义 UIView,它不会剪切另一个视图的顶部,所以使用圆圈效果很好。如何绘制圆的顶部区域?
编辑:我希望这部分(我用红色圈出的地方)填充为白色:
所以我希望最终图像看起来像(抱歉质量不好,在我的 iPad 上手动绘制):
面具不是画的,它是面具。如果你想强制你的圆圈的一部分变成白色,你需要画成白色。如果您要覆盖 drawRect,只需在绘制图像后绘制您想要的白色区域。
如果您想创建一个视图来执行您想要的操作而不覆盖 drawRect,这通常是更好的方法,您可以在视图层上设置一个遮罩层,并在顶部添加另一个形状层包含白色形状的图像视图。
你说:
... the "Messaging" is from a view underneath. The dark shadow view is a UIView on top, and I have a mask in the dark shadow view so I can see through underneath it.
这里有两种方法:
如果你真的想使用掩码,你需要一个复杂的视图层次结构,它有四个主要视图:根视图(白色),chrome视图(包含所有视图的视图) chrome 添加圆形遮罩时将被遮罩;例如,您需要遮罩的圆的顶部),添加您的 UI 元素视图时不会被遮罩chrome 和调光视图的遮罩)和调光视图(也将被遮罩)。后三个需要是主视图的子视图(不要将消息按钮放在 chrome 视图上,而是使其成为自己的视图,所以当你屏蔽 chrome 时,这些 UI 元素不会被屏蔽掉)。
你最终会得到类似下面的结果(这是在添加蒙版后显示的):
然后您可以使调光视图可见并屏蔽它和背景视图:
@IBAction func didTapButton(_ sender: Any) { dimmingView.alpha = 0.5 let center = messagingView.center let radius = messagingView.frame.width * 0.7 mask(center: center, radius: radius, in: messagingView.superview!, on: dimmingView) mask(center: center, radius: radius, in: messagingView.superview!, on: backgroundView) } private func mask(center: CGPoint, radius: CGFloat, in view: UIView, on viewToMask: UIView) { let point = view.convert(center, to: viewToMask) let path = UIBezierPath(rect: viewToMask.bounds) path.addArc(withCenter: point, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true) let mask = CAShapeLayer() mask.fillColor = UIColor.white.cgColor mask.path = path.cgPath mask.fillRule = kCAFillRuleEvenOdd viewToMask.layer.mask = mask }
因此,在调光视图不可见且没有遮罩的情况下,您可以看到之前的视图:
然后在调暗视图可见并且它和 "chrome" 视图都被屏蔽后:
恕我直言,更简单的方法是:
- 截取消息视图快照;
- 添加调光视图(模糊消息视图);
- 在调光视图的顶部添加圆形视图(不透明和白色);和
- 在圆圈顶部添加消息视图的快照(或其他再现)。
这会产生一种感觉,就像您是 "revealing" 消息按钮一样,但您真正在做的是添加变暗视图、一个圆圈和消息按钮的另一种形式。这避免了向各种视图添加蒙版的所有笨拙。