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

iOS: camera.zoom calculates smaller zoom for camera(for:) initially #2170

Open mfazekas opened 4 months ago

mfazekas commented 4 months ago

Environment

Observed behavior and steps to reproduce

CameraOptions calculated for camera(for: coordinates) just after map is added to a view is smaller than when calculated from onStyleDataLoaded

When calculated just after map added to a view the zoom is less than the ideal (:

image

When calculated from onStyleDataLoaded the zoom is correct:

image

To reproduce use the code snippet at the end of the report to replace BasicMapExample in the Apps/Examples Xcode project. Observe the zoom values printed and uncomment the setCamera in onStyleDataLoaded handler to verify that that the zoom value is correct there.

=> zoom: Optional(3.535590091035326)
=> zoom(styleDataLoaded): Optional(3.9738550186157227)

Expected behaviour

Either camera(for:) should return an error, so signal that it's not in the state to calculate CameraOption correctly or return the correct camera settings (zoom!) for the actual bounds. I don't think any map loading is needed for that calculation.

Notes / preliminary analysis

Additional links and references

import UIKit
import MapboxMaps

final class BasicMapExample: UIViewController, ExampleProtocol {
    private var mapView: MapView!

    var handlers: [AnyCancelable] = [];

    override func viewDidLoad() {
        super.viewDidLoad()

      mapView = MapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.ornaments.options.scaleBar.visibility = .visible

      let coordinates = [
          CLLocationCoordinate2D(latitude: -74.41429582091831, longitude: -105.02738295071447),
          CLLocationCoordinate2D(latitude: -82.41571395310365, longitude: -108.67784207799926),
          CLLocationCoordinate2D(latitude: -71.45151781686236, longitude: -117.5641615804278),
          CLLocationCoordinate2D(latitude: -74.41429582091831, longitude: -105.02738295071447)
      ]

      view.addSubview(mapView)

      let camera = try! mapView.mapboxMap.camera(for: coordinates, camera:
                                                CameraOptions(), coordinatesPadding: nil,
                                              maxZoom: nil,
                                              offset: nil
      )

      print("=> zoom: \(String(describing: camera.zoom))")
      mapView.mapboxMap.setCamera(to: camera)

      handlers.append(mapView.mapboxMap.onStyleDataLoaded.observe {
        event in

        let camera1 = try! self.mapView.mapboxMap.camera(for: coordinates, camera:
                                                  CameraOptions(), coordinatesPadding: nil,
                                                maxZoom: nil,
                                                offset: nil
        )
        print("=> zoom(styleDataLoaded): \(String(describing: camera1.zoom))")
        // uncomment this next line to see the correct zoom
        // self.mapView.mapboxMap.setCamera(to: camera1)
      })

      handlers.append(mapView.mapboxMap.onMapLoaded.observe {
        event in

        let sourceData = GeoJSONSourceData.geometry(.lineString(LineString(coordinates)))
        var source = GeoJSONSource(id: "poly")
        source.data = sourceData
        try! self.mapView.mapboxMap.addSource(source)

        var layer = LineLayer(id: "poly-l", source: "poly")
        layer.lineWidth = .constant(2.0)
        layer.lineColor = .constant(StyleColor(UIColor.red))
        try! self.mapView.mapboxMap.addLayer(layer)
      })
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // The below line is used for internal testing purposes only.
        finish()
    }
}

https://github.com/rnmapbox/sponsors/issues/3

aleksproger commented 4 months ago

Hey, @mfazekas I'm currently working on the issues with camera(for:) and will take a look at this too. Thank you, for the reproduction steps!

benjamin-sweney commented 3 months ago

Hi @aleksproger - any updates on findings for this issue?

kiryldz commented 3 months ago

@mfazekas hey! do you observe similar problem in Android in v11.4.0-rc.1 when using async overload of cameraForCoordinates which makes sure that viewport is set properly.

mfazekas commented 3 months ago

@kiryldz sorry, I cannot comment on that, this was reported as an iOS only issue, so this might not have surfaced on android beacuse timing or other

nmondollot commented 1 month ago

+1 on this camera(for coordinates:camera:coordinatesPadding:maxZoom:offset:) behaves inconsistently in my app. The zoom is smaller than expected in some scenarios.

SDK Version (iOS): v11.5.1

I have to stay on v10.x until it's fixed :( Hope a fix can be found soon.