Search code examples
swiftcalayermaskuibezierpathcaanimation

Setting layer mask to UIBezierPath superview


so I have a circle that I draw with UIBezierPath and I need to set superview to be the same with my circle, here's my code:

   override func draw(_ rect: CGRect) {
    let circlePath = UIBezierPath(arcCenter: CGPoint(x: rect.midX, y: rect.midY), radius: circleRadius, startAngle: 0.0, endAngle:CGFloat(Double.pi * 2), clockwise: true)
    let strokeColorAnimation = CABasicAnimation(keyPath: "strokeColor")
    let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")

    shapeLayer.path = circlePath.cgPath
    shapeLayer.lineWidth = 0.3 * circleRadius
    shapeLayer.fillColor = UIColor.clear.cgColor

    if oldColor == nil { oldColor = newColor }
    if oldStrokeEnd == nil { oldStrokeEnd = 0.01 * currentCGFloatProximity }

    strokeColorAnimation.fromValue = oldColor!.cgColor
    strokeColorAnimation.toValue = newColor.cgColor
    strokeColorAnimation.duration = 0.3
    strokeColorAnimation.isRemovedOnCompletion = false
    strokeColorAnimation.fillMode = kCAFillModeForwards

    strokeEndAnimation.fromValue = oldStrokeEnd
    strokeEndAnimation.toValue = 0.01 * currentCGFloatProximity
    strokeEndAnimation.duration = 0.3
    strokeEndAnimation.isRemovedOnCompletion = false
    strokeEndAnimation.fillMode = kCAFillModeForwards

    shapeLayer.add(strokeColorAnimation, forKey: strokeColorAnimation.keyPath)
    shapeLayer.add(strokeEndAnimation, forKey: strokeEndAnimation.keyPath)

    layer.mask = shapeLayer


   // layer.addSublayer(shapeLayer)


    oldColor = newColor
    oldStrokeEnd = 0.01 * currentCGFloatProximity
}

Here's when I add to superview's layer mask my shapeLayer I get this result, its black and don't change it color: enter image description here

    //layer.mask = shapeLayer

    layer.addSublayer(shapeLayer)

When I add sublayer to superview's layer I get this result: enter image description here

All I want is the result as in first image, but with colored circle. Hope for help. Sorry for my english.


Solution

  • Okay, I fixed it by adding new shape layer, but maybe someone have better solution. Now I have this code:

    override func draw(_ rect: CGRect) {
        let circlePath = UIBezierPath(arcCenter: CGPoint(x: rect.midX, y: rect.midY), radius: circleRadius, startAngle: 0.0, endAngle:CGFloat(Double.pi * 2), clockwise: true)
        let strokeColorAnimation = CABasicAnimation(keyPath: "strokeColor")
        let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")
    
        circleLayer.path = circlePath.cgPath
        circleLayer.lineWidth = 0.3 * circleRadius
        circleLayer.fillColor = UIColor.clear.cgColor
    
        backgroundLayer.path = circlePath.cgPath
        backgroundLayer.lineWidth = 0.3 * circleRadius
        backgroundLayer.strokeColor = UIColor.black.cgColor
        backgroundLayer.fillColor = UIColor.clear.cgColor
    
    
        if oldColor == nil { oldColor = newColor }
        if oldStrokeEnd == nil { oldStrokeEnd = 0.01 * currentCGFloatProximity }
    
        strokeColorAnimation.fromValue = oldColor!.cgColor
        strokeColorAnimation.toValue = newColor.cgColor
        strokeColorAnimation.duration = 0.3
        strokeColorAnimation.isRemovedOnCompletion = false
        strokeColorAnimation.fillMode = kCAFillModeForwards
    
        strokeEndAnimation.fromValue = oldStrokeEnd
        strokeEndAnimation.toValue = 0.01 * currentCGFloatProximity
        strokeEndAnimation.duration = 0.3
        strokeEndAnimation.isRemovedOnCompletion = false
        strokeEndAnimation.fillMode = kCAFillModeForwards
    
        circleLayer.add(strokeColorAnimation, forKey: strokeColorAnimation.keyPath)
        circleLayer.add(strokeEndAnimation, forKey: strokeEndAnimation.keyPath)
    
        layer.mask = backgroundLayer
    
        layer.addSublayer(circleLayer)
        oldColor = newColor
        oldStrokeEnd = 0.01 * currentCGFloatProximity
    }
    

    Result