Skip to content

MapViewCamera Improvements #75

@Archdoog

Description

@Archdoog

Summary

The MapViewCamera in this repository follows a SwiftUI focused approach, where the variable can be manipulated as @State or @binding. This is an ideal outcome when compared with Apple's MapKit, however our current implementation fails to give the developer complete control over the MapLibre camera manipulation methods. The primary goal of this discussion is to properly expose the MapLibre camera animation behavior through SwiftUI functionality.

Why/Current Issues

  1. The developer does not have control over the way the camera animates. This library assumes the best behavior for any state, but that may not always be accurate. Think setting the camera in an onAppear versus normally.
  2. Some MapLibre camera behaviors are not conducive to a seamless state. E.g. if you launch a MapView with user tracking, you typically get a long flyTo animation from 0.0, 0.0.
  3. Any specialized camera feature must be implemented through the MapView and coordinator. This is totally fine, but centralizes a lot of specialized assumption based camera logic.

Proposal Option 1 - SwiftUI Tooling

Disclaimer: I don't know if this is the correct tooling yet, but it's what I found when researching how MapKit allows Camera animations.

Determine if the SwiftUI Keyframes tooling would allow us to ditch MapLibre animations. Review this MapKit function as an example
mapCameraKeyFrameAnimator(trigger:keyframes:). This system may be exactly what we need to let SwiftUI handle the camera animation behavior. My understanding is the keyframe system may allow us to build custom camera animations on the SwiftUI side, which could then applied to the MapLibre map view as immediate camera updates. Avoiding any reliance on MapLibre's internal camera animation system.

If this works, we may also be able to simplify our coordinator layer a lot.

Proposal Option 2 - Google Maps Compose Inspired

GoogleMap's CameraPositionState takes a very different approach that may well be the best solution for MapLibre (both on this project and a compose counterpart). Instead of first class mutable state (@State/@binding) support, they built a custom wrapper class that internally manages its state variable. This lets developers do things like:

MapView(camera: camera)
    .onAppear {
        camera.easeTo(newPosition, duration: .seconds(1))
    }

This behavior makes things a little interesting, in that we diverge from the familiar SwiftUI approach. However, this architecture may offer several advantages:

  1. We can provide a more intuitive API for camera manipulation, such as easeTo, flyTo, and jumpTo.
  2. As google does, we can implement camera specific delegate listeners inside the camera state class. This will clean up our coordinator layer.
  3. We can hide specialized handling for things like camera caching. Think something that launches the camera state based on the last view port, and then updates the camera state correctly. This is how I'm currently mitigating the MapLibre iOS deficiency where launching the map with camera state of tracking user first pans the map from 0.0, 0.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions