Фигуры

Google Maps API для Android позволяет добавлять на карты в приложении различные фигуры и настраивать их внешний вид.

  • Ломаная линия (Polyline) – это серия соединенных отрезков, из которых можно составить любую фигуру. С их помощью можно отмечать пути и маршруты на карте.
  • Многоугольник (Polygon) – это замкнутая фигура, которую можно использовать, чтобы отметить области на карте.
  • Круг (Circle) – это географически точная проекция круга на земную поверхность.

Внешний вид всех перечисленных фигур можно менять, задавая для их свойств разные значения.

Примеры кода

Руководство по добавлению многоугольников и ломаных линий, обозначающих области и маршруты, содержит пример кода для простого приложения Android.

Кроме того, в репозитории ApiDemos на сайте GitHub есть примеры, где демонстрируется использование фигур и их функций:

  • CircleDemoActivity (Java/Kotlin): круг.
  • PolygonDemoActivity (Java/Kotlin): многоугольник.
  • PolylineDemoActivity (Java/Kotlin): ломаная линия.

Ломаные линии

Класс Polyline определяет набор соединенных друг с другом сегментов на карте. Объект Polyline содержит множество точек LatLng и формирует набор отрезков, соединяющих эти точки в заданной последовательности.

В этом видео рассказывается, как реализовать в приложении прорисовку маршрута с помощью ломаных линий.

Чтобы нарисовать ломаную линию, сначала создайте объект PolylineOptions и добавьте в него точки (т. е. объекты LatLng, указывающие точки на земной поверхности). Точки соединяются прямыми линиями в том порядке, в каком они были добавлены в объект PolylineOptions. Чтобы добавить точку в объект PolylineOptions, вызовите метод PolylineOptions.add(). Обратите внимание, что этот метод принимает переменное число параметров, поэтому вы можете добавить несколько точек одновременно. Вы также можете вызвать метод PolylineOptions.addAll(Iterable<LatLng>), если точки уже содержатся в списке.

Чтобы добавить на карту ломаную линию, вызовите метод GoogleMap.addPolyline(PolylineOptions). Он возвращает объект Polyline, с помощью которого можно затем менять внешний вид линии.

В следующем фрагменте кода показано, как добавить на карту прямоугольник.

Java

// Instantiates a new Polyline object and adds points to define a rectangle
PolylineOptions polylineOptions = new PolylineOptions()
    .add(new LatLng(37.35, -122.0))
    .add(new LatLng(37.45, -122.0))  // North of the previous point, but at the same longitude
    .add(new LatLng(37.45, -122.2))  // Same latitude, and 30km to the west
    .add(new LatLng(37.35, -122.2))  // Same longitude, and 16km to the south
    .add(new LatLng(37.35, -122.0)); // Closes the polyline.

// Get back the mutable Polyline
Polyline polyline = map.addPolyline(polylineOptions);
      

Kotlin

// Instantiates a new Polyline object and adds points to define a rectangle
val polylineOptions = PolylineOptions()
    .add(LatLng(37.35, -122.0))
    .add(LatLng(37.45, -122.0)) // North of the previous point, but at the same longitude
    .add(LatLng(37.45, -122.2)) // Same latitude, and 30km to the west
    .add(LatLng(37.35, -122.2)) // Same longitude, and 16km to the south
    .add(LatLng(37.35, -122.0)) // Closes the polyline.

// Get back the mutable Polyline
val polyline = map.addPolyline(polylineOptions)
      

Чтобы изменить форму ломаной линии после ее добавления, вызовите метод Polyline.setPoints() и укажите другой список точек.

Затем можно изменить внешний вид ломаной линии (как до ее добавления на карту, так и после). Подробнее…

События ломаных линий

По умолчанию ломаные линии не реагируют на клики. Чтобы включить или отключить кликабельность, необходимо вызвать метод Polyline.setClickable(boolean).

С помощью OnPolylineClickListener можно прослушивать события кликов по кликабельной ломаной линии. Чтобы добавить прослушиватель на карту, вызовите метод GoogleMap.setOnPolylineClickListener(OnPolylineClickListener). Когда пользователь нажмет на ломаную линию, вы получите обратный вызов onPolylineClick(Polyline).

Многоугольники

Объекты Polygon сходны с объектами Polyline тем, что они состоят из последовательности координат в заданном порядке. Многоугольники отличаются тем, что являются замкнутыми фигурами и могут иметь заливку.

Добавить на карту многоугольник (Polygon) можно тем же способом, что и ломаную линию (Polyline). Сначала создайте объект PolygonOptions и добавьте в него точки, формирующие контур многоугольника. Затем добавьте многоугольник на карту, вызвав метод GoogleMap.addPolygon(PolygonOptions), возвращающий объект Polygon.

Ниже показан код, добавляющий на карту прямоугольник. Обратите внимание, что цвет заливки не определен, а по умолчанию она прозрачна. Поэтому внешне этот многоугольник ничем не отличается от ломаной линии из предыдущего примера.

Java

// Instantiates a new Polygon object and adds points to define a rectangle
PolygonOptions polygonOptions = new PolygonOptions()
    .add(new LatLng(37.35, -122.0),
        new LatLng(37.45, -122.0),
        new LatLng(37.45, -122.2),
        new LatLng(37.35, -122.2),
        new LatLng(37.35, -122.0));

// Get back the mutable Polygon
Polygon polygon = map.addPolygon(polygonOptions);
      

Kotlin

// Instantiates a new Polygon object and adds points to define a rectangle
val rectOptions = PolygonOptions()
    .add(
        LatLng(37.35, -122.0),
        LatLng(37.45, -122.0),
        LatLng(37.45, -122.2),
        LatLng(37.35, -122.2),
        LatLng(37.35, -122.0)
    )

// Get back the mutable Polygon
val polygon = map.addPolygon(rectOptions)
      

Чтобы изменить форму многоугольника после его добавления, вызовите метод Polygon.setPoints() и укажите новую последовательность точек контура.

Внешний вид многоугольника можно изменить как до его добавления на карту, так и после. Подробнее…

Автозавершение многоугольников

Многоугольник из предыдущего примера содержит четыре координаты, но обратите внимание на то, что первая и последняя координаты находятся в одной точке, образуя замкнутый контур. Однако на практике указывать последнюю координату не требуется, поскольку многоугольники по определению являются замкнутыми фигурами. Если последняя координата отличается от первой, API автоматически замкнет многоугольник, добавив первую координату в конец последовательности координат.

Ниже приведены два одинаковых многоугольника. При вызове метода polygon.getPoints() для каждого из них будут возвращены все 4 точки.

Java

Polygon polygon1 = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5),
        new LatLng(0, 0))
    .strokeColor(Color.RED)
    .fillColor(Color.BLUE));

Polygon polygon2 = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5))
    .strokeColor(Color.RED)
    .fillColor(Color.BLUE));
      

Kotlin

val polygon1 = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0),
            LatLng(0.0, 0.0)
        )
        .strokeColor(Color.RED)
        .fillColor(Color.BLUE)
)
val polygon2 = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0)
        )
        .strokeColor(Color.RED)
        .fillColor(Color.BLUE)
)
      

Как создать несплошной многоугольник

В одном объекте Polygon можно объединить несколько контуров. Это позволяет создавать сложные фигуры, в которых одни многоугольники располагаются внутри других подобно островкам (например, кольца с заливкой). Сложные фигуры всегда являются комбинациями более простых контуров.

Два контура должны быть определены в одной и той же области. Больший контур является простым многоугольником без дополнительных параметров и определяет область заливки. Создав большой контур, вызовите метод addHole() и передайте ему информацию о меньшем контуре. Если второй (меньший) контур располагается внутри первого, меньший контур отображается как вырезанный сегмент. Если вырезанный контур пересекается с внешним контуром многоугольника, то фигура не может иметь заливку.

Показанный ниже код создает прямоугольник с прямоугольным "отверстием" внутри.

Java

List<LatLng> hole = Arrays.asList(new LatLng(1, 1),
    new LatLng(1, 2),
    new LatLng(2, 2),
    new LatLng(2, 1),
    new LatLng(1, 1));
Polygon hollowPolygon = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5),
        new LatLng(3, 0),
        new LatLng(0, 0))
    .addHole(hole)
    .fillColor(Color.BLUE));
      

Kotlin

val hole = listOf(
    LatLng(1.0, 1.0),
    LatLng(1.0, 2.0),
    LatLng(2.0, 2.0),
    LatLng(2.0, 1.0),
    LatLng(1.0, 1.0)
)
val hollowPolygon = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0),
            LatLng(3.0, 0.0),
            LatLng(0.0, 0.0)
        )
        .addHole(hole)
        .fillColor(Color.BLUE)
)
      

События многоугольников

По умолчанию многоугольники не реагируют на клики. Чтобы включить или отключить кликабельность, необходимо вызвать метод Polygon.setClickable(boolean).

С помощью OnPolygonClickListener можно прослушивать события кликов по кликабельному многоугольнику. Чтобы добавить прослушиватель на карту, вызовите метод GoogleMap.setOnPolygonClickListener(OnPolygonClickListener). Когда пользователь нажмет на многоугольник, вы получите обратный вызов onPolygonClick(Polygon).

Круги

Помимо обобщенного класса Polygon в API Карт содержатся отдельные классы для объектов Circle, что упрощает создание кругов.

Чтобы создать круг, необходимо указать следующие два свойства:

  • center (объект LatLng, содержащий координаты центра);
  • radius (радиус в метрах).

Окружность затем определяется как набор всех точек на земной поверхности, которые удалены от координат radius на расстояние center. В силу особенностей проекции Меркатора в API Карт, сфера выглядит на карте, как почти идеальный круг, если располагается в районе экватора, и стремится к эллипсу по мере приближения к полюсу.

В приведенном ниже фрагменте кода показано, как добавить на карту круг, создав объект CircleOptions и вызвав метод GoogleMap.addCircle(CircleOptions).

Java

// Instantiates a new CircleOptions object and defines the center and radius
CircleOptions circleOptions = new CircleOptions()
    .center(new LatLng(37.4, -122.1))
    .radius(1000); // In meters

// Get back the mutable Circle
Circle circle = map.addCircle(circleOptions);
      

Kotlin

// Instantiates a new CircleOptions object and defines the center and radius
val circleOptions = CircleOptions()
    .center(LatLng(37.4, -122.1))
    .radius(1000.0) // In meters

// Get back the mutable Circle
val circle = map.addCircle(circleOptions)
      

Чтобы изменить параметры круга после его добавления, вызовите метод Circle.setRadius() или Circle.setCenter() и укажите новые значения.

Изменить внешний вид круга можно как до, так и после его добавления на карту. Подробнее…

События кругов

По умолчанию круги не реагируют на клики. Чтобы включить или отключить кликабельность, необходимо вызвать метод GoogleMap.addCircle() с методом CircleOptions.clickable(boolean) или метод Circle.setClickable(boolean).

С помощью OnCircleClickListener можно прослушивать события кликов по кликабельному кругу. Чтобы добавить прослушиватель на карту, вызовите метод GoogleMap.setOnCircleClickListener(OnCircleClickListener).

Когда пользователь нажмет на круг, вы получите обратный вызов onCircleClick(Circle), как показано в приведенном ниже примере кода.

Java

Circle circle = map.addCircle(new CircleOptions()
    .center(new LatLng(37.4, -122.1))
    .radius(1000)
    .strokeWidth(10)
    .strokeColor(Color.GREEN)
    .fillColor(Color.argb(128, 255, 0, 0))
    .clickable(true));

map.setOnCircleClickListener(new GoogleMap.OnCircleClickListener() {
    @Override
    public void onCircleClick(Circle circle) {
        // Flip the r, g and b components of the circle's stroke color.
        int strokeColor = circle.getStrokeColor() ^ 0x00ffffff;
        circle.setStrokeColor(strokeColor);
    }
});
      

Kotlin

val circle = map.addCircle(
    CircleOptions()
        .center(LatLng(37.4, -122.1))
        .radius(1000.0)
        .strokeWidth(10f)
        .strokeColor(Color.GREEN)
        .fillColor(Color.argb(128, 255, 0, 0))
        .clickable(true)
)
map.setOnCircleClickListener {
    // Flip the r, g and b components of the circle's stroke color.
    val strokeColor = it.strokeColor xor 0x00ffffff
    it.strokeColor = strokeColor
}
      

Как изменять внешний вид фигур

Фигуру можно изменить как до, так и после добавления на карту. Для этого нужно задать новые значения соответствующих свойств объекта. Ко всем свойствам применимы методы получения данных, поэтому узнать текущее состояние фигуры можно в любой момент.

Показанный ниже код соединяет Мельбурн и Перт толстой синей ломаной линией, сегменты которой являются геодезическими линиями (эти свойства подробно описаны ниже).

Java

Polyline polyline = map.addPolyline(new PolylineOptions()
    .add(new LatLng(-37.81319, 144.96298), new LatLng(-31.95285, 115.85734))
    .width(25)
    .color(Color.BLUE)
    .geodesic(true));
      

Kotlin

val polyline = map.addPolyline(
    PolylineOptions()
        .add(LatLng(-37.81319, 144.96298), LatLng(-31.95285, 115.85734))
        .width(25f)
        .color(Color.BLUE)
        .geodesic(true)
)
      

Примечание. Хотя почти все перечисленные свойства можно применять к любым фигурам, в некоторых случаях это не даст никакого эффекта. Например, нет смысла применять заливку к полилинии, поскольку она не имеет замкнутого контура.

Цвет контура

Цвет контура определяется целым числом в 32-битном формате ARGB (прозрачность-красный-зеленый-синий). Чтобы задать это свойство объекта фигуры, вызовите метод *Options.strokeColor() (или метод PolylineOptions.color(), если фигура является ломаной линией). Если цвет контура не указан, используется цвет по умолчанию – черный (Color.BLACK).

После добавления фигуры на карту можно получить цвет контура с помощью метода getStrokeColor() (или getColor() для ломаных линий) и изменить цвет с помощью метода setStrokeColor() (или setColor() for a polyline).

Цвет заливки

Цвет заливки применяется только к многоугольникам и кругам. Ломаная линия не может иметь заливку, так как не является замкнутой фигурой. "Отверстия" внутри многоугольника не считаются частью его внутренней области, поэтому к ним не применяется заливка заданного цвета.

Цвет заливки определяется целым числом в 32-битном формате ARGB (прозрачность-красный-зеленый-синий). Задайте это свойство объекта фигуры с помощью метода *Options.fillColor(). Если цвет не указан, используется цвет по умолчанию – прозрачный (Color.TRANSPARENT).

После добавления фигуры на карту цвет заливки можно получить с помощью метода getFillColor() и изменить с помощью setFillColor().

Толщина контура

Толщина контура определяется числом с плавающей запятой, обозначающим ширину в пикселях (пкс). Она не масштабируется, т. е. остается одинакова на всех уровнях масштаба карты. Чтобы задать это свойство объекта фигуры, вызовите метод *Options.strokeWidth() (или PolylineOptions.width() для ломаной линии). Если это свойство не указано, толщина контура по умолчанию составляет 10 пикселей.

После добавления фигуры на карту можно получить толщину контура с помощью метода getStrokeWidth() (или getWidth() для ломаных линий) и изменить толщину контура с помощью метода setStrokeWidth() (или setWidth() for a polyline).

Шаблон контура

Шаблон контура по умолчанию – сплошная линия (для ломаных линий, многоугольников и кругов). Вы можете задать другой шаблон контура с помощью объектов PatternItem, где каждый элемент представляет черту, точку или пробел.

В приведенном ниже примере кода в качестве шаблона контура задается последовательность "точка, пробел длиной 20 пикселей, черта длиной 30 пикселей, пробел длиной 20 пикселей".

Java

List<PatternItem> pattern = Arrays.asList(
    new Dot(), new Gap(20), new Dash(30), new Gap(20));
polyline.setPattern(pattern);
      

Kotlin

val pattern = listOf(
    Dot(), Gap(20F), Dash(30F), Gap(20F)
)
polyline.pattern = pattern
      

Шаблон циклично повторяется по всей длине контура и начинается с первого объекта последовательности в первой указанной вершине контура.

Типы соединений

Для ломаных линий и контуров многоугольников можно задать скошенные или закругленные соединения (JointType) вместо используемых по умолчанию угловых соединений.

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

Java

polyline.setJointType(JointType.ROUND);
      

Kotlin

polyline.jointType = JointType.ROUND
      

Тип соединений влияет на внутренние изгибы линии. Если для линии задан шаблон контура, содержащий черту, то тип соединений влияет на форму черт, приходящихся на места соединений. Тип соединений не влияет на точки, поскольку точка всегда круглая.

Окончания линий

Вы можете указать стиль линии (Cap) для каждого конца ломаной линии. Возможные варианты: торец (по умолчанию), квадрат, закругление, пользовательская битовая карта. Задайте стиль в полях PolylineOptions.startCap и PolylineOptions.endCap или используйте соответствующие геттер и сеттер методы.

В приведенном ниже примере кода показано, как закруглить начало ломанной линии.

Java

polyline.setStartCap(new RoundCap());
      

Kotlin

polyline.startCap = RoundCap()
      

В приведенном ниже примере показано, как задать пользовательскую битовую карту для окончания линии.

Java

polyline.setEndCap(
    new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.arrow), 16));
      

Kotlin

polyline.endCap = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.arrow), 16F)
      

Если вы задали пользовательскую битовую карту, необходимо указать ориентировочную ширину контура (в пикселях). API будет масштабировать битовую карту соответствующим образом. Ориентировочная ширина контура – это фактическая ширина контура в созданном вами изображении (битовой карте) без масштабирования. Значение по умолчанию для базовой ширины контура – 10 пикселей. Совет. Чтобы выбрать базовую ширину контура, откройте битовую карту в графическом редакторе в масштабе 100 % и определите нужную ширину контура для этого изображения.

Если вы создаете битовую карту с помощью метода BitmapDescriptorFactory.fromResource(), нужно использовать ресурс, независимый от плотности (nodpi).

Геодезические линии

Параметр geodesic указывает, является ли линия геодезической. Он применяется к ломаным линиям и многоугольникам, но не к окружностям, поскольку они не представляют собой наборы отрезков.

Это свойство определяет, каким образом рисовать отрезки между последовательными вершинами ломаной линии или многоугольника. Геодезическая линия представляет собой наиболее краткий путь вдоль земной поверхности (сферы). На карте с проекцией Меркатора такая линия имеет форму кривой. Негеодезическая линия рисуется на карте как прямая.

Чтобы задать это свойство для объекта параметров фигуры, вызовите метод *Options.geodesic(). Если указать значение true, отрезки будут отрисованы как геодезические линии, а если false – как прямые. По умолчанию используется значение false (т. е. негеодезические линии).

После добавления фигуры на карту это свойство можно получить с помощью метода isGeodesic() и изменить с помощью метода setGeodesic().

Z-индекс

Z-индекс определяет место фигуры в череде наложений на карте (других фигур, наземных наложений и мозаичных наложений). Наложение с большим значением свойства Z-index прорисовывается над наложениями с меньшими значениями Z-index. Два наложения с одинаковым значением свойства Z-index изображаются в произвольном порядке.

Обратите внимание, что маркеры всегда располагаются поверх всех остальных наложений (независимо от значений Z-индекса для этих наложений).

Задайте это свойство объекта фигуры с помощью метода *Options.zIndex(). Если оно не задано, используется значение по умолчанию – 0. После добавления фигуры на карту Z-индекс можно получить с помощью метода getZIndex() и изменить с помощью метода setZIndex().

Видимость

Свойство видимости указывает, должна ли фигура прорисовываться на карте. Значение true означает, что фигура должна отображаться, а значение false – что фигура невидима. С помощью этого параметра можно временно скрывать фигуры. Чтобы удалить фигуру навсегда, вызовите метод remove().

Задайте это свойство объекта фигуры с помощью метода *Options.visible(). Если оно не задано, используется значение по умолчанию – true. После добавления фигуры на карту значение видимости можно получить с помощью метода isVisible() и изменить с помощью метода setVisible().

Как связать данные с фигурой

С ломаной линией, многоугольником или кругом можно связать произвольный объект данных, вызвав метод setTag() объекта фигуры. Получить связанный с фигурой объект можно с помощью метода getTag(). Например, вызов метода Polyline.setTag() добавляет объект данных для многоугольника, а вызов метода Polyline.getTag() возвращает этот объект данных.

В приведенном ниже примере кода показано, как задать произвольный тег (A) для указанной ломаной линии:

Java

Polyline polyline = map.addPolyline((new PolylineOptions())
    .clickable(true)
    .add(new LatLng(-35.016, 143.321),
        new LatLng(-34.747, 145.592),
        new LatLng(-34.364, 147.891),
        new LatLng(-33.501, 150.217),
        new LatLng(-32.306, 149.248),
        new LatLng(-32.491, 147.309)));

polyline.setTag("A");
      

Kotlin

val polyline = map.addPolyline(
    PolylineOptions()
        .clickable(true)
        .add(
            LatLng(-35.016, 143.321),
            LatLng(-34.747, 145.592),
            LatLng(-34.364, 147.891),
            LatLng(-33.501, 150.217),
            LatLng(-32.306, 149.248),
            LatLng(-32.491, 147.309)
        )
)
polyline.tag = "A"
      

Примеры случаев, когда вам может понадобиться сохранение или получение данных, связанных с фигурами:

  • Ваше приложение должно по-разному обрабатывать нажатия на фигуры с учетом типа фигур.
  • Ваше приложение взаимодействует с системой, где имеются уникальные идентификаторы записей, и эти записи представлены фигурами.
  • В качестве связанных с фигурой данных можно задать значение ее Z-индекса.