Skip to main content

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.

iOS Examples App Available

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.

Custom3DPuckExample.swift
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)
}
}
Was this example helpful?