Search code examples
iosuikitcore-graphicscalayer

Overlapping multiple CAShapelayers of the same size


In my application, there is a scene that requires overlapping three rounded rectangles, which I implemented through CAShapelayer and UIBezierPath.

Sample code here.

[UIColor.green, UIColor.blue, UIColor.yellow].forEach { color in
    let roundPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100), cornerRadius: 25)
    let layer = CAShapeLayer()
    layer.path = roundPath.cgPath
    layer.fillColor = color.cgColor
    layer.masksToBounds = true
    layer.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
    view.layer.addSublayer(layer)
}

But I found that in the rounded corners of the rounded rectangle, the colors overlap and strange edges appear.

enter image description here

I want to know the reason for this and how to fix it


Solution

  • CAShapeLayer's shape is drawn antialiased by default, and there doesn't appear to be a way to turn this off. Antialiased edges are done by making partially transparent pixels, and you're seeing the effect of stacking transparent pixels in different colours.

    Depending on the actual colours you will be using, one fix is to set the stroke colour of the final layer:

    if let shape = view.layer.sublayers?.last as? CAShapeLayer {
        shape.strokeColor = shape.fillColor
    }