bakuiseok
bakuiseok

Reputation: 161

Why is the drawn UIBezierPath positioned in the bottom right without specifying a central position in CAShapeLayer?

I tried to centralize UIBezierPath in a superview, but the UIBezierPath is positioned at the bottom right, not at the center.

I set the value of anchorPoint to (0.5, 0.5), position self.view.center or self.view.frame.width / 2, but the UIBezierPath is not centered.

import UIKit

/* ViewSection */
class ViewController: UIViewController {
    @IBOutlet weak var Toolbar: UIToolbar!
    @IBOutlet weak var UIToolbarButtonItem: UIBarButtonItem!
    @IBAction func UIToolbarButtonItem(_ sender: Any) {
        let objectFramePath = UIBezierPath.init(roundedRect: CGRect(x: 0, y:  0, width: 150, height: 150), byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 39.5, height: 39.5))

        let shapeLayer = CAShapeLayer()
        shapeLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
        shapeLayer.position = self.view.center
        shapeLayer.fillColor = UIColor.blue.cgColor
        shapeLayer.path = objectFramePath.cgPath

        self.view.layer.addSublayer(shapeLayer)
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

The result is this:

screenshot of the result

Upvotes: 1

Views: 73

Answers (1)

Rob
Rob

Reputation: 437422

The anchor doesn’t work because the new layer doesn’t have a frame. If you set that, it works:

let rect = CGRect(x: 0, y:  0, width: 150, height: 150)
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 39.5, height: 39.5))

let shapeLayer = CAShapeLayer()
shapeLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
shapeLayer.frame = rect
shapeLayer.position = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
shapeLayer.fillColor = UIColor.blue.cgColor
shapeLayer.path = path.cgPath

view.layer.addSublayer(shapeLayer)

Alternatively, you can just set the origin of the path:

let size = CGSize(width: 150, height: 150)
let origin = CGPoint(x: view.bounds.midX - size.width / 2,
                     y: view.bounds.midY - size.height / 2)

let path = UIBezierPath(roundedRect: CGRect(origin: origin, size: size), byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 39.5, height: 39.5))

let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.blue.cgColor
shapeLayer.path = path.cgPath

view.layer.addSublayer(shapeLayer)

By the way, notice that I do not reference center, because as the docs say, “The center point is specified in points in the coordinate system of its superview.”

Always use bounds (and if you need the center of that, the midX and midY of the bounds), because that will always be in the coordinate system of the view in question. In this case it just happens to not make much of a difference, but we should note that the middle of the bounds and the center within the superview are two completely different things.

Upvotes: 2

Related Questions