MapsSDK - библиотека, позволяющая использовать картографические данные и геосервисы VK в ваших iOS-приложениях.
Для использования MapsSDK вам необходим API-ключ. Подробнее о том, как его получить вы можете прочитать по этой ссылке
С помощью MapsSDK вы можете добавить в собственное приложение карты на основе геоданных VK. MapsSDK максимально упрощает процесс интеграции и отображения карт и берет на себя обработку жестов пользователя. Так же у вас есть возможность добавить на карту произвольные маркеры, полилинии и другие графические элементы, которые позволят пользователю получить дополнительную информацию и успешно взаимодействовать с картой.
MapsSDK может быть интегрирован в приложения с поддержкой iOS 12.4 и более поздних версий.
Начиная с iPadOS 13 у пользователей появилась возможность использовать многооконный режим. MapsSDK не был оптимизирован для работы в это режиме и его использование может привести к неопределенному поведению.
Вы можете с легкостью интегрировать MapsSDK в приложения, основанные на фреймворках UIKit или SwiftUI. Подробнее об этом будет рассказано далее.
Для подключения MapsSDK вы можете использовать Swift Package Manager.
MapsSDK доступен в виде пакета для Swift Package Manager (SPM). SPM - это менеджер зависимостей, он интегрирован в систему сборки Swift и автоматизирует процесс загрузки, компиляции и линковки зависимостей.
Для установки пакета выполните следующие действия:
File -> Add Packages
.Так же вы можете выбрать файл проекта на панели
Project Navigator
, перейти к настройкам проекта, далее выбрать вкладкуPackage Dependencies
и нажать кнопкуAdd Package Dependency
.
https://github.com/maps-mailru/maps-sdk-ios
.Импортируйте MapsSDK
в файл, где вы будете использовать карту.
import MapsSDK
Для начала работы необходимо:
MapView
.MapView
let mapView = MapView()
MapView
Для конфигурации необходимо создать объект типа MapViewConfig
, содержащий следующие сведения:
Далее конфигурацию необходимо передать в объект карты.
let mapConfig = MapViewConfig(
apiKey: "##YOUR_API_KEY##",
center: Coordinates(lng: 33, lat: 55),
zoomLevel: 11,
style: .automatic
mapView.setup(mapConfig)
)
Уровень зума (zoomLevel
) может иметь значение от 0 (самый отдаленный) до 22 (самый приближенный).
Стиль тайлов (style
) может принять одно из следующих значений:
.automatic
- автоматический выбор стиля в зависимости от текущих настроек карты;.main
- базовый стиль;.light
- светлый стиль;.dark
- темный стиль;.navMain
- базовый стиль для навигации с акцентом на дороги;.navDark
- темный стиль для навигации с акцентом на дороги.Делегат должен реализовывать требования протокола MapViewDelegate
. Он будет использоваться для обработки оповещений от карты о различных событиях, таких как:
и другие.
Все доступные события будут рассмотрены далее в руководстве.
override func viewDidLoad() {
let mapView = MapView()
let mapConfig = MapViewConfig(
apiKey: "##YOUR_API_KEY##",
center: Coordinates(lng: 33, lat: 55),
zoomLevel: 11,
style: .automatic
)
mapView.setup(mapConfig)
mapView.delegate = self
view.addSubview(mapView)
}
Метод MapView.setCurrentLocation
устанавливает:
bearing
);accuracy
);zoom
). Данный аргумент является опциональным.// без установки зума
mapView.setCurrentLocation(Coordinates(lng: 33, lat: 55), bearing: 0, accuracy: 0)
// с установкой зума
mapView.setCurrentLocation(Coordinates(lng: 33, lat: 55), bearing: 0, accuracy: 0, zoom: 10)
Уровень зума (zoom
) может изменяться в диапазоне от 0 (самый отдаленный) до 22 (самый приближенный).
Для управления камерой используется метод flyTo
, а так же setBearing
и setZoom
.
flyTo
Позволяет изменить координаты центра карты. За анимацию изменений отвечает аргумент animated
, а за длительность - duration
.
// без указания длительности анимации
mapView.flyTo(Coordinates(lng: 33, lat: 55), animated: true)
// с указание длительности анимации
mapView.flyTo(Coordinates(lng: 33, lat: 55), animated: true, duration: 2)
Дополнительно вы можете передать аргумент options
типа MapCameraOptions
, определяющий:
bearing
) - угол поворота карты;zoom
) - уровень зума карты;padding
) - отступы с каждой стороны окна для смещения центральной точки вьюпорта;curve
) - коэфициент для определения траектории движения камеры;resetFollowMode
) - см. раздел "Установка режимов следования".Каждый из перечисленных параметров является опциональным.
let options = MapCameraOptions(bearing: 180,
zoom: 12,
padding: UIEdgeInsets.init(top: 20, left: 20, bottom: 150, right: 20),
curve: 1.42,
resetFollowMode: false)
mapView.flyTo(Coordinates(lng: 33, lat: 55), options: options, animated: true)
setBearing
Устанавливает направление карты, является облегченной версией метода flyTo
.
mapView.setBearing(90, animated: true)
setZoom
Устанавливает зум карты, является облегченной версией метода flyTo
.
mapView.setZoom(11, animated: true)
mapView.setMinZoom(10, maxZoom: 15)
mapView.isZoomButtonsHidden = true
mapView.isCompassHidden = true
mapView.isMyLocationButtonHidden = true
mapView.isDragPanEnabled = true
mapView.isZoomRotateEnabled = true
mapView.mode = .followLocation
mapView.fitBounds(northWest: coords1, southEast: coords2, animated: true)
По умолчанию логотип отображается в нижнем правом углу карты и учитывает safeArea
.
mapView.logoAlignment = .bottomRight
mapView.logoIgnoresSafeArea = false
mapView.logoInsets = .zero
Маркеры - это активные графические элементы, отображаемые на карте.
Для создания маркеров используется структура Marker
. В инициализатор передаются уникальный идентификатор маркера, координату и картинку, а также, опционально, выравнивание.
let marker1 = Marker(id: "marker_id_1",
coords: Coordinates(lng: 33, lat: 55),
pin: .electricPin)
let marker2 = Marker(id: "marker_id_2",
coords: Coordinates(lng: 33, lat: 55),
pin: .electricInfo,
alignment: .bottomLeft)
В данном случае передаются картинки из предустановленного в SDK набора изображений. При необходимости вы можете передать собственную.
let markerImage = UIImage(...)
let marker3 = Marker(id: "marker_id_3",
coords: Coordinates(lng: 33, lat: 55),
pin: .custom(markerImage),
alignment: .center)
По умолчанию выравнивание маркера имеет значение .center
, то есть центр маркера совмещается с переданными координатами. Но у вас есть возможность гибко управлять этим параметров, выбирая одно из множества доступных значений, или передав произвольное смещение.
// Выравнивание по центру нижней грани
let marker4 = Marker(id: "marker_id_4",
coords: Coordinates(lng: 33, lat: 55),
pin: .electricPhoto,
alignment: .bottom)
// Выравнивание со смещением
// Смещение высчитывается относительно центра маркера
let marker5 = Marker(id: "marker_id_5",
coords: Coordinates(lng: 33, lat: 55),
pin: .electricStar,
alignment: .center(offsetByX: 10, byY: -10)
Для размещения маркера на карте используется метод addMarker(_: Marker)
.
// Размещение маркеров по одному
mapView.addMarker(marker1)
mapView.addMarker(marker2)
// Размещение нескольких маркеров
mapView.addMarkers([marker1, marker2])
Для удаления маркера используется метод removeMarker(id: String)
, который принимает уникальный идентификатор маркера.
mapView.removeMarker(id: "marker_id_1")
Так же есть возможность удалить все маркеры сразу.
mapView.removeAllMarkers()
Для отслеживания события нажатия на маркер необходимо использовать метод MapViewDelegate.mapView(_: MapView, didSelectMarkerID: String)
делегата объекта карты, принимающий ID выбранного маркера.
func MapDelegate: MapViewDelegate{
func mapView(_ map: MapView, didSelectMarkerID markerID: String) {
// ...
// markerID - ID выбранного маркера
// ...
}
}
Дополнительно при нажатии на любой маркер вызывается метод MapViewDelegate.mapView(_: MapView, didReceiveEvent: MapEvent)
делегата. В данном случае свойство didReceiveEvent.type
меет значение .clickOnMarker
.
func MapDelegate: MapViewDelegate{
func mapView(_ map: MapView, didReceiveEvent event: String) {
// ...
// Для события нажатия на маркер
// event.type = .clickOnMarker
// ...
}
}
Маркеры можно объединять в кластеры. Кластеризация создает новый источник данных на карте. Вы можете указать радиус кластеров в метрах, цвет текста и фона.
let markers: [Marker] = ...
mapView.addCluster(markers, id: "clusterId", radius: 50, textColor: .white, backgroundColor: .blue)
Удаление кластеров происходит с указанием идентификатора кластера.
mapView.removeCluster(id: "clusterId")
Для показа попапа на карте, нужно указать идентификатор маркера, для которого он будет отображен, и текст внутри попапа.
mapView.displayPopup(markerId: "marker_id_1", content: "Hello world")
Для скрытия попапа, нужно указать идентификатор маркера.
mapView.hidePopup(markerId: "marker_id_1")
Для этого необходимо реализовать метод mapView(_:, didSelectMarkerID:)
делегата MapViewDelegate
.
extension MyController: MapViewDelegate {
func mapView(_ mapView: MapView, didSelectMarkerID id: String) {
mapView.displayPopup(id: id, content: "Hello world")
}
}
Карта поддерживает смену стилей. Стиль .automatic
означает, что карта будет автоматически менять светлый и темный стили в зависимости от настройки системной темы интерфейса.
mapView.changeStyle(.automatic)
mapView.changeStyle(.dark)
Карта поддерживает отрисовку полигонов и линий из GeoJSON источника.
let sourceData = Data(...)
let source = MapDataSource(id: "sourceID", type: .geoJSON(sourceData))
mapView.addSource(source)
let fillLayer = MapLayer(
id: "fillLayer",
sourceID: "sourceID",
paint: FillPaintProperties(fillColor: .iuColor(.green), fillOpacity: .value(0.3))
)
let strokeLayer = MapLayer(
id: "strokeLayer",
sourceID: "sourceID",
paint: LinePaintProperties()
)
mapView.addLayer(fillLayer)
mapView.addLayer(strokeLayer)
Значение цвета и прозрачности можно задать в самом источнике. В таком случае используйте .source("field"), где "field" - имя поля в properties источника, откуда брать значение.
Удалить источники и слои можно с указанием их идентификаторов.
mapView.removeLayer("fillLayer")
mapView.removeLayer("strokeLayer")
mapView.removeSource("sourceID")
Поддерживается отрисовка маршрутов в формате кодированной строки сервиса построения маршрутов.
let routeSource = MapDataSource(id: "routeSourceID", type: .encodedString(encodedRoute))
mapView.addSource(routeSource)
let routeLayer = MapLayer(
id: "routeLineLayer",
sourceID: "routeSourceID",
paint: LinePaintProperties(lineColor: .iuColor(.red), lineWidth: 2)
)
mapView.addLayer(routeLayer)
Поддерживается отрисовка кругов. Поскольку GeoJSON не поддерживает круги, они симулируются полигоном с заданным количеством сторон.
mapView.addCircleSource(center: coords, radius: 500, steps: 32, id: sourceID)
Карта может показывать пробки на дорогах и уровни высот (изолинии). Для включения воспользуйтесь методом setLayoutVisible
.
mapView.setLayoutVisible(true, layout: .traffic)
mapView.setLayoutVisible(true, layout: .isolines)
mapView.setLayoutVisible(true, layout: .isolinesLabel)
Для обработки ошибок используется метод mapView(_:, didFailWithError:)
делегата MapViewDelegate
.
extension MyController: MapViewDelegate {
func mapView(_ mapView: MapView, didFailWithError error: Error) {
print("Did fail with error: \(error.localizedDescription)")
}
}
Geocoder - компонент MapsSDK для прямого и обратного геокодирования. Для инициализации необходим API key.
let geocoder = Geocoder(apiKey: "your apiKey")
geocoder.geocode(
query: "Ленинградский проспект 39с79",
lang: "ru",
location: Coordinates(lng: 37.537892, lat: 55.796926)
) { result in
switch result {
case let .success(response):
print(response)
case let .failure(error):
print(error.localizedDescription)
}
Для использования карты в SwiftUI есть компонент Map
.
import SwiftUI
import MapsSDK
class StateObject: ObservableObject {
let mapConfig = MapViewConfig(
apiKey: apiKey,
center: Coordinates(lng: 37.537892, lat: 55.796926)
zoomLevel: 15,
style: .automatic
)
let mapView = MapView()
}
extension StateObject: MapViewDelegate {
// методы делегата
}
struct ContentView: View {
@StateObject private var state = StateObject()
var body: some View {
Map(
config: state.mapConfig,
view: state.mapView,
delegate: state
)
}
}
link |
Stars: 2 |
Last commit: 2 weeks ago |
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics