I am new in Swift and also in Core Animation. I want to create rectangle box around CAShapeLayer just like in this image, but I don't know.
In detail, I am parsing SVG image through PocketSVG and convert it's UIBezierPath into CAShapeLayer and after that I added these layers to UI Image View as sublayer.
here is the code where I am converting Path to CaShape Layer.
fileprivate func createLayer(path: SVGBezierPath) -> CAShapeLayer {
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
if let any = path.svgAttributes["stroke"] {
shapeLayer.strokeColor = (any as! CGColor)
}
if let any = path.svgAttributes["fill"] {
shapeLayer.fillColor = (any as! CGColor)
}
return shapeLayer
}
Below is the code, where I add layers to UIImage View (backgroundIV)
for path in paths {
path.apply(.init(scaleX: scale, y: scale))
let layer = createLayer(path: path)
layer.frame = self.backgroundIV.bounds
self.backgroundIV.layer.addSublayer(layer)
}
I also add TapGesture, RotateGesture, ScaleGesture and PanGesture to CA Shape Layers, Below is the code.
@objc func rotateLayer(_ sender: UIRotationGestureRecognizer) {
selectedLayer?.setAffineTransform(CGAffineTransform(rotationAngle: sender.rotation))
}
@objc func selectLayer(_ sender: UITapGestureRecognizer) {
let point = sender.location(in: self.backgroundIV)
guard let layers = self.backgroundIV.layer.sublayers
else { return }
var hitLayers: [CAShapeLayer] = []
selectedLayer?.lineWidth = CGFloat(0)
for subLayer in layers {
if let thisLayer = subLayer as? CAShapeLayer,
let pth = thisLayer.path {
let layerPoint: CGPoint = thisLayer.convert(point, from: self.backgroundIV.layer)
if pth.contains(layerPoint) {
hitLayers.append(thisLayer)
}
}
}
selectedLayer = hitLayers.last
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
selectedLayerRect = CGRect(origin: point, size: CGSize(width: 100, height: 100))
showPopupMenu()
}
@objc func moveLayer(_ recognizer: UIPanGestureRecognizer) {
let p = recognizer.location(in: self.backgroundIV)
selectedLayer?.position = p
}
@objc func scaleLayer(_ sender: UIPinchGestureRecognizer) {
selectedLayer?.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
In the last lines of SelectLayer method, I am highlight the selected layer by increasing it's stroke width and color.
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
When I dis select layer, I just set it's lineWidth value to 0, which is not good practice.
Is there any way to create rectangle box like in this image?
This worked for me
var selectedLayer: CAShapeLayer! {
didSet {
guard let layer = selectedLayer else {return}
box.frame = layer.path?.boundingBox ?? CGRect()
box.borderWidth = layer.contentsScale * 3
box.borderColor = UIColor.red.cgColor
self.updateControlView()
layer.addSublayer(box)
}
willSet {
self.controlView.isHidden = true
box.removeFromSuperlayer()
}
}