1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-09-21 09:59:10 +03:00
Macaw/Source/svg/SVGView.swift
2016-12-01 21:08:31 +07:00

152 lines
5.8 KiB
Swift

import UIKit
open class SVGView: MacawView {
@IBInspectable open var fileName: String? {
didSet {
render()
}
}
override open func layoutSubviews() {
super.layoutSubviews()
render()
}
private let rootNode = Group()
private func render() {
let viewBounds = self.bounds
let svgNode = SVGParser.parse(
path: fileName ?? ""
)
if let nodeBounds = svgNode.bounds()?.cgRect() {
let svgWidth = nodeBounds.origin.x + nodeBounds.width
let svgHeight = nodeBounds.origin.y + nodeBounds.height
let viewAspectRatio = viewBounds.width / viewBounds.height
let svgAspectRatio = svgWidth / svgHeight
let scaleX = viewBounds.width / svgWidth
let scaleY = viewBounds.height / svgHeight
switch self.contentMode {
case .scaleToFill:
svgNode.place = Transform.scale(
sx: Double(scaleX),
sy: Double(scaleY)
)
case .scaleAspectFill:
let scaleX, scaleY: CGFloat
if viewAspectRatio > svgAspectRatio {
scaleX = viewBounds.width / svgWidth
scaleY = viewBounds.width / (svgWidth / svgAspectRatio)
} else {
scaleX = viewBounds.height / (svgHeight / svgAspectRatio)
scaleY = viewBounds.height / svgHeight
}
let calculatedWidth = svgWidth * scaleX
let calculatedHeight = svgHeight * scaleY
svgNode.place = Transform.move(
dx: (viewBounds.width / 2 - calculatedWidth / 2).doubleValue,
dy: (viewBounds.height / 2 - calculatedHeight / 2).doubleValue
).scale(
sx: scaleX.doubleValue,
sy: scaleX.doubleValue
)
case .scaleAspectFit:
let calculatedXWidth = scaleX * svgWidth
let calculatedXHeight = scaleX * svgHeight
let calculatedYWidth = scaleY * svgWidth
let calculatedYHeight = scaleY * svgHeight
if calculatedXWidth <= viewBounds.width && calculatedXHeight <= viewBounds.height {
svgNode.place = Transform.move(
dx: (viewBounds.midX - calculatedXWidth / 2).doubleValue,
dy: (viewBounds.midY - calculatedXHeight / 2).doubleValue
).scale(
sx: scaleX.doubleValue,
sy: scaleX.doubleValue
)
} else if calculatedYWidth <= viewBounds.width && calculatedYHeight <= viewBounds.height {
svgNode.place = Transform.move(
dx: (viewBounds.midX - calculatedYWidth / 2).doubleValue,
dy: (viewBounds.midY - calculatedYHeight / 2).doubleValue
).scale(
sx: scaleY.doubleValue,
sy: scaleY.doubleValue
)
}
case .center:
svgNode.place = Transform.move(
dx: getMidX(viewBounds, nodeBounds).doubleValue,
dy: getMidY(viewBounds, nodeBounds).doubleValue
)
case .top:
svgNode.place = Transform.move(
dx: getMidX(viewBounds, nodeBounds).doubleValue,
dy: 0
)
case .bottom:
svgNode.place = Transform.move(
dx: getMidX(viewBounds, nodeBounds).doubleValue,
dy: getBottom(viewBounds, nodeBounds).doubleValue
)
case .left:
svgNode.place = Transform.move(
dx: 0,
dy: getMidY(viewBounds, nodeBounds).doubleValue
)
case .right:
svgNode.place = Transform.move(
dx: getRight(viewBounds, nodeBounds).doubleValue,
dy: getMidY(viewBounds, nodeBounds).doubleValue
)
case .topLeft:
break
case .topRight:
svgNode.place = Transform.move(
dx: getRight(viewBounds, nodeBounds).doubleValue,
dy: 0
)
case .bottomLeft:
svgNode.place = Transform.move(
dx: 0,
dy: getBottom(viewBounds, nodeBounds).doubleValue
)
case .bottomRight:
svgNode.place = Transform.move(
dx: getRight(viewBounds, nodeBounds).doubleValue,
dy: getBottom(viewBounds, nodeBounds).doubleValue
)
case .redraw:
break
}
}
rootNode.contents = [svgNode]
self.node = rootNode
}
private func getMidX(_ viewBounds: CGRect, _ nodeBounds: CGRect) -> CGFloat {
let viewMidX = viewBounds.midX
let nodeMidX = nodeBounds.midX + nodeBounds.origin.x
return viewMidX - nodeMidX
}
private func getMidY(_ viewBounds: CGRect, _ nodeBounds: CGRect) -> CGFloat {
let viewMidY = viewBounds.midY
let nodeMidY = nodeBounds.midY + nodeBounds.origin.y
return viewMidY - nodeMidY
}
private func getBottom(_ viewBounds: CGRect, _ nodeBounds: CGRect) -> CGFloat {
return viewBounds.maxY - nodeBounds.maxY + nodeBounds.origin.y
}
private func getRight(_ viewBounds: CGRect, _ nodeBounds: CGRect) -> CGFloat {
return viewBounds.maxX - nodeBounds.maxX + nodeBounds.origin.x
}
}