简体   繁体   English

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

[英]SwiftUI: Scaling an Image of a UIBezierPath to fit inside its parent view

I'm trying to build an Image from a UIBezierPath (a running workout's route), and this is working however it's getting clipped because it doesn't fit perfectly inside it's parent view.我正在尝试从UIBezierPath (正在运行的锻炼路线)构建Image ,这正在工作,但是它被剪裁了,因为它不完全适合它的父视图。 How can I scale it to fit neatly inside the parent view?如何缩放它以整齐地适合父视图?

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)

]

After a few more tests, I think that the problem (getting image clipped) may be due to the bounds of the renderer , not the size of the child/parent views.经过几次测试后,我认为问题(图像被剪辑)可能是由于renderer的边界,而不是子/父视图的大小。 That is, the picture cannot be drawn within the bounds given by the geometry.size (too small).也就是不能在geometry.size (太小)给定的范围内绘制图片。

This example code shows my results, where I removed the GeometryReader , and used the bezier.bounds for the renderer bounds.此示例代码显示了我的结果,其中我删除了GeometryReader ,并使用bezier.bounds作为renderer边界。 With these bounds the image is not clipped and fit perfectly inside it's parent view.有了这些边界,图像就不会被剪裁并完全适合它的父视图。

 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
     }
     
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM