我正在构建一个包含图像和角标(Badge)的自定义 View 。图片显示了我想要的结果。
我可以使用 Sketch 轻松实现这一目标,但编程要困难得多。
我在 CALayer 和 UIBezierPath 中找不到减法操作,所以我不知道如何创建一个裁剪形状来遮盖图像。
我想要什么
我现在拥有的
class PetAvatarView: UIView {
var image: UIImage? {
didSet {
layer.contents = image?.cgImage
}
}
private let maskLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
layer.mask = maskLayer
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
maskLayer.frame = layer.bounds
// image
let imageMaskRadius = bounds.width / 2
let imageMaskCenter = CGPoint(x: imageMaskRadius, y: imageMaskRadius)
let imageMaskPath = UIBezierPath()
imageMaskPath.addArc(withCenter: imageMaskCenter, radius: imageMaskRadius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
let badgeMaskRadius = bounds.width / 5
let badgeMaskCenter = CGPoint(x: bounds.maxX - badgeMaskRadius, y: bounds.maxY - badgeMaskRadius)
let badgeMaskPath = UIBezierPath()
badgeMaskPath.addArc(withCenter: badgeMaskCenter, radius: badgeMaskRadius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
let path = imageMaskPath
path.append(badgeMaskPath.reversing())
path.usesEvenOddFillRule = true
maskLayer.path = path.cgPath
}
最佳答案
so I have no idea how to create a clipped shape to mask the image
是的,你知道!刚才你自己也说了。您创建一个带有剪裁的形状并使用它来遮盖图像。您的代码的问题是您实际上没有做任何裁剪。
这是一个没有角标(Badge)的例子,展示了如何从图像上的圆形蒙版中取出圆形“咬合”:
这是怎么做到的?好吧,我从显示小猫图像的 ImageView 开始。然后我给那个 ImageView 一个 mask 。面具看起来像这样(如果你能看到面具):
所以现在唯一的问题是如何绘制那个面具。显然,我们是通过填充大圆圈来实现的。但在此之前,我们创建一个由小圆圈(右下角)加上整个蒙版的边界框组成的剪切路径。因此,大圆圈最终被剪裁到该区域。
请注意,角标(Badge)绘制本身(红色圆圈)现在不能是 ImageView 的 subview 或子图层,因为我们刚刚屏蔽了该区域!然而,这并不是一个困难的问题;故事中只需要有另一种观点。
关于ios - 如何从 CALayer 中的图像中减去形状?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57347771/