Search code examples
iosswiftuibezierpathcashapelayer

How to align CAShapeLayer To parent View


I have a bezier path shape which I need to set as its parent view frame shape. I need to scale it to the correct size so it can fit in its own parent as borders. I am using CAShapeLayer to add the bezier path to the parent view subLayer and then animate it.

class FrameView: NSObject {
    var shapeLayer: CAShapeLayer!

    func frameLayer(frame targetFrame: UIView) -> CAShapeLayer {
        let bezierPath = UIBezierPath()
        bezierPath.move(to: CGPoint(x: 34.93, y: 0))
        bezierPath.addCurve(to: CGPoint(x: 36.05, y: 0.2), controlPoint1: CGPoint(x: 34.79, y: 0), controlPoint2: CGPoint(x: 35.45, y: -0))
        bezierPath.addLine(to: CGPoint(x: 36.16, y: 0.22))
        bezierPath.addCurve(to: CGPoint(x: 38, y: 2.85), controlPoint1: CGPoint(x: 37.27, y: 0.63), controlPoint2: CGPoint(x: 38, y: 1.68))
        bezierPath.addCurve(to: CGPoint(x: 38, y: 3), controlPoint1: CGPoint(x: 38, y: 3), controlPoint2: CGPoint(x: 38, y: 3))
        // MORE CODE FOR BEZIERPATH ...

        bezierPath.apply(CGAffineTransform(translationX: targetFrame.bounds.minX, y: targetFrame.bounds.minY))
        bezierPath.apply(CGAffineTransform(scaleX: 2.0, y: 2.0))

        self.shapeLayer = CAShapeLayer()
        shapeLayer.path = bezierPath.cgPath
        shapeLayer.fillColor = UIColor.white.cgColor
        shapeLayer.strokeColor = UIColor.clear.cgColor
        return shapeLayer

Below is what I'm getting. I tried some solutions in StackOverflow and didn't work for me. What I need is to set that white frame as borders of the parent view which is the transparent gray rectangle:

enter image description here


Solution

  • Found the solution, First mistake was i was changing the UIView frame somewhere in ViewController, and it was giving me always a wrong coordinate than what i expected, so i just created the UIView in Storyboard and used its outlet.

    second mistake was a wrong mathematical calculation.

    to fit the shapeLayer in its parent view size, i've did this:

    bezierPath.apply(CGAffineTransform(scaleX: abs(targetFrame.bounds.size.width / bezierPath.cgPath.boundingBox.width), y: abs(targetFrame.bounds.size.height / bezierPath.cgPath.boundingBox.height)))
    

    before i tried dividing target frame and bezierRect sizes but i was not using abs() and it was giving me wrong result !

    enter image description here