Je suis en train de convertir un MKPolyline en un BezierPath puis un CAShapeLayer puis en ajoutant la couche en tant que sous-couche à un UIView. En train de lutter pour s'assurer que le chemin n'est pas tracé en dehors des limites de l'UIView. Je ne veux pas masquer et faire disparaître une partie du chemin, mais plutôt m'assurer que chaque point est redimensionné et positionné au centre de l'UIView.Comment faire pour que CAShapeLayer se redimensionne pour s'adapter à UIView
func addPathToView() {
guard let path = createPath(onView: polylineView) else { return }
path.fit(into: polylineView.bounds).moveCenter(to: polylineView.center).fill()
path.lineWidth = 3.0
path.lineJoinStyle = .round
guard let layer = createCAShapeLayer(fromBezierPath: path) else { return }
layer.path = getScaledPath(fromPath: path, layer: layer)
layer.frame = polylineView.bounds
layer.position.x = polylineView.bounds.minX
layer.position.y = polylineView.bounds.minY
polylineView.layer.addSublayer(layer)
}
func createCAShapeLayer(fromBezierPath path: UIBezierPath?) -> CAShapeLayer? {
guard let path = path else { print("No Path"); return nil }
let pathLayer = CAShapeLayer(path: path, lineColor: UIColor.red, fillColor: UIColor.clear)
return pathLayer
}
func createPath(onView view: UIView?) -> UIBezierPath? {
guard let polyline = Polyline().createPolyline(forLocations: locations) else { print("No Polyline"); return nil }
guard let points = convertMapPointsToCGPoints(fromPolyline: polyline) else { print("No CGPoints"); return nil }
let path = UIBezierPath(points: points)
return path
}
func convertMapPointsToCGPoints(fromPolyline polyline: MKPolyline?) -> [CGPoint]? {
guard let polyline = polyline else { print("No Polyline"); return nil }
let mapPoints = polyline.points()
var points = [CGPoint]()
for point in 0..<polyline.pointCount {
let coordinate = MKCoordinateForMapPoint(mapPoints[point])
points.append(mapView.convert(coordinate, toPointTo: view))
}
return points
}
func getScaledPath(fromPath path: UIBezierPath, layer: CAShapeLayer) -> CGPath? {
let boundingBox = path.cgPath.boundingBoxOfPath
let boundingBoxAspectRatio = boundingBox.width/boundingBox.height
let viewAspectRatio = polylineView.bounds.size.width/polylineView.bounds.size.height
let scaleFactor: CGFloat
if (boundingBoxAspectRatio > viewAspectRatio) {
// Width is limiting factor
scaleFactor = polylineView.bounds.size.width/boundingBox.width
} else {
// Height is limiting factor
scaleFactor = polylineView.bounds.size.height/boundingBox.height
}
var affineTransorm = CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)
let transformedPath = path.cgPath.copy(using: &affineTransorm)
guard let tPath = transformedPath else { print ("nope"); return nil }
return tPath
}
extension UIBezierPath
{
func moveCenter(to:CGPoint) -> Self{
let bound = self.cgPath.boundingBox
let center = bounds.center
let zeroedTo = CGPoint(x: to.x-bound.origin.x, y: to.y-bound.origin.y)
let vector = center.vector(to: zeroedTo)
offset(to: CGSize(width: vector.dx, height: vector.dy))
return self
}
func offset(to offset:CGSize) -> Self{
let t = CGAffineTransform(translationX: offset.width, y: offset.height)
applyCentered(transform: t)
return self
}
func fit(into:CGRect) -> Self{
let bounds = self.cgPath.boundingBox
let sw = into.size.width/bounds.width
let sh = into.size.height/bounds.height
let factor = min(sw, max(sh, 0.0))
return scale(x: factor, y: factor)
}
func scale(x:CGFloat, y:CGFloat) -> Self{
let scale = CGAffineTransform(scaleX: x, y: y)
applyCentered(transform: scale)
return self
}
func applyCentered(transform: @autoclosure() -> CGAffineTransform) -> Self{
let bound = self.cgPath.boundingBox
let center = CGPoint(x: bound.midX, y: bound.midY)
var xform = CGAffineTransform.identity
xform = xform.concatenating(CGAffineTransform(translationX: -center.x, y: -center.y))
xform = xform.concatenating(transform())
xform = xform.concatenating(CGAffineTransform(translationX: center.x, y: center.y))
apply(xform)
return self
}
}
extension UIBezierPath
{
convenience init(points:[CGPoint])
{
self.init()
//connect every points by line.
//the first point is start point
for (index,aPoint) in points.enumerated()
{
if index == 0 {
self.move(to: aPoint)
}
else {
self.addLine(to: aPoint)
}
}
}
}
//2. To create layer use this extension
extension CAShapeLayer
{
convenience init(path:UIBezierPath, lineColor:UIColor, fillColor:UIColor)
{
self.init()
self.path = path.cgPath
self.strokeColor = lineColor.cgColor
self.fillColor = fillColor.cgColor
self.lineWidth = path.lineWidth
self.opacity = 1
self.frame = path.bounds
}
}
pourquoi vous décalez dans votre fonction moveCenter? – Ocunidee
@Ocunidee le UIBezierPathExtension était une tentative trouvée en ligne pour résoudre mon problème [link] (https://github.com/xhamr/paintcode-path-scale/blob/master/UIBezierPath%2B.swift) Actuellement, je me sens comme je suis Il suffit de mettre en place des parties de différents casse-tête et de faire à peine quelque chose de travail, c'est pourquoi je suis venu à empiler débordement pour de l'aide! Je ne peux pas déterminer pourquoi je ne peux pas simplement redimensionner la couche, définir son cadre aux limites de l'uiview et être fait. – lifewithelliott
avez-vous essayé de commenter la partie sur le décalage? – Ocunidee