I am parsing SVG image file and convert it paths into CAShapeLayer, after that I am adding this CAShapeLayer to UIImage View's layer. It's work fine, but the problem is that it does not fit to the UIImage View. That's output. Image 1. That's code of adding layers to UIImageView
if let svgURL = Bundle.main.url(forResource: "image", withExtension: "svg") {
let paths = SVGBezierPath.pathsFromSVG(at: svgURL)
for path in paths {
items.append(path)
let layer = createLayer(path: path)
layer.frame = self.backgroundIV.bounds
self.backgroundIV.layer.addSublayer(layer)
}
} // Create Layer from Paths Method
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
}
I Searched and added these two lines of code, i got this result
let scale = CGFloat(0.5)
for path in paths {
path.apply(CGAffineTransform(scaleX: scale, y: scale))
items.append(path)
let layer = createLayer(path: path)
layer.frame = self.backgroundIV.bounds
self.backgroundIV.layer.addSublayer(layer)
}
That's is output. Image 2
I don't know how to calculate scaleX
or scaleY
(using in CGAffineTransform
method) value according to uiImage View bounds
Edit Note: I am apply touch support to CAShapeLayer, That's code.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
guard let point = touches.first?.location(in: self.backgroundIV),
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) {
// undoModel.append()
hitLayers.append(thisLayer)
}
}
}
selectedLayer = hitLayers.last
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
undo.append(.init(stokeColor: nil, selectedLayer: selectedLayer, points: []))
if ((selectedLayer?.frame.contains(point)) != nil) {
isDragged = true
}
}
According to your updated question, calculating scale using view bounds
var paths = [SVGBezierPath]()
override func viewDidLoad() {
super.viewDidLoad()
if let svgURL = Bundle.main.url(forResource: "Freesample", withExtension: "svg") {
paths = SVGBezierPath.pathsFromSVG(at: svgURL)
backgroundIV.layer.borderColor = UIColor.black.withAlphaComponent(0.3).cgColor
backgroundIV.layer.borderWidth = 1
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let svgBounds = SVGBoundingRectForPaths(paths)
var scale = CGFloat.zero
if backgroundIV.bounds.width < backgroundIV.bounds.height {
scale = backgroundIV.bounds.width / svgBounds.width
} else {
scale = backgroundIV.bounds.height / svgBounds.height
}
self.backgroundIV.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
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)
}
}