mapbox / mapbox-maps-ios

Interactive, thoroughly customizable maps for iOS powered by vector tiles and Metal
https://www.mapbox.com/mapbox-mobile-sdk
Other
460 stars 151 forks source link

SwiftUI - Centering camera using Overview with padding not working. #2113

Open jhoanarango opened 6 months ago

jhoanarango commented 6 months ago

Environment

Observed behavior and steps to reproduce

We are presenting a map to show the different cities someone has visited throughout the year. When showing the map, we want to center the camera to show all of the cities.

In the .onAppear method we get the coordinates to create the overview . The behavior works as expected.

Code in .onAppear

.onAppear {
     let airports = summary?.routes.flatMap { $0.airports } // <-- We get the airports which hold the coordinate

      if let points = airports.flatMap({ $0.map { $0.coordinate } }) {
         let multiPoints = MultiPoint(points) // <-- We create the MultiPoint with the coordinates.
         viewport = .overview(geometry: multiPoints, geometryPadding: .init(top: 20 , leading: 20, bottom: 20, trailing: 20), maxZoom: 3, offset: .zero) // <-- We set the overview with the paddings.
     }
}

Here is a screenshot that shows the results.

[!NOTE] As you can see, the camera was centered properly and with the correct padding.

Screenshot 2024-02-08 at 4 59 10 PM

However, when the user taps through the different months to see the cities and routes that correspond to those months, the map is centering correctly, but it is not applying the paddings.

Code in .onChange

.onChange(of: summary?.routes) { oldValue, newValue in
       withViewportAnimation {
       let airports = newValue?.flatMap { $0.airports } // <-- We get the new airports which hold the coordinate

       if let points = airports.flatMap({ $0.map { $0.coordinate } }) {
          let multiPoints = MultiPoint(points) // <-- We create the MultiPoint with the coordinates.
                viewport = .overview(geometry: multiPoints, geometryPadding: .init(top: 20, leading: 20, bottom: 20, trailing: 20), maxZoom: 3, offset: .zero) // <-- We set the overview with the paddings.
          }
     }
}

Here is a screenshot that shows the results.

[!WARNING] The padding is not correct. As you can see the cities are flushed to the edges.

Screenshot 2024-02-08 at 5 18 34 PM

What is interesting is that when the map's style is changed to .satellite, the map works as expected.


.mapStyle(colorScheme == .light ? .standard : .satellite)

Here is a screen record displaying both in the .standard and .satellite. As shown in the video the padding is only applied while the map is on .satellite and not in the .standard.

https://github.com/mapbox/mapbox-maps-ios/assets/14069813/e8ffdab7-dad1-4fbc-8fcc-d771019b1c26

Expected behavior

The expected behavior is that the map should center in the overview and apply the paddings passed in.

pjleonard37 commented 6 months ago

Hi @jhoanarango -- thanks for reporting. We'll investigate this issue.

jhoanarango commented 6 months ago

@pjleonard37

Hi @jhoanarango -- thanks for reporting. We'll investigate this issue.

I noticed that the .default style of the map shows as a Global map, where the .satellite is flat. Not sure if that has to do with it, but maybe something you can look into.

persidskiy commented 6 months ago

@jhoanarango Thank you for this report.

Did you mean .standard here?

The standard style uses the Globe projection by default, but the camera framing is known to work buggy with Globe projection, we are investigating this. As a temporary workaround, you can use mercator projection with standard style:

MapReader { proxy in
  Map()
      .onStyleLoaded { _ in
          try? proxy.map?.setProjection(StyleProjection(name: .mercator))
      }
}
jhoanarango commented 6 months ago

@persidskiy

Did you mean .standard here?

Yes I did, sorry about that. And the workaround works perfectly. Please let me know when you guys are able to resolve this bug. Would love to use the global style.