Search code examples
iosswiftuikitmapboxmapbox-ios

MapBox for iOS prevent rotating map when the device is rotated


I'm using the Mapbox SDK for iOS and have decided to implement a functionality that allows switching between the map sticking to the North and the map following the device direction with a tap of a button.

Currently, I am able to start 'following' the user's direction and rotating the camera to the north. Here's the code I'm using

    var showsToNorth = false
    

    override func viewDidLoad() {
        super.viewDidLoad()
        
        ...
        // starts rotating map based on device direction when map opens
        mapView.viewport.transition(to: mapView.viewport.makeFollowPuckViewportState(options: .init(pitch: 0)))
        ...
    }   
    
    @objc
    func currentLocationButtonAction() {
        showsToNorth.toggle()
        if showsToNorth {
            var cameraOption = CameraOptions(cameraState: mapView.cameraState)
            cameraOption.bearing = 0
            cameraOption.center = mapView.location.latestLocation?.coordinate
            mapView.camera.ease(to:  cameraOption, duration: 0)
        } else {
            mapView.viewport.transition(to: mapView.viewport.makeFollowPuckViewportState(options: .init(pitch: 0)))
        }
    }

the problem occurs when the code executes in the 'true' case; the map rotates correctly to the north, but as soon as the device rotates, it automatically continues tracking the device's direction. I've tried many ways but still can't find any solution.

Will appreciate your help.

Edit: https://imgur.com/EsScTSI Here in video you can see

  1. Map rotates because as declared in didLoad method
  2. When tapping button camera animates to the North and instantly continues 'following' the device direction
  3. After panning the map 'following' stops, and in this case after tapping the button camera stays facing to the north
  4. After tapping button again map starts rotating as it should

The problem is that i cannot find a way to 'stop the binding' of map rotation to device rotation


Solution

  • Well, just found the way to do this, and here's the code and it works like a charm

        if showsToNorth {
            mapView.viewport.transition(to: mapView.viewport.makeFollowPuckViewportState(options: .init(bearing: .constant(0),
                                                                                                        pitch: 0)))
        } else {
            mapView.viewport.transition(to: mapView.viewport.makeFollowPuckViewportState(options: .init(pitch: 0)))
        }
    

    Turns out there was a correct and easier way to do so.

    Here based on the showsToNorth variable map transitions between showing to the north by setting bearing value to constant 0 degrees and binding to users direction.

    Also want to make a notice. No matter the puck properties showBearing, puckBearing: .course, puckBearing: .heading or puckBearingEnabled vales the map rotation works, I will consider this as a feature rather than a bug, because it can easily be handled.