gpt4 book ai didi

swift - 如何确保 CAShapeLayer 调整大小以适应 UIView

转载 作者:搜寻专家 更新时间:2023-10-31 22:58:02 24 4
gpt4 key购买 nike

我目前正在将 MKPolyline 转换为 BezierPath,然后转换为 CAShapeLayer,然后将该层作为子层添加到 UIView。目前正在努力确保路径不会在 UIView 的边界之外绘制。我不想屏蔽并让部分路径消失,而是确保每个点都调整大小并定位在 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
}
}

enter image description here

最佳答案

UIBezierPath 可以像 CGRectCGPoint 或使用 CGAffineTransform 的“CGSize”一样缩放。🐙

// calculate the scale
//
let scaleWidth = toSize.width / fromSize.width
let scaleHeight = toSize.height / fromSize.height

// re-scale the path
//
path.apply(CGAffineTransform(scaleX: scaleWidth, y: scaleHeight))

关于swift - 如何确保 CAShapeLayer 调整大小以适应 UIView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42085795/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com