mapbox / mapbox-maps-android

Interactive, thoroughly customizable maps in native Android powered by vector tiles and OpenGL.
https://www.mapbox.com/mobile-maps-sdk
Other
464 stars 131 forks source link

Max zoom missing for camera manipulation functions and map #611

Open daniel-j-h opened 3 years ago

daniel-j-h commented 3 years ago

Hey folks, in GL JS camera / bounds functions like

allow the user to set a maxZoom so that the map doesn't zoom in too closely when the bounds are small.

It seems like this is missing in this project.

Or at least I could not find it in any of the camera / bounds manipulation functions e.g. see cameraForCoordinateBounds.

Can we get this missing feature in? Or is there another way to fit the camera to bounds, but only up to a max zoom level?

:v:

daniel-j-h commented 3 years ago

Another related issue I'm encountering regarding zoom limits: I can not find a way to set min and max zoom for the map.

In GL JS I can pass min and max zoom to the map constructor, and in the old Android SDK the map view had min and max zoom

https://github.com/mapbox/mapbox-gl-native-android/blob/3467eefe5d5f66240107b123be4b7dd62564aed0/MapboxGLAndroidSDK/src/main/res-public/values/public.xml#L28-L30

but in the latest v10-rc7 I can not find ways to set min or max zoom for the map.

I can find min and max zooms e.g. for layers but that is a different feature.

Are these missing, too, or did I not look in the right places?

daniel-j-h commented 3 years ago

Hey @ank27 @kiryldz can I get your eyes quickly on this :eyes: This is blocking me from properly integrating the maps sdk.

Am I doing something wrong or is there currently no way to

(see above for more detailed descriptions)

similar to what Mapbox GL JS offers?

kiryldz commented 3 years ago

@daniel-j-h you have precise control of min / max zoom / pitch level + bound area by using mapboxMap.setBounds(CameraBoundsOptions) function.

daniel-j-h commented 3 years ago

For the global map settings that works :raised_hands:

But what I can not find is setting a max zoom dynamically in the functions to set the camera based on bounds, e.g.

map.cameraForCoordinateBounds(bounds, insets)

The analogous Mapbox GL JS functions provide ways to set a max zoom here, so we can have

Something like

map.setBounds(..maxZoom(x).build())

map.cameraForCoordinateBounds(bounds, insets, maxZoom = y)

with x != y.

tobrun commented 3 years ago

@daniel-j-h cool seeing you around here!

Briefly looking into this issue and it seems you are missing a zoom parameter on:

  /**
   * Convert to a camera options from a given LatLngBounds, padding, bearing and pitch values.
   *
   * In order for this method to produce correct results [MapView] must be already
   * measured and inflated to have correct width and height values.
   * Calling this method in [Activity.onCreate] will lead to incorrect results.
   *
   * @param bounds The LatLngBounds to take in account when converting
   * @param padding The additional padding to take in account when converting
   * @param bearing The optional bearing to take in account when converting
   * @param pitch The optional pitch to take in account when converting
   *
   * @return Returns the converted camera options
   */
  override fun cameraForCoordinateBounds(
    bounds: CoordinateBounds,
    padding: EdgeInsets,
    bearing: Double?,
    pitch: Double?
  ): CameraOptions =
    nativeMapWeakRef.call {
      this.cameraForCoordinateBounds(
        bounds,
        padding,
        bearing,
        pitch
      )
    }

The idea for that function and related overloads, is that the zoom is a variable factor. I will ticket this upstream as a feature request and to have parity with gl-js.

Side note: an approximation of get your use-case kinda working:

    mapView.getMapboxMap()
      .apply {
        // This restrict the camera to a bounds
        setBounds(CameraBoundsOptions.Builder().maxZoom(10.0).build())

        // This calculates a bounds for a camera position for which you define a zoom
        val bounds = coordinateBoundsForCamera(CameraOptions.Builder().zoom(11.0).center(foobar).build())
        setCamera(cameraForCoordinateBounds(bounds))
      }