Объекты карты
MapKit SDK позволяет отображать на карте объекты. Все объекты карты настраиваемые: вы можете создавать уникальные пользовательские сценарии с учетом потребностей разработчиков.
Метки
Добавьте пользовательские метки изображения на карту с помощью метода YMKMapObjectCollection.addPlacemark() из поля YMKMap.mapObjects.
Метод принимает YMKPoint
с координатами для метки и экземпляр UIImage
.
let placemark = map.mapObjects.addPlacemark()
placemark.geometry = YMKPoint(latitude: 59.935493, longitude: 30.327392)
placemark.setIconWith(UIImage(named: "icon_dollar")!)
С помощью приведенного выше кода создается экземпляр класса YMKPlacemarkMapObject, который расширяет интерфейс YMKMapObject.
Интерфейс YMKMapObject представляет каждый видимый объект на карте. Существует несколько способов настройки объектов карты: изменение видимости, разрешение перетаскивания, изменение z-индекса, настройка обработчика событий касания или перетаскивания и многое другое.
Подробнее об этом можно почитать в разделе YMKMapObject.
Настройка текста
Вы можете создавать текстовые надписи рядом с метками. Для этого используйте метод YMKPlacemarkMapObject.setTextWithText(_:).
Чтобы изменить внешний вид меток, включая их размер, цвет и положение текста относительно значка, используйте метод YMKTextStyle.
placemark.setTextWithText(
"Special place",
style: {
let textStyle = YMKTextStyle()
textStyle.size = 10.0
textStyle.placement = .right
textStyle.offset = 5.0
return textStyle
}()
)
Стили значков
Вы можете настроить представление значков меток с помощью класса YMKIconStyle. Он позволяет изменять положение привязки, размер, тип поворота, z-индекс, кликабельные области, видимость и плоскость по отношению к карте.
let iconStyle = YMKIconStyle()
iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 0.5))
iconStyle.scale = 0.6
let placemark = map.mapObjects.addPlacemark()
placemark.geometry = point
placemark.setIconWith(image, style: iconStyle)
Составные значки
Объедините несколько значков, чтобы создать составной.
-
Создайте значок по умолчанию с помощью YMKMapObjectCollection.addPlacemark().
-
Используйте YMKPlacemarkMapObject.useCompositeIcon(), чтобы создать составной значок.
-
Используйте YMKCompositeIcon.setIconWithName(_:image:style:), чтобы добавить новый значок к составному значку.
Полный пример кода для создания составного значка:
let placemark = map.mapObjects.addPlacemark()
placemark.geometry = GeometryProvider.compositeIconPoint
placemark.addTapListener(with: singlePlacemarkTapListener)
placemark.setTextWithText(
"Special place",
style: {
let textStyle = YMKTextStyle()
textStyle.size = 10.0
textStyle.placement = .right
textStyle.offset = 5.0
return textStyle
}()
)
let compositeIcon = placemark.useCompositeIcon()
compositeIcon.setIconWithName(
"pin",
image: UIImage(named: "icon_dollar")!,
style: {
let iconStyle = YMKIconStyle()
iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 1.0))
iconStyle.scale = 0.9
return iconStyle
}()
)
compositeIcon.setIconWithName(
"point",
image: UIImage(named: "icon_circle")!,
style: {
let iconStyle = YMKIconStyle()
iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 0.5))
iconStyle.scale = 0.5
iconStyle.flat = true
return iconStyle
}()
)
Результат:
Анимированные метки
Вы можете создать анимированную метку из анимированного PNG-файла.
-
Создайте метку с помощью YMKMapObjectCollection.addPlacemark().
let animatedPlacemark = pinsCollection.addPlacemark() animatedPlacemark.geometry = GeometryProvider.animatedImagePoint
-
Используйте метод YMKPlacemarkMapObject.useAnimation() для создания объекта анимации. Задать ресурс анимации можно при помощи экземпляра YRTAnimatedImageProvider.
let animatedImageProvider = YRTAnimatedImageProviderFactory.fromFile( Bundle.main.path(forResource: "animation", ofType: "png") ) as! YRTAnimatedImageProvider let animation = animatedPlacemark.useAnimation() animation.setIconWithImage(animatedImageProvider)
-
Запустите анимацию, управляя ею с помощью объекта YMKPlacemarkAnimation.
animation.play()
Коллекции меток
Коллекции меток используются для группировки нескольких меток в новую коллекцию вложенных объектов карты.
-
Чтобы создать коллекцию вложенных объектов карты, используйте метод YMKMapObjectCollection.add().
let pinsCollection = map.mapObjects.add()
-
Теперь вы можете использовать новую коллекцию
pinsCollection
для отображения меток и других объектов карты.GeometryProvider.placemarkPoints.enumerated().forEach { pair in let point = pair.element let image = UIImage(named: "icon_dollar")! let placemark = map.mapObjects.addPlacemark() placemark.geometry = point placemark.setIconWith(image) placemark.isDraggable = true }
Как это выглядит после добавления меток в коллекцию новых объектов карты:
После создания коллекции pinCollection
вы можете добавить в нее пины так же, как и для объектов YMKMap.mapObjects, поскольку они имеют тот же тип YMKMapObjectCollection.
Примечание
Интерфейс YMKMapObjectCollection расширяет YMKMapObject, поэтому допускается создавать вложенные коллекции и добавлять их в другие.
Все методы, имеющие интерфейс YMKMapObject, также доступны в YMKMapObjectCollection.
Вы можете итерироваться по элементам YMKMapObjectCollection, используя метод YMKBaseMapObjectCollection.traverse(with:).
Геометрии
MapKit SDK позволяет рисовать на карте примитивные геометрические объекты, такие как полигоны, полилинии и круги. Все они настраиваемые и реализуют интерфейс YMKMapObject.
Полигоны
Используйте полигон, когда вам нужно отобразить область карты для пользователей.
-
Начните с создания экземпляра YMKPolygon.
static let polygon: YMKPolygon = { var points = [ YMKPoint(latitude: 59.935493, longitude: 30.327392), YMKPoint(latitude: 59.938185, longitude: 30.32808), YMKPoint(latitude: 59.937376, longitude: 30.33621), YMKPoint(latitude: 59.934517, longitude: 30.335059) ] points.append(points[0]) let outerRing = YMKLinearRing(points: points) return YMKPolygon(outerRing: outerRing, innerRings: []) }()
-
Используйте метод YMKMapObjectCollection.addPolygon(with:) для создания полигонального объекта карты.
polygonMapObject = collection.addPolygon(with: GeometryProvider.polygon)
После завершения сборки вы увидите полигон в стиле по умолчанию:
-
Задайте внутренние точки при создании полигона, чтобы исключить часть внутри него.
static let polygon: YMKPolygon = { var points = [ YMKPoint(latitude: 59.935493, longitude: 30.327392), YMKPoint(latitude: 59.938185, longitude: 30.32808), YMKPoint(latitude: 59.937376, longitude: 30.33621), YMKPoint(latitude: 59.934517, longitude: 30.335059) ] points.append(points[0]) let outerRing = YMKLinearRing(points: points) var innerPoints = [ YMKPoint(latitude: 59.937487, longitude: 30.330034), YMKPoint(latitude: 59.936688, longitude: 30.33127), YMKPoint(latitude: 59.937116, longitude: 30.33328), YMKPoint(latitude: 59.937704, longitude: 30.331842) ] innerPoints.append(innerPoints[0]) let innerRing = YMKLinearRing(points: innerPoints) return YMKPolygon(outerRing: outerRing, innerRings: [innerRing]) }()
Полигон с внутренними точками:
-
Измените цвет заливки и обводки по умолчанию, используя созданный экземпляр YMKPolygonMapObject.
polygonMapObject.strokeWidth = 1.5 polygonMapObject.strokeColor = Palette.olive polygonMapObject.fillColor = Palette.oliveTransparent
Подробнее про настройку полигонов см. в разделе YMKPolygonMapObject.
Полилинии
Полилинии часто используются для отображения маршрутов и траекторий.
-
Создайте экземпляр YMKPolyline с искомой геометрией и добавьте на карту объект полилинейной карты с помощью метода YMKMapObjectCollection.addPolyline(with:).
let polyline: YMKPolyline = { YMKPolyline( points: [ YMKPoint(latitude: 59.935493, longitude: 30.327392), YMKPoint(latitude: 59.938185, longitude: 30.32808), YMKPoint(latitude: 59.937376, longitude: 30.33621), YMKPoint(latitude: 59.934517, longitude: 30.335059) ] ) }() let polylineMapObject = collection.addPolyline(with: polyline)
-
Настройте стили полилиний, используя переменную YMKPolylineMapObject.
polylineMapObject.strokeWidth = 5.0 polylineMapObject.setStrokeColorWith(.gray) polylineMapObject.outlineWidth = 1.0 polylineMapObject.outlineColor = .black
Результат после добавления полилинии на карту:
Подробнее об этом можно почитать в разделе YMKPolylineMapObject.
Круги
Круги используются для отображения круглых областей.
-
Создайте экземпляр YMKCircle с искомой геометрией: центральной точкой и радиусом в метрах.
var circleWithRandomRadius: YMKCircle { YMKCircle(center: YMKPoint(latitude: 59.935493, longitude: 30.327392), radius: 400.0) }
-
С помощью метода YMKMapObjectCollection.addCircle(with:stroke:strokeWidth:fill:) добавьте на карту объект круга.
let circle = pinsCollection.addCircle(with: GeometryProvider.circleWithRandomRadius) circle.strokeColor = Palette.red circle.strokeWidth = 2.0 circle.fillColor = Palette.redTransparent
Результат после добавления круга на карту:
Подробнее о том, как настроить круговой объект карты, можно почитать в разделе YMKCircleMapObject.
Кластеры
Кластеризованные коллекции используются для отображения нескольких меток.
-
Начните с создания YMKClusterListener с одним методом YMKClusterListener.onClusterAdded(with:), который управляет внешним видом кластера на карте.
final class ClusterListener: NSObject, YMKClusterListener, YMKClusterTapListener { // MARK: - Constructor init(controller: UIViewController) { self.controller = controller } // MARK: - Public methods func onClusterTap(with cluster: YMKCluster) -> Bool { AlertPresenter.present( from: controller, with: "Tapped the cluster", message: "With \(cluster.size) items" ) return true } func onClusterAdded(with cluster: YMKCluster) { let placemarks = cluster.placemarks.compactMap { $0.userData as? PlacemarkUserData } cluster.appearance.setViewWithView(YRTViewProvider(uiView: ClusterView(placemarks: placemarks))) cluster.addClusterTapListener(with: self) } // MARK: - Private properties private weak var controller: UIViewController? }
Свойство YMKCluster.appearance возвращает объект YMKPlacemarkMapObject. В нашем примере мы используем метод YMKPlacemarkMapObject.setViewWithView(_:), чтобы изменить внешний вид кластера.
ClusterView
— это определяемый пользователем класс. Чтобы узнать, как он реализован, посмотрите код в нашем репозитории на GitHub. -
Создайте новую вложенную коллекцию с помощью метода YMKMapObjectCollection.addClusterizedPlacemarkCollection(with:).
clusterizedCollection = collection.addClusterizedPlacemarkCollection(with: clusterListener)
-
Добавьте несколько меток в новый
clusterizedCollection
.GeometryProvider.clusterizedPoints.enumerated().forEach { pair in let index = pair.offset let point = pair.element let type = PlacemarkType.random let image = type.image let iconStyle = YMKIconStyle() iconStyle.anchor = NSValue(cgPoint: CGPoint(x: 0.5, y: 0.5)) iconStyle.scale = 0.6 let placemark = clusterizedCollection.addPlacemark() placemark.geometry = point placemark.setIconWith(image, style: iconStyle) placemark.isDraggable = true placemark.setDragListenerWith(mapObjectDragListener) placemark.userData = PlacemarkUserData(name: "Data_\(index)", type: type) placemark.addTapListener(with: mapObjectTapListener) }
-
Вызовите метод YMKClusterizedPlacemarkCollection.clusterPlacemarks(withClusterRadius:minZoom:). Он принимает два аргумента:
clusterRadius
— минимальное расстояние в единицах между объектами, которые остаются в отдельных кластерах.minZoom
— минимальный уровень масштабирования, отображающий кластеры.
clusterizedCollection.clusterPlacemarks(withClusterRadius: Const.clusterRadius, minZoom: Const.clusterMinZoom)
Важно
YMKClusterizedPlacemarkCollection.clusterPlacemarks(withClusterRadius:minZoom:) следует вызывать явно каждый раз, когда метки добавляются в кластеризованные коллекции или удаляются из них.
Иначе кластеризованные метки не будут повторно отображаться.
Кластеризованные метки с разным масштабом:
Исходный код
Полные примеры кода из руководства смотрите в приложении MapObjects
в нашем GitHub репозитории.