SwiftUI:缩放UIBezierPath的图像以适应其父视图



我正试图从UIBezierPath(跑步锻炼的路线(构建一个Image,这是可行的,但它被剪掉了,因为它不完全适合它的父视图。如何缩放它以整齐地适应父视图?

struct WorkoutRoutePathForCard: View {

@State var coords: [CLLocationCoordinate2D]

var body: some View {
VStack {
GeometryReader { geometry in
Image(uiImage: getPathImage(geometry: geometry, coordinates: coords))
}
}
.frame(width: 300, height: 300)
}



func getPathImage(geometry: GeometryProxy, coordinates: [CLLocationCoordinate2D]) -> UIImage {
let r = MKPolylineRenderer(polyline: .init(coordinates: coordinates, count: coordinates.count))
let path = r.path!
let bezier = UIBezierPath(cgPath: path)
bezier.apply(.init(scaleX: 0.05, y: 0.05))
let renderer = UIGraphicsImageRenderer(bounds: .init(x: geometry.size.width / 2, y: geometry.size.height / 2, width: geometry.size.width, height: geometry.size.height))
let image = renderer
.image { context in
let size = renderer.format.bounds.size
UIColor.clear.setFill()
context.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
UIColor.green.setStroke()
bezier.lineWidth = 5
bezier.stroke()
}

return image
}

}


Example Coords: 
let myCoords: [CLLocationCoordinate2D] = [
.init(latitude: 40.45447016031924, longitude: -79.98049149097986),
.init(latitude: 40.45480813412811, longitude: -79.98042319697163),
.init(latitude: 40.45520567452709, longitude: -79.98001536452354),
.init(latitude: 40.455495507707624, longitude: -79.97960818847154),
.init(latitude: 40.455669734914764, longitude: -79.97945181240351),
.init(latitude: 40.455962469448195, longitude: -79.97968629102485),
.init(latitude: 40.45610586081772, longitude: -79.97963772295147),
.init(latitude: 40.4562591381994, longitude: -79.97981354297161),
.init(latitude: 40.45641915652463, longitude: -79.98013725326828),
.init(latitude: 40.456916076807275, longitude: -79.98057473087967),
.init(latitude: 40.45696543637191, longitude: -79.98111241962415),
.init(latitude: 40.45658094060211, longitude: -79.9815750340419),
.init(latitude: 40.45633241325463, longitude: -79.98213689422677),
.init(latitude: 40.456005715732466, longitude: -79.98264837678823),
.init(latitude: 40.45566308287974, longitude: -79.98313926160685),
.init(latitude: 40.455482156946836, longitude: -79.98339909382858),
.init(latitude: 40.455431346304245, longitude: -79.98350236725716),
.init(latitude: 40.45510882284016, longitude: -79.98392447563586),
.init(latitude: 40.45473960595957, longitude: -79.983839249276),
.init(latitude: 40.45419535436064, longitude: -79.98372212671902),
.init(latitude: 40.45418877882902, longitude: -79.98317032323045),
.init(latitude: 40.45409625179924, longitude: -79.98337238791783),
.init(latitude: 40.453702136321205, longitude: -79.98383112841569),
.init(latitude: 40.45333968007657, longitude: -79.9843527839287),
.init(latitude: 40.453015767532904, longitude: -79.98470010009864),
.init(latitude: 40.452756328441005, longitude: -79.98519113714033),
.init(latitude: 40.452431463269576, longitude: -79.98567567972282),
.init(latitude: 40.45211699883118, longitude: -79.98613715996406),
.init(latitude: 40.45180291771363, longitude: -79.98659016559115),
.init(latitude: 40.45130420151201, longitude: -79.98645138634363),
.init(latitude: 40.450950946065355, longitude: -79.98694918550348),
.init(latitude: 40.4506422698389, longitude: -79.98745765702658),
.init(latitude: 40.450327618934, longitude: -79.98798683271804),
.init(latitude: 40.449992148160234, longitude: -79.98850139382195),
.init(latitude: 40.449618449168355, longitude: -79.98819580017779),
.init(latitude: 40.44961717175458, longitude: -79.98813056857591),
.init(latitude: 40.44981214587717, longitude: -79.98784037287729),
.init(latitude: 40.45010798888214, longitude: -79.98731732932961),
.init(latitude: 40.45044357521365, longitude: -79.98682415678626),
.init(latitude: 40.45074079718418, longitude: -79.9863306116891),
.init(latitude: 40.45102708900798, longitude: -79.9858412709496),
.init(latitude: 40.45135186368611, longitude: -79.98537165274894),
.init(latitude: 40.451693905584776, longitude: -79.98487831686919),
.init(latitude: 40.451695266189674, longitude: -79.9846134771703),
.init(latitude: 40.4519948921123, longitude: -79.98410232215397),
.init(latitude: 40.45211625978421, longitude: -79.9836457603929),
.init(latitude: 40.4517601191445, longitude: -79.98325242116834),
.init(latitude: 40.45199766696091, longitude: -79.98257604896489),
.init(latitude: 40.452354714382864, longitude: -79.98217790736636),
.init(latitude: 40.452722542943405, longitude: -79.98175806857729),
.init(latitude: 40.453023655083086, longitude: -79.98131890493468),
.init(latitude: 40.453351081755606, longitude: -79.98081647794157),
.init(latitude: 40.453523684592156, longitude: -79.98081191524473),
.init(latitude: 40.45386406976813, longitude: -79.9812629401123),
.init(latitude: 40.45418688545403, longitude: -79.98132777596072)
]

经过几次测试后,我认为问题(截取图像(可能是由于renderer的边界而不是子视图/父视图的大小。也就是说,图片不能在geometry.size给出的边界内绘制(太小(。

此示例代码显示了我的结果,其中我删除了GeometryReader,并将bezier.bounds用于renderer边界。有了这些边界,图像就不会被剪裁并完美地融入其父视图中。

struct ContentView: View {
let myCoords: [CLLocationCoordinate2D] = [
.init(latitude: 40.45447016031924, longitude: -79.98049149097986),
.init(latitude: 40.45480813412811, longitude: -79.98042319697163),
.init(latitude: 40.45520567452709, longitude: -79.98001536452354),
.init(latitude: 40.455495507707624, longitude: -79.97960818847154),
.init(latitude: 40.455669734914764, longitude: -79.97945181240351),
.init(latitude: 40.455962469448195, longitude: -79.97968629102485),
.init(latitude: 40.45610586081772, longitude: -79.97963772295147),
.init(latitude: 40.4562591381994, longitude: -79.97981354297161),
.init(latitude: 40.45641915652463, longitude: -79.98013725326828),
.init(latitude: 40.456916076807275, longitude: -79.98057473087967),
.init(latitude: 40.45696543637191, longitude: -79.98111241962415),
.init(latitude: 40.45658094060211, longitude: -79.9815750340419),
.init(latitude: 40.45633241325463, longitude: -79.98213689422677),
.init(latitude: 40.456005715732466, longitude: -79.98264837678823),
.init(latitude: 40.45566308287974, longitude: -79.98313926160685),
.init(latitude: 40.455482156946836, longitude: -79.98339909382858),
.init(latitude: 40.455431346304245, longitude: -79.98350236725716),
.init(latitude: 40.45510882284016, longitude: -79.98392447563586),
.init(latitude: 40.45473960595957, longitude: -79.983839249276),
.init(latitude: 40.45419535436064, longitude: -79.98372212671902),
.init(latitude: 40.45418877882902, longitude: -79.98317032323045),
.init(latitude: 40.45409625179924, longitude: -79.98337238791783),
.init(latitude: 40.453702136321205, longitude: -79.98383112841569),
.init(latitude: 40.45333968007657, longitude: -79.9843527839287),
.init(latitude: 40.453015767532904, longitude: -79.98470010009864),
.init(latitude: 40.452756328441005, longitude: -79.98519113714033),
.init(latitude: 40.452431463269576, longitude: -79.98567567972282),
.init(latitude: 40.45211699883118, longitude: -79.98613715996406),
.init(latitude: 40.45180291771363, longitude: -79.98659016559115),
.init(latitude: 40.45130420151201, longitude: -79.98645138634363),
.init(latitude: 40.450950946065355, longitude: -79.98694918550348),
.init(latitude: 40.4506422698389, longitude: -79.98745765702658),
.init(latitude: 40.450327618934, longitude: -79.98798683271804),
.init(latitude: 40.449992148160234, longitude: -79.98850139382195),
.init(latitude: 40.449618449168355, longitude: -79.98819580017779),
.init(latitude: 40.44961717175458, longitude: -79.98813056857591),
.init(latitude: 40.44981214587717, longitude: -79.98784037287729),
.init(latitude: 40.45010798888214, longitude: -79.98731732932961),
.init(latitude: 40.45044357521365, longitude: -79.98682415678626),
.init(latitude: 40.45074079718418, longitude: -79.9863306116891),
.init(latitude: 40.45102708900798, longitude: -79.9858412709496),
.init(latitude: 40.45135186368611, longitude: -79.98537165274894),
.init(latitude: 40.451693905584776, longitude: -79.98487831686919),
.init(latitude: 40.451695266189674, longitude: -79.9846134771703),
.init(latitude: 40.4519948921123, longitude: -79.98410232215397),
.init(latitude: 40.45211625978421, longitude: -79.9836457603929),
.init(latitude: 40.4517601191445, longitude: -79.98325242116834),
.init(latitude: 40.45199766696091, longitude: -79.98257604896489),
.init(latitude: 40.452354714382864, longitude: -79.98217790736636),
.init(latitude: 40.452722542943405, longitude: -79.98175806857729),
.init(latitude: 40.453023655083086, longitude: -79.98131890493468),
.init(latitude: 40.453351081755606, longitude: -79.98081647794157),
.init(latitude: 40.453523684592156, longitude: -79.98081191524473),
.init(latitude: 40.45386406976813, longitude: -79.9812629401123),
.init(latitude: 40.45418688545403, longitude: -79.98132777596072)
]

var body: some View {
WorkoutRoutePathForCard(coords: myCoords)
.frame(width: 333, height: 333)
.border(.blue)
}
}
struct WorkoutRoutePathForCard: View {
@State var coords: [CLLocationCoordinate2D]
@State var img = UIImage()

var body: some View {
Image(uiImage: getPathImage(coordinates: coords)).resizable()
}
func getPathImage(coordinates: [CLLocationCoordinate2D]) -> UIImage {
let r = MKPolylineRenderer(polyline: .init(coordinates: coordinates, count: coordinates.count))
let path = r.path!

let bezier = UIBezierPath(cgPath: path)
bezier.apply(.init(scaleX: 0.05, y: 0.05))
let renderer = UIGraphicsImageRenderer(bounds: CGRect(x: 0, y: 0, width: bezier.bounds.width, height: bezier.bounds.height))
let image = renderer
.image { context in
let size = renderer.format.bounds.size

UIColor.clear.setFill()
context.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))

UIColor.green.setStroke()
bezier.lineWidth = 5
bezier.stroke()
}
return image
}

}

最新更新