Карта
Создание карты
Чтобы создать карту, добавьте MapWidget в ваше дерево:
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
class SimpleMapScreen extends StatelessWidget {
const SimpleMapScreen({super.key});
@override
Widget build(BuildContext context) {
final sdkContext = sdk.DGis.initialize();
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: sdk.MapWidget(
sdkContext: sdkContext,
mapOptions: sdk.MapOptions(),
),
);
}
}
Основным объектом для управления картой является MapWidgetController. Внутри MapWidget
он будет приватным, поэтому для получения доступа к нему рекомендуется создать его вручную и передать в MapWidget
параметром:
class SimpleMapScreen extends StatelessWidget {
const SimpleMapScreen({super.key});
@override
Widget build(BuildContext context) {
final sdk.Context sdkContext = sdk.DGis.initialize();
final sdk.MapWidgetController mapWidgetController = sdk.MapWidgetController();
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: sdk.MapWidget(
sdkContext: sdkContext,
mapOptions: sdk.MapOptions(),
controller: mapWidgetController,
),
);
}
}
Объект карты (Map) можно получить, вызвав метод getMapAsync(). Этот метод работает асинхронно, поэтому его безопасно вызывать в любой момент жизненного цикла, начиная с initState()
.
Другие действия с картой можно выполнить внутри метода getMapAsync()
, т. к. это первый момент, когда карта становится доступна. Все операции с картой, которые описаны в этом разделе далее, подразумевают, что карта уже проинициализирована, а все вызовы происходят внутри метода.
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
sdk.Map? sdkMap = null;
@override
initState() {
super.initState();
mapWidgetController.getMapAsync((map) {
sdkMap = map;
});
}
Источники данных для карты
В некоторых случаях для добавления объектов на карту нужно создать специальный объект: источник данных. Источники данных выступают в роли менеджеров объектов: вместо добавления объектов на карту напрямую, на карту добавляется источник данных, и вся последующая работа с объектами происходит через него.
Источники данных бывают разных типов: движущиеся маркеры, маршруты с отображением текущей загруженности дорог, произвольные геометрические фигуры и т. д. Для каждого типа данных существует свой класс.
В общем случае работа с источниками данных выглядит следующим образом:
// Создание источника данных
final sdk.MyLocationMapObjectSource locationSource = sdk.MyLocationMapObjectSource(sdkContext);
// Добавление источника данных на карту
map?.addSource(locationSource);
Чтобы удалить созданный источник данных и все связанные с ним объекты, нужно вызвать метод карты removeSource():
map?.removeSource(locationSource);
Список активных источников данных можно получить, используя свойство map.sources.
Офлайн-режим
Чтобы настроить карту для работы в офлайн-режиме:
-
Выполните подготовительные шаги, чтобы карта могла работать с предзагруженными данными.
-
Добавьте источник данных для карты. Для этого в функции createDgisSource() установите параметру
workingMode
одно из следующих значений:OFFLINE
— чтобы всегда использовать только предварительно загруженные данные.HYBRID_ONLINE_FIRST
— чтобы преимущественно использовать онлайн-данные с серверов 2ГИС. Предзагруженные данные используются, только когда они совпадают с онлайн-данными или когда данные с серверов получить невозможно.HYBRID_OFFLINE_FIRST
— чтобы преимущественно использовать предзагруженные данные. Онлайн-данные с серверов 2ГИС используются, только когда отсутствуют предзагруженные данные.
final dgisSource = sdk.DgisSource.createDgisSource(
sdkContext,
sdk.DgisSourceWorkingMode.hybridOfflineFirst,
); -
При создании карты укажите созданный источник в MapOptions:
final mapOptions = sdk.MapOptions(sources: [dgisSource]);
// Теперь MapOptions можно передать в MapWidget
sdk.MapWidget(
sdkContext: sdkContext,
mapOptions: mapOptions,
controller: mapWidgetController,
);
Добавление объектов
Для добавления динамических объектов на карту (маркеров, линий, кругов, многоугольников) нужно создать менеджер объектов (MapObjectManager), указав объект карты. При удалении менеджера объектов удаляются все связанные с ним объекты на карте, поэтому его нужно сохранить в activity.
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
final sdk.MapObjectManager mapObjectManager = sdk.MapObjectManager(map)
Для добавления объектов используются методы addObject() и addObjects(). Для каждого динамического объекта можно указать поле userData
, которое будет хранить произвольные данные, связанные с объектом. Настройки объектов можно менять после их создания.
Для удаления объектов используются методы removeObject() и removeObjects(). Чтобы удалить все объекты, можно использовать метод removeAll()
.
MapObjectManager — это контейнер объектов. Пока объекты нужны на карте,
MapObjectManager
необходимо сохранять на уровне класса.
Маркер
Чтобы добавить маркер на карту, нужно создать объект Marker, указав нужные настройки в MarkerOptions, и передать его в вызов addObject()
менеджера объектов.
Единственный обязательный параметр — координаты маркера (position
).
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
final sdk.Marker marker = sdk.Marker(
sdk.MarkerOptions(
position: sdk.GeoPointWithElevation(
latitude: sdk.Latitude(55.752425),
longitude: sdk.Longitude(37.613983),
)
),
);
mapObjectManager.addObject(marker);
Чтобы создать иконку маркера, нужно указать объект Image в качестве параметра icon
. Создать Image
можно с помощью следующих функций:
- loadLottieFromAsset()
- loadLottieFromFile()
- loadPngFromAsset()
- loadPngFromFile()
- loadSVGFromAsset()
- loadSVGFromFile()
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
final sdk.ImageLoader loader = sdk.ImageLoader(_sdkContext);
final sdk.Image icon = loader.loadSVGFromAsset("assets/icons/bridge.svg");
final marker = sdk.Marker(
sdk.MarkerOptions(
position: sdk.GeoPointWithElevation(
latitude: sdk.Latitude(55.752425),
longitude: sdk.Longitude(37.613983),
icon = icon
)
),
);
Чтобы изменить настройки уже созданного маркера, установите новые значения для параметров объекта Marker
: cм. полный список доступных параметров в описании Marker.
// Изменение позиции маркера
marker.position = const sdk.GeoPointWithElevation(
latitude: sdk.Latitude(55.74460317215391),
longitude: sdk.Longitude(37.63435363769531),
);
// Изменение иконки
late sdk.ImageLoader loader;
marker.icon = loader.loadSVGFromAsset("Path to SVG");
// Изменение точки привязки иконки
marker.anchor = const sdk.Anchor(x:0.5, y:0.5);
// Изменение прозрачности иконки
marker.iconOpacity = const sdk.Opacity(0.5);
// Изменение подписи маркера
marker.text = 'Text';
// Изменения стиля подписи
marker.textStyle = sdk.TextStyle();
// Изменение флага перемещаемости маркера
marker.isDraggable = false;
// Изменение целевой ширины маркера
marker.iconWidth = const sdk.LogicalPixel(10);
// Изменение угла поворота маркера на карте относительно направления на север
marker.iconMapDirection = sdk.MapDirection(0.5);
// Изменение флага а нимации для появления маркера
marker.animatedAppearance = true;
Линия
Чтобы нарисовать на карте линию, нужно создать объект Polyline, указав нужные настройки в PolylineOptions, и передать его в вызов addObject()
менеджера объектов.
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
// Координаты вершин ломаной линии
final sdk.GeoPoint point1 = sdk.GeoPoint(latitude: sdk.Latitude(55.7), longitude: sdk.Longitude(37.6));
final sdk.GeoPoint point2 = sdk.GeoPoint(latitude: sdk.Latitude(55.8), longitude: sdk.Longitude(37.7));
final sdk.GeoPoint point3 = sdk.GeoPoint(latitude: sdk.Latitude(55.9), longitude: sdk.Longitude(37.8));
final sdk.GeoPoint geopoints = <sdk.GeoPoint>[point1,point2,point3]
// Создание линии
final sdk.Polyline polyline = sdk.Polyline(
sdk.PolylineOptions(
points: geopoints,
width: sdk.LogicalPixel(2),
),
);
// Добавление линии на карту
mapObjectManager.addObject(polyline);
Чтобы изменить настройки уже созданной линии, установите новые значения для параметров объекта Polyline
: cм. полный список доступных параметров в описании Polyline.
// Изменение координат вершин линии
polyline.points = geopoints;
// Изменение толщины линии
polyline.width = sdk.LogicalPixel(10);
// Изменение цвета линии
polyline.color = sdk.Color(Colors.black.value);
// Изменение стёртой части
polyline.erasedPart = 0.1;
// Изменение параметров пунктирной линии
polyline.dashedPolylineOptions = sdk.DashedPolylineOptions();
// Изменение параметров градиентной линии
polyline.gradientPolylineOptions = sdk.GradientPolylineOptions();
Многоугольник
Чтобы нарисовать на карте многоугольник, нужно создать объект Polygon, указав нужные настройки в PolygonOptions, и передать его в вызов addObject()
менеджера объектов.
Координаты для многоугольника указываются в виде двумерного списка. Первый вложенный список должен содержать координаты основных вершин многоугольника. Остальные вложенные списки не обязательны и могут быть заданы для того, чтобы создать вырез внутри многоугольника (один дополнительный список — один вырез в виде многоугольника).
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
final sdk.GeoPoint point1 = sdk.GeoPoint(latitude: sdk.Latitude(55.7), longitude: sdk.Longitude(37.6));
final sdk.GeoPoint point2 = sdk.GeoPoint(latitude: sdk.Latitude(55.8), longitude: sdk.Longitude(37.7));
final sdk.GeoPoint point3 = sdk.GeoPoint(latitude: sdk.Latitude(55.9), longitude: sdk.Longitude(37.8));
final sdk.GeoPoint countor = <sdk.GeoPoint>[point1,point2,point3];
final sdk.GeoPoint point4 = sdk.GeoPoint(latitude: sdk.Latitude(55.7), longitude: sdk.Longitude(37.6));
final sdk.GeoPoint point5 = sdk.GeoPoint(latitude: sdk.Latitude(55.8), longitude: sdk.Longitude(37.7));
final sdk.GeoPoint point6 = sdk.GeoPoint(latitude: sdk.Latitude(55.9), longitude: sdk.Longitude(37.8));
final sdk.GeoPoint points = <sdk.GeoPoint>[point4,point5,point6];
final sdk.Polygon polygon = sdk.Polygon(
sdk.PolygonOptions(
contours: [countor,points],
strokeWidth: sdk.LogicalPixel(5),
),
);
mapObjectManager.addObject(polygon);
Чтобы изменить настройки уже созданного многоугольника, установите новые значения для параметров объекта Polygon
: cм. полный список доступных параметров в описании Polygon.
// Изменение вершин многоугольника
polygon.contours = [contuor, points];
// Изменение цвета заливки многоугольника
polygon.color = sdk.Color(Colors.black.value);
// Изменение толщины границы многоугольника
polygon.strokeWidth = sdk.LogicalPixel(10);
// Изменение цвета границы многоугольника
polygon.strokeColor = sdk.Color(Colors.black.value);
Окружность
Чтобы нарисовать на карте окружность, нужно создать объект Circle, указав нужные настройки в CircleOptions, и передать её в вызов addObject()
менеджера объектов.
// Настройки окружно сти
final circle = sdk.Circle(
const sdk.CircleOptions(
position: sdk.GeoPoint(latitude: sdk.Latitude(10),longitude: sdk.Longitude(10)),
radius: sdk.Meter(10)
)
);
// Создание и добавление окружности
mapObjectManager.addObject(circle);
Чтобы изменить настройки уже созданной окружности, установите новые значения для параметров объекта Circle
: cм. полный список доступн ых параметров в описании Circle.
// Изменение центра окружности
circle.position = sdk.GeoPoint(latitude: sdk.Latitude(55.752425),longitude: sdk.Longitude(37.613983));
// Изменение радиуса окружности
circle.radius = sdk.Meter(10);
// Изменение цвета заливки окружности
circle.color = sdk.Color(Colors.black.value);
// Изменение толщины границы окружности
circle.strokeWidth = sdk.LogicalPixel(12);
// Изменение цвета границы окружности
circle.strokeColor = sdk.Color(Colors.black.value);
Добавление нескольких объектов
Если на карту необходимо добавить коллекцию объектов, то добавление через метод addObject
в цикле по всей коллекции приведет к потере производительности. Для добавления коллекции объектов нужно сначала подготовить всю коллекцию и добавить её через метод addObjects:
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
// Подготавливаем коллекцию объектов
final List<sdk.Marker> markers = [];
final sdk.MarkerOptions markerOptions = sdk.MarkerOptions(
<params>
);
markers.add(sdk.Marker(markerOptions));
// Добавляем коллекцию объектов на карту
mapObjectManager.addObjects(markers)
Кластеризация
Кластеризация — это визуальная группировка близко расположенных друг к другу объектов (маркеров) в один кластер при уменьшении масштаба карты. Группировка происходит постепенно: чем меньше масштаб карты, тем меньше кластеров. Кластер отображается как маркер с цифрой, соответствующий количеству объектов в кластере.
Чтобы добавить на карту маркеры в режиме кластеризации, создайте менеджер объектов (MapObjectManager) с помощью метода MapObjectManager.withClustering() и укажите следующие свойства:
- Экземпляр карты (
map
). - Минимальное расстояние между маркерами в логических пикселях на уровнях масштабирования, при которых работает кластеризация (
logicalPixel
). - Уровень масштабирования, при котором и выше видны только отдельные маркеры, без кластеров (
maxZoom
). - Уровень масштабирования, при котором и ниже перестают формироваться новые кластеры (
minZoom
). - Пользовательскую реализацию протокола SimpleClusterRenderer, который используется для кастомизации кластеров в MapObjectManager.
import 'package:dgis_mobile_sdk_map/dgis.dart' as sdk;
class SimpleClusterRendererImpl implements sdk.SimpleClusterRenderer {
final sdk.Image image;
int idx = 0;
SimpleClusterRendererImpl({
required this.image,
});
@override
sdk.SimpleClusterOptions renderCluster(sdk.SimpleClusterObject cluster) {
final int objectCount = cluster.objectCount;
final sdk.MapDirection? iconMapDirection =
objectCount < 5 ? const sdk.MapDirection(45) : null;
idx += 1;
const double baseSize = 30.0;
final double sizeMultiplier = 1.0 + (objectCount / 50.0);
final double iconSize = min(baseSize * sizeMultiplier, 100);
return sdk.SimpleClusterOptions(
icon: image,
iconMapDirection: iconMapDirection,
text: objectCount.toString(),
iconWidth: sdk.LogicalPixel(iconSize),
userData: idx,
zIndex: const sdk.ZIndex(1),
);
}
}
clusterRenderer ??= SimpleClusterRendererImpl(
image: loader.loadSVGFromAsset("assets/icons/bridge.svg"),
);
mapObjectManager = sdk.MapObjectManager.withClustering(
map,
const sdk.LogicalPixel(80.0),
const sdk.Zoom(19.0),
const sdk.Zoom(8.0),
clusterRenderer
);
После создания менеджера объектов с кластеризацией вы можете добавлять маркеры обычными способами через addObject()
или addObjects()
.