Как создать маркер с собственным представлением

Вы можете использовать Marker, чтобы отображать пользовательские иерархии SwiftUI View в виде маркеров на трехмерной Map. С помощью маркеров пользовательских представлений можно показывать макеты SwiftUI, интерактивные элементы управления и анимацию, привязанные к географическим координатам.

Как добавить маркер пользовательского представления

Чтобы добавить маркер пользовательского представления в Map, объявите Marker в конструкторе контента карты, укажите его position с помощью значения LatLngAltitude и добавьте пользовательское представление SwiftUI View в замыкание content.

Если вы не укажете замыкание content, Marker отобразит представление Pin по умолчанию.

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())
      }
    }
  }
}

Как настроить представление маркера по умолчанию

Вместо того чтобы создавать полностью настраиваемый объект View SwiftUI, вы можете отрисовать настроенный маркер, передав объект Pin, инициализированный с помощью Pin.Configuration, в замыкание контента Marker:

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
          )
        )
      }
    }
  }
}

Обработка взаимодействий и анимаций

Поскольку Marker содержит View SwiftUI, вы можете прикреплять стандартные модификаторы жестов SwiftUI (например, .onTapGesture) и анимации SwiftUI непосредственно к представлению внутри замыкания контента Marker.

Кроме того, Marker соответствует MapContentAnchorable, что позволяет привязать Popover к маркеру с помощью модификатора popover(isOpen:autoClosedEnabled:autoPanEnabled:style:content:):

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")
      }
    }
  }
}

Настройка высоты и поведения при наложении

Вы можете настроить вертикальное положение Marker и его взаимодействие с перекрывающимися ярлыками или маркерами карты, передав параметры в Marker.init:

  • Режим высоты. Передайте значение AltitudeMode в параметр altitudeMode. По умолчанию Marker использует AltitudeMode.clampToGround.
  • Поведение при наложении. Передайте значение CollisionBehavior в параметр collisionBehavior (по умолчанию используется CollisionBehavior.required) и укажите относительный приоритет для необязательных маркеров, которые накладываются друг на друга, с помощью collisionPriority (Int?). Чем больше значение, тем выше приоритет.