首页 > 解决方案 > 如何从 CALayer 中的图像中减去形状?

问题描述

我正在构建一个包含图像和徽章的自定义视图。图片显示了我想要的结果。

我可以使用 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

    }

标签: ios

解决方案


所以我不知道如何创建一个剪裁的形状来掩盖图像

是的你是!你只是自己说的。您可以使用剪辑创建一个形状并使用它来遮盖图像。您的代码的问题在于您实际上没有进行任何剪辑。

这是一个没有徽章的示例,展示了如何从图像上的圆形蒙版中取出圆形“咬”:

在此处输入图像描述

那是怎么做的?好吧,我从一个显示小猫图像的图像视图开始。然后我给那个图像视图一个蒙版。面具看起来像这样(如果你能看到面具):

在此处输入图像描述

所以现在唯一的问题是如何绘制那个面具。显然,我们通过填充大圆圈来做到这一点。但在我们这样做之前,我们创建一个由小圆圈(右下角)加上整个蒙版的边界框组成的剪切路径。因此,大圆圈最终被夹在该区域中。

请注意,徽章绘制本身,红色圆圈,现在不能是图像视图的子视图或子层,因为我们只是屏蔽了该区域!但是,这不是一个困难的问题。故事中只需要另一种观点。

在此处输入图像描述


推荐阅读