You can use Marker to render custom SwiftUI View hierarchies as markers on a
3D Map.
Custom view markers let you display rich SwiftUI layouts, interactive controls,
and animations anchored to geographic coordinates.
Add a custom view marker
To add a custom view marker to your
Map, declare
a Marker inside the map content builder, specify its position using a
LatLngAltitude
value, and provide your custom SwiftUI View in the trailing content closure.
If you omit the content closure, Marker renders a default
Pin view.
import GoogleMaps3D
import SwiftUI
struct CustomMarkerExampleView: View {
var body: some View {
Map(mode: .hybrid) {
Marker(
position: LatLngAltitude(
latitude: 40.7484,
longitude: -73.9857,
altitude: 100.0
),
altitudeMode: .relativeToGround
) {
Text("Empire State Building")
.padding(.horizontal, 12)
.padding(.vertical, 6)
.background(Color.white)
.clipShape(Capsule())
}
}
}
}
Customize the default Pin view
Instead of building a completely custom SwiftUI View, you can render a
customized pin by passing a
Pin
initialized with a
Pin.Configuration
to the Marker content closure:
import GoogleMaps3D
import SwiftUI
struct CustomPinMarkerExampleView: View {
var body: some View {
Map(mode: .hybrid) {
Marker(
position: LatLngAltitude(
latitude: 40.7484,
longitude: -73.9857,
altitude: 100.0
),
altitudeMode: .relativeToGround
) {
Pin(
configuration: .init(
backgroundColor: .blue,
borderColor: .white
)
)
}
}
}
}
Handle interactions and animations
Because Marker hosts a SwiftUI View, you can attach standard SwiftUI
gesture modifiers (such as .onTapGesture) and SwiftUI animations directly to
the view inside the Marker content closure.
In addition, Marker conforms to
MapContentAnchorable,
which lets you anchor a
Popover
to the marker using the
popover(isOpen:autoClosedEnabled:autoPanEnabled:style:content:)
modifier:
import GoogleMaps3D
import SwiftUI
struct InteractiveMarkerExampleView: View {
@State private var isPopoverOpen = false
var body: some View {
Map(mode: .hybrid) {
Marker(
position: LatLngAltitude(
latitude: 37.7955,
longitude: -122.3937,
altitude: 0
),
altitudeMode: .relativeToGround
) {
Pin(configuration: .init(backgroundColor: .black) {
Image(systemName: "ferry.fill")
.foregroundStyle(.white)
})
.onTapGesture {
isPopoverOpen.toggle()
}
}
.popover(isOpen: $isPopoverOpen) {
Text("Ferry Building")
}
}
}
}
Configure altitude and collision behavior
You can customize how a Marker is positioned vertically and how it interacts
with overlapping map labels or markers by passing parameters to Marker.init:
- Altitude mode: Pass an
AltitudeModevalue to thealtitudeModeparameter. By default,MarkerusesAltitudeMode.clampToGround. - Collision behavior: Pass a
CollisionBehaviorvalue to thecollisionBehaviorparameter (defaults toCollisionBehavior.required), and usecollisionPriority(Int?) to specify relative priority when optional markers collide (a higher value indicates higher priority).