Use a 3D model to show the user's location
This example demonstrates a custom 3D puck implementation using the Mapbox Maps SDK for iOS. The code sets up a MapView
with a specific initial camera view and listens for the style to load before configuring the 3D puck. The 3D puck is customized with a 3D model sourced from a gltf
asset (in this case, "sportcar.glb") and additional settings including the model scale and opacity. The puck is then configured to display on the map with bearing information and bearing updates enabled. Whenever there is a change in the user's location, the camera smoothly adjusts to focus on the new location with a specific zoom, bearing, and pitch. The implementation utilizes classes such as CameraOptions
, Model
, and Puck3DConfiguration
provided by the SDK.
This example code is part of the Maps SDK for iOS Examples App, a working iOS project available on Github. iOS developers are encouraged to run the examples app locally to interact with this example in an emulator and explore other features of the Maps SDK.
See our Run the Maps SDK for iOS Examples App tutorial for step-by-step instructions.
import UIKit
import MapboxMaps
final class ViewController: UIViewController {
private var cancelables = Set<AnyCancelable>()
private var mapView: MapView!
override func viewDidLoad() {
super.viewDidLoad()
let cameraOptions = CameraOptions(center: CLLocationCoordinate2D(latitude: 37.26301831966747, longitude: -121.97647612483807), zoom: 15, pitch: 55)
mapView = MapView(frame: view.bounds, mapInitOptions: MapInitOptions(cameraOptions: cameraOptions))
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(mapView)
mapView.mapboxMap.onStyleLoaded.observeNext { _ in
self.setupExample()
}.store(in: &cancelables)
}
private func setupExample() {
// Fetch the `gltf` asset
let uri = Bundle.main.url(forResource: "sportcar", withExtension: "glb")
// Instantiate the model
let myModel = Model(uri: uri, orientation: [0, 0, 180])
let configuration = Puck3DConfiguration(
model: myModel,
modelScale: .constant([10, 10, 10]),
modelOpacity: .constant(0.5),
layerPosition: .default
)
mapView.location.options.puckType = .puck3D(configuration)
mapView.location.options.puckBearing = .course
mapView.location.options.puckBearingEnabled = true
mapView.location.onLocationChange.observeNext { [weak mapView] newLocation in
guard let location = newLocation.last, let mapView else { return }
mapView.camera.ease(
to: CameraOptions(
center: location.coordinate,
zoom: 15,
bearing: 0,
pitch: 55),
duration: 1,
curve: .linear,
completion: nil)
}.store(in: &cancelables)
}
}