Фигуры и линии

Выберите платформу: Android iOS JavaScript

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

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

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

Как добавить ломаную линию

Конструктор Polyline берет набор параметров PolylineOptions, задающих координаты LatLng линии и набор стилей для настройки ее отображения.

Объекты Polyline (полилинии) рисуются на карте в виде последовательности прямых отрезков. С помощью свойств объекта PolylineOptions можно задать цвет, толщину и прозрачность линии (как во время, так и после ее отрисовки). Ломаная линия поддерживает следующие стили штрихов:

  • strokeColor задает шестнадцатеричный цвет HTML в формате "#FFFFFF". Класс Polyline не поддерживает именованные цвета.
  • strokeOpacity – числовое значение в диапазоне от 0.0 до 1.0, определяющее прозрачность линии. Значение по умолчанию – 1.0.
  • strokeWeight – толщина линии в пикселях.

Свойство полилинии editable определяет, может ли пользователь редактировать ее (подробнее читайте в разделе Формы, редактируемые пользователем). Свойство draggable определяет, может ли пользовать перетаскивать линию.

В этом примере создается красная ломаная линия шириной два пикселя, которая показывает путь первого транстихоокеанского перелета между Оклендом (Калифорния, США) и Брисбеном (Австралия).

TypeScript

// This example creates a 2-pixel-wide red polyline showing the path of
// the first trans-Pacific flight between Oakland, CA, and Brisbane,
// Australia which was made by Charles Kingsford Smith.
const mapElement = document.querySelector('gmp-map')!;
let innerMap: google.maps.Map;

async function init() {
    const { Polyline } = await google.maps.importLibrary('maps');
    innerMap = mapElement.innerMap;

    const flightPlanCoordinates = [
        { lat: 37.772, lng: -122.214 },
        { lat: 21.291, lng: -157.821 },
        { lat: -18.142, lng: 178.431 },
        { lat: -27.467, lng: 153.027 },
    ];
    const flightPath = new Polyline({
        path: flightPlanCoordinates,
        geodesic: true,
        strokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2,
    });

    flightPath.setMap(innerMap);
}

void init();

JavaScript

// This example creates a 2-pixel-wide red polyline showing the path of
// the first trans-Pacific flight between Oakland, CA, and Brisbane,
// Australia which was made by Charles Kingsford Smith.
const mapElement = document.querySelector('gmp-map');
let innerMap;

async function init() {
    const { Polyline } = await google.maps.importLibrary('maps');
    innerMap = mapElement.innerMap;

    const flightPlanCoordinates = [
        { lat: 37.772, lng: -122.214 },
        { lat: 21.291, lng: -157.821 },
        { lat: -18.142, lng: 178.431 },
        { lat: -27.467, lng: 153.027 },
    ];
    const flightPath = new Polyline({
        path: flightPlanCoordinates,
        geodesic: true,
        strokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2,
    });

    flightPath.setMap(innerMap);
}

void init();
Посмотреть пример

Удаление ломаной линии

Чтобы удалить ломаную линию с карты, вызовите метод setMap() и передайте с его помощью аргумент null. Во фрагменте кода ниже flightPath обозначает ломаную линию.

flightPath.setMap(null);

Отметим, что этот метод не удаляет ломаную линию окончательно, а просто убирает ее с карты. Чтобы полностью удалить ломаную линию, необходимо также присвоить ее объекту значение null.

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

Ломаная линия представляет собой последовательность координат в виде массива объектов LatLng. Координаты определяют форму линии. Чтобы получить координаты, вызовите метод getPath(), который возвращает массив MVCArray. Для проверки и управления массивом можно использовать следующие методы:

  • getAt(): возвращает объект LatLng для заданного индексного значения (с точкой отсчета в нуле).
  • insertAt(): вставляет переданный объект LatLng в позицию для заданного индексного значения (с точкой отсчета в нуле). При этом индексные значения всех остальных координат смещаются.
  • removeAt(): удаляет объект LatLng с заданной индексным значением позиции.

В следующем примере показано, как создать ломаную линию на основе нажатий (нажмите на карту, чтобы добавить вершину).

TypeScript

/**
 * This example creates an interactive map which constructs a polyline based on
 * user clicks. Note that the polyline only appears once its path property
 * contains two LatLng coordinates.
 */

let poly: google.maps.Polyline;
const mapElement = document.querySelector('gmp-map')!;
let innerMap: google.maps.Map;

async function init() {
    // Import the needed libraries.
    const [{ Polyline }, { AdvancedMarkerElement }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('marker'),
    ]);

    innerMap = mapElement.innerMap;

    poly = new Polyline({
        strokeColor: '#000000',
        strokeOpacity: 1.0,
        strokeWeight: 3,
    });
    poly.setMap(innerMap);

    // Handles click events on a map, and adds a new point to the Polyline.
    innerMap.addListener('click', (event: google.maps.MapMouseEvent) => {
        const latLng = event.latLng;
        if (!latLng) return;

        const path = poly.getPath();

        // Because path is an MVCArray, we can simply append a new coordinate
        // and it will automatically appear.
        path.push(latLng);

        // Add a new marker at the new plotted point on the polyline.
        new AdvancedMarkerElement({
            position: latLng,
            title: '#' + path.getLength(),
            map: innerMap,
        });
    });
}

void init();

JavaScript

/**
 * This example creates an interactive map which constructs a polyline based on
 * user clicks. Note that the polyline only appears once its path property
 * contains two LatLng coordinates.
 */

let poly;
const mapElement = document.querySelector('gmp-map');
let innerMap;

async function init() {
    // Import the needed libraries.
    const [{ Polyline }, { AdvancedMarkerElement }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('marker'),
    ]);

    innerMap = mapElement.innerMap;

    poly = new Polyline({
        strokeColor: '#000000',
        strokeOpacity: 1.0,
        strokeWeight: 3,
    });
    poly.setMap(innerMap);

    // Handles click events on a map, and adds a new point to the Polyline.
    innerMap.addListener('click', (event) => {
        const latLng = event.latLng;
        if (!latLng) return;

        const path = poly.getPath();

        // Because path is an MVCArray, we can simply append a new coordinate
        // and it will automatically appear.
        path.push(latLng);

        // Add a new marker at the new plotted point on the polyline.
        new AdvancedMarkerElement({
            position: latLng,
            title: '#' + path.getLength(),
            map: innerMap,
        });
    });
}

void init();
Посмотреть пример

Настройка ломаной линии

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

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

Многоугольник – это область, ограниченная замкнутым контуром, который определяется последовательностью координат. Объекты Polygon похожи на Polyline тем, что состоят из заданной последовательности координат. Многоугольники отрисовываются линиями и заливкой. Вы можете задавать цвета, толщину и прозрачность границ многоугольника (линий), а также цвета и прозрачность заливки. Цвета следует указывать в шестнадцатеричном формате HTML. Названия цветов не поддерживаются.

С помощью объектов Polygon можно определять сложные фигуры, в том числе:

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

Для определения сложных фигур используется многоугольник из нескольких контуров.

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

Как добавить многоугольник

Поскольку многоугольная область может содержать несколько контуров, свойство paths объекта Polygon определяет массив массивов типа MVCArray. Каждый из включенных массивов определяет собственную последовательность координат LatLng.

Если вы хотите нарисовать простой многоугольник с одним путем, достаточно создать объект Polygon с единым массивом координат LatLng. При вызове конструктора Maps JavaScript API преобразует простой массив в массив массивов и сохраняет его в свойстве paths. Для простых многоугольников в API предусмотрен метод getPath().

Свойство многоугольника editable определяет, может ли пользователь редактировать его (подробнее читайте в разделе Формы, редактируемые пользователем). Свойство draggable определяет, может ли пользователь перетаскивать многоугольник.

TypeScript

// This example creates a simple polygon representing the Bermuda Triangle.

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 5,
      center: { lat: 24.886, lng: -70.268 },
      mapTypeId: "terrain",
    }
  );

  // Define the LatLng coordinates for the polygon's path.
  const triangleCoords = [
    { lat: 25.774, lng: -80.19 },
    { lat: 18.466, lng: -66.118 },
    { lat: 32.321, lng: -64.757 },
    { lat: 25.774, lng: -80.19 },
  ];

  // Construct the polygon.
  const bermudaTriangle = new google.maps.Polygon({
    paths: triangleCoords,
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
  });

  bermudaTriangle.setMap(map);
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example creates a simple polygon representing the Bermuda Triangle.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 5,
    center: { lat: 24.886, lng: -70.268 },
    mapTypeId: "terrain",
  });
  // Define the LatLng coordinates for the polygon's path.
  const triangleCoords = [
    { lat: 25.774, lng: -80.19 },
    { lat: 18.466, lng: -66.118 },
    { lat: 32.321, lng: -64.757 },
    { lat: 25.774, lng: -80.19 },
  ];
  // Construct the polygon.
  const bermudaTriangle = new google.maps.Polygon({
    paths: triangleCoords,
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
  });

  bermudaTriangle.setMap(map);
}

window.initMap = initMap;
Посмотреть пример

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

Объект Polygon из предыдущего примера содержит четыре пары координат LatLng. Обратите внимание: первая и последняя координаты находятся в одной точке, образуя замкнутый контур. На практике указывать последнюю координату не требуется, поскольку многоугольники по определению являются замкнутыми фигурами. Maps JavaScript API автоматически дорисовывает все многоугольники, соединяя последнюю координату с первой для любого заданного пути.

Этот пример идентичен предыдущему, за исключением того, что последнее значение LatLng опущено.

Как удалить многоугольник

Чтобы удалить многоугольник с карты, вызовите метод setMap() и передайте с его помощью аргумент null. В примере ниже используется многоугольник bermudaTriangle.

bermudaTriangle.setMap(null);

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

Как проверить многоугольник

Многоугольник определяет серию своих координат как массив массивов типа MVCArray. Каждый подчиненный массив – это набор координат LatLng, определяющий один путь. Чтобы извлечь эти координаты, вызовите для объекта Polygon метод getPaths(). Поскольку массив является объектом MVCArray, для работы с ним нужно использовать перечисленные ниже методы.

  • getAt(): возвращает объект LatLng для заданного индексного значения (с точкой отсчета в нуле).
  • insertAt(): вставляет переданный объект LatLng в позицию для заданного индексного значения (с точкой отсчета в нуле). При этом индексные значения всех остальных координат смещаются.
  • removeAt(): удаляет объект LatLng с заданной индексным значением позиции.

TypeScript

// This example creates a simple polygon representing the Bermuda Triangle.
// When the user clicks on the polygon an info window opens, showing
// information about the polygon's coordinates.

let map: google.maps.Map;

let infoWindow: google.maps.InfoWindow;

function initMap(): void {
  map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
    zoom: 5,
    center: { lat: 24.886, lng: -70.268 },
    mapTypeId: "terrain",
  });

  // Define the LatLng coordinates for the polygon.
  const triangleCoords: google.maps.LatLngLiteral[] = [
    { lat: 25.774, lng: -80.19 },
    { lat: 18.466, lng: -66.118 },
    { lat: 32.321, lng: -64.757 },
  ];

  // Construct the polygon.
  const bermudaTriangle = new google.maps.Polygon({
    paths: triangleCoords,
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 3,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
  });

  bermudaTriangle.setMap(map);

  // Add a listener for the click event.
  bermudaTriangle.addListener("click", showArrays);

  infoWindow = new google.maps.InfoWindow();
}

function showArrays(event: any) {
  // Since this polygon has only one path, we can call getPath() to return the
  // MVCArray of LatLngs.
  // @ts-ignore
  const polygon = this as google.maps.Polygon;
  const vertices = polygon.getPath();

  let contentString =
    "<b>Bermuda Triangle polygon</b><br>" +
    "Clicked location: <br>" +
    event.latLng.lat() +
    "," +
    event.latLng.lng() +
    "<br>";

  // Iterate over the vertices.
  for (let i = 0; i < vertices.getLength(); i++) {
    const xy = vertices.getAt(i);

    contentString +=
      "<br>" + "Coordinate " + i + ":<br>" + xy.lat() + "," + xy.lng();
  }

  // Replace the info window's content and position.
  infoWindow.setContent(contentString);
  infoWindow.setPosition(event.latLng);

  infoWindow.open(map);
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example creates a simple polygon representing the Bermuda Triangle.
// When the user clicks on the polygon an info window opens, showing
// information about the polygon's coordinates.
let map;
let infoWindow;

function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    zoom: 5,
    center: { lat: 24.886, lng: -70.268 },
    mapTypeId: "terrain",
  });

  // Define the LatLng coordinates for the polygon.
  const triangleCoords = [
    { lat: 25.774, lng: -80.19 },
    { lat: 18.466, lng: -66.118 },
    { lat: 32.321, lng: -64.757 },
  ];
  // Construct the polygon.
  const bermudaTriangle = new google.maps.Polygon({
    paths: triangleCoords,
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 3,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
  });

  bermudaTriangle.setMap(map);
  // Add a listener for the click event.
  bermudaTriangle.addListener("click", showArrays);
  infoWindow = new google.maps.InfoWindow();
}

function showArrays(event) {
  // Since this polygon has only one path, we can call getPath() to return the
  // MVCArray of LatLngs.
  // @ts-ignore
  const polygon = this;
  const vertices = polygon.getPath();
  let contentString =
    "<b>Bermuda Triangle polygon</b><br>" +
    "Clicked location: <br>" +
    event.latLng.lat() +
    "," +
    event.latLng.lng() +
    "<br>";

  // Iterate over the vertices.
  for (let i = 0; i < vertices.getLength(); i++) {
    const xy = vertices.getAt(i);

    contentString +=
      "<br>" + "Coordinate " + i + ":<br>" + xy.lat() + "," + xy.lng();
  }

  // Replace the info window's content and position.
  infoWindow.setContent(contentString);
  infoWindow.setPosition(event.latLng);
  infoWindow.open(map);
}

window.initMap = initMap;
Посмотреть пример

Отверстие в многоугольнике

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

Примечание. Слой данных самостоятельно определяет порядок внутренних и внешних контуров, облегчая создание многоугольников с отверстиями. Подробнее читайте в разделе Слой данных.

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

TypeScript

// This example creates a triangular polygon with a hole in it.

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 5,
      center: { lat: 24.886, lng: -70.268 },
    }
  );

  // Define the LatLng coordinates for the polygon's  outer path.
  const outerCoords = [
    { lat: 25.774, lng: -80.19 },
    { lat: 18.466, lng: -66.118 },
    { lat: 32.321, lng: -64.757 },
  ];

  // Define the LatLng coordinates for the polygon's inner path.
  // Note that the points forming the inner path are wound in the
  // opposite direction to those in the outer path, to form the hole.
  const innerCoords = [
    { lat: 28.745, lng: -70.579 },
    { lat: 29.57, lng: -67.514 },
    { lat: 27.339, lng: -66.668 },
  ];

  // Construct the polygon, including both paths.
  const bermudaTriangle = new google.maps.Polygon({
    paths: [outerCoords, innerCoords],
    strokeColor: "#FFC107",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FFC107",
    fillOpacity: 0.35,
  });

  bermudaTriangle.setMap(map);
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example creates a triangular polygon with a hole in it.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 5,
    center: { lat: 24.886, lng: -70.268 },
  });
  // Define the LatLng coordinates for the polygon's  outer path.
  const outerCoords = [
    { lat: 25.774, lng: -80.19 },
    { lat: 18.466, lng: -66.118 },
    { lat: 32.321, lng: -64.757 },
  ];
  // Define the LatLng coordinates for the polygon's inner path.
  // Note that the points forming the inner path are wound in the
  // opposite direction to those in the outer path, to form the hole.
  const innerCoords = [
    { lat: 28.745, lng: -70.579 },
    { lat: 29.57, lng: -67.514 },
    { lat: 27.339, lng: -66.668 },
  ];
  // Construct the polygon, including both paths.
  const bermudaTriangle = new google.maps.Polygon({
    paths: [outerCoords, innerCoords],
    strokeColor: "#FFC107",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FFC107",
    fillOpacity: 0.35,
  });

  bermudaTriangle.setMap(map);
}

window.initMap = initMap;
Посмотреть пример

Прямоугольники

Помимо общего класса Polygon, в Maps JavaScript API предусмотрен специальный класс Rectangle, упрощающий создание прямоугольников.

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

Прямоугольник (Rectangle) похож на многоугольник (Polygon) тем, что вы можете задавать цвет, толщину и прозрачность границ, а также цвет и прозрачность заливки. Цвета следует указывать в шестнадцатеричном числовом формате HTML.

В отличие от Polygon, задавать объект paths для фигуры Rectangle не требуется. Вместо него используется свойство bounds, определяющее форму прямоугольника при помощи объекта google.maps.LatLngBounds.

Свойство прямоугольника editable определяет, может ли пользователь редактировать его (подробнее читайте в разделе Формы, редактируемые пользователем). Свойство draggable определяет, может ли пользователь перетаскивать прямоугольник.

TypeScript

// This example adds a red rectangle to a map.

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 11,
      center: { lat: 33.678, lng: -116.243 },
      mapTypeId: "terrain",
    }
  );

  const rectangle = new google.maps.Rectangle({
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
    map,
    bounds: {
      north: 33.685,
      south: 33.671,
      east: -116.234,
      west: -116.251,
    },
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example adds a red rectangle to a map.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 11,
    center: { lat: 33.678, lng: -116.243 },
    mapTypeId: "terrain",
  });
  const rectangle = new google.maps.Rectangle({
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
    map,
    bounds: {
      north: 33.685,
      south: 33.671,
      east: -116.234,
      west: -116.251,
    },
  });
}

window.initMap = initMap;
Посмотреть пример

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

TypeScript

// This example creates a rectangle based on the viewport
// on any 'zoom-changed' event.

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 11,
      center: { lat: 40.74852, lng: -73.981687 },
      mapTypeId: "terrain",
    }
  );

  const rectangle = new google.maps.Rectangle();

  map.addListener("zoom_changed", () => {
    // Get the current bounds, which reflect the bounds before the zoom.
    rectangle.setOptions({
      strokeColor: "#FF0000",
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: "#FF0000",
      fillOpacity: 0.35,
      map,
      bounds: map.getBounds() as google.maps.LatLngBounds,
    });
  });
}

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;

JavaScript

// This example creates a rectangle based on the viewport
// on any 'zoom-changed' event.
function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 11,
    center: { lat: 40.74852, lng: -73.981687 },
    mapTypeId: "terrain",
  });
  const rectangle = new google.maps.Rectangle();

  map.addListener("zoom_changed", () => {
    // Get the current bounds, which reflect the bounds before the zoom.
    rectangle.setOptions({
      strokeColor: "#FF0000",
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: "#FF0000",
      fillOpacity: 0.35,
      map,
      bounds: map.getBounds(),
    });
  });
}

window.initMap = initMap;
Посмотреть пример

Удаление прямоугольника

Чтобы удалить прямоугольник с карты, вызовите метод setMap() и передайте с его помощью аргумент null.

rectangle.setMap(null);

Отметим, что этот метод не удаляет прямоугольник окончательно, а лишь убирает его с карты. Чтобы полностью удалить прямоугольник, необходимо также задать для его объекта значение null.

Окружности

Помимо общего класса Polygon, в Maps JavaScript API предусмотрен специальный класс Circle, упрощающий создание окружностей.

Как добавить окружность

Фигура Circle похожа на Polygon тем, что вы можете задавать ее цвет, толщину и прозрачность очертания, а также цвет и прозрачность заливки. Цвета следует указывать в шестнадцатеричном числовом формате HTML.

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

  • center задает значения google.maps.LatLng для центра окружности.
  • radius задает радиус окружности в метрах.

Свойство окружности editable определяет, может ли пользователь редактировать ее (подробнее читайте в разделе Формы, редактируемые пользователем). Свойство draggable определяет, может ли пользователь перетаскивать окружность.

В следующем примере показаны круги, обозначающие приблизительное время пешей прогулки между разными местами в Киото (Япония). Выберите нужное расстояние в меню, нажмите на карту, чтобы снова центрировать круг, и перетащите круг, чтобы изменить его положение.

TypeScript

const mapElement = document.querySelector('gmp-map')!;
let innerMap: google.maps.Map;

async function init() {
    // Request needed libraries.
    const [{ Circle }, { AdvancedMarkerElement }, { event }] =
        await Promise.all([
            google.maps.importLibrary('maps'),
            google.maps.importLibrary('marker'),
            google.maps.importLibrary('core'),
        ]);

    // Set the initial map center point.
    const initialCenter = { lat: 34.98956821576194, lng: 135.74239981260283 }; // Hotel Emion, Kyoto, Japan

    // Get the inner map.
    innerMap = mapElement.innerMap;

    // Get the buttons.
    const buttons = document.querySelectorAll('input[name="radius"]');

    // Create the circle.
    const walkingCircle = new Circle({
        strokeColor: '#ffdd00ff',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#ffdd00ff',
        fillOpacity: 0.35,
        map: innerMap,
        center: initialCenter,
        radius: 400,
        draggable: true,
        editable: false,
    });

    // Define a "Crosshair" vector icon
    const parser = new DOMParser();
    const svgString = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="-6 -6 12 12"><path d="M -6,0 L 6,0 M 0,-6 L 0,6" stroke="black" stroke-width="1"/></svg>`;

    const pinSvg = parser.parseFromString(
        svgString,
        'image/svg+xml'
    ).documentElement;

    const centerMarker = new AdvancedMarkerElement({
        position: initialCenter,
        title: 'A marker using a custom SVG image.',
        anchorLeft: '-50%',
        anchorTop: '-50%',
    });
    centerMarker.append(pinSvg);
    mapElement.append(centerMarker);

    // Wait for the map to finish drawing its tiles.
    event.addListenerOnce(innerMap, 'tilesloaded', () => {
        // Get the controls div
        const controls = document.getElementById('control-panel');

        // Display controls once map is loaded.
        if (controls) {
            controls.style.display = 'block';
        }
    });

    // Add event listener to update the radius based on user selection.
    buttons.forEach((button) => {
        button.addEventListener('change', (changeEvent) => {
            const target = changeEvent.target as HTMLInputElement;
            walkingCircle.setRadius(Number(target.value));
        });
    });

    // Handle user click, reset the map center and position the circle.
    innerMap.addListener(
        'click',
        (
            mapsMouseEvent:
                google.maps.MapMouseEvent | google.maps.IconMouseEvent
        ) => {
            const newCenter = mapsMouseEvent.latLng;
            if (!newCenter) return;
            walkingCircle.setCenter(newCenter);
            centerMarker.position = newCenter;
            innerMap.panTo(newCenter);
        }
    );

    // Handle user dragging the circle, update the center marker position.
    walkingCircle.addListener('center_changed', () => {
        centerMarker.position = walkingCircle.getCenter();
    });
}

void init();

JavaScript

const mapElement = document.querySelector('gmp-map');
let innerMap;

async function init() {
    // Request needed libraries.
    const [{ Circle }, { AdvancedMarkerElement }, { event }] =
        await Promise.all([
            google.maps.importLibrary('maps'),
            google.maps.importLibrary('marker'),
            google.maps.importLibrary('core'),
        ]);

    // Set the initial map center point.
    const initialCenter = { lat: 34.98956821576194, lng: 135.74239981260283 }; // Hotel Emion, Kyoto, Japan

    // Get the inner map.
    innerMap = mapElement.innerMap;

    // Get the buttons.
    const buttons = document.querySelectorAll('input[name="radius"]');

    // Create the circle.
    const walkingCircle = new Circle({
        strokeColor: '#ffdd00ff',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#ffdd00ff',
        fillOpacity: 0.35,
        map: innerMap,
        center: initialCenter,
        radius: 400,
        draggable: true,
        editable: false,
    });

    // Define a "Crosshair" vector icon
    const parser = new DOMParser();
    const svgString = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="-6 -6 12 12"><path d="M -6,0 L 6,0 M 0,-6 L 0,6" stroke="black" stroke-width="1"/></svg>`;

    const pinSvg = parser.parseFromString(
        svgString,
        'image/svg+xml'
    ).documentElement;

    const centerMarker = new AdvancedMarkerElement({
        position: initialCenter,
        title: 'A marker using a custom SVG image.',
        anchorLeft: '-50%',
        anchorTop: '-50%',
    });
    centerMarker.append(pinSvg);
    mapElement.append(centerMarker);

    // Wait for the map to finish drawing its tiles.
    event.addListenerOnce(innerMap, 'tilesloaded', () => {
        // Get the controls div
        const controls = document.getElementById('control-panel');

        // Display controls once map is loaded.
        if (controls) {
            controls.style.display = 'block';
        }
    });

    // Add event listener to update the radius based on user selection.
    buttons.forEach((button) => {
        button.addEventListener('change', (changeEvent) => {
            const target = changeEvent.target;
            walkingCircle.setRadius(Number(target.value));
        });
    });

    // Handle user click, reset the map center and position the circle.
    innerMap.addListener('click', (mapsMouseEvent) => {
        const newCenter = mapsMouseEvent.latLng;
        if (!newCenter) return;
        walkingCircle.setCenter(newCenter);
        centerMarker.position = newCenter;
        innerMap.panTo(newCenter);
    });

    // Handle user dragging the circle, update the center marker position.
    walkingCircle.addListener('center_changed', () => {
        centerMarker.position = walkingCircle.getCenter();
    });
}

void init();

CSS

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#control-panel {
    display: none; /* Set to 'display: block' after the map loads. */
    background-color: #fff;
    border: 2px solid #fff;
    border-radius: 3px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    font-family: 'Roboto', sans-serif;
    font-size: medium;
    margin: 10px;
    padding: 10px;
}

HTML

<html>
    <head>
        <title>Circles</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <gmp-map
            center="34.98956821576194, 135.74239981260283"
            zoom="15"
            map-id="DEMO_MAP_ID">
            <div id="control-panel" slot="control-inline-start-block-start">
                <input
                    id="short-walk"
                    type="radio"
                    name="radius"
                    value="400"
                    checked />
                <label for="short-walk">Short Walk (~5 minutes)</label><br />
                <input
                    id="medium-walk"
                    type="radio"
                    name="radius"
                    value="800" />
                <label for="medium-walk">Medium Walk (~15 minutes)</label><br />
                <input id="long-walk" type="radio" name="radius" value="1600" />
                <label for="long-walk">Long Walk (~30 minutes) </label>
            </div>
        </gmp-map>
    </body>
</html>
Посмотреть пример

Удаление круга

Чтобы удалить окружность с карты, вызовите метод setMap() и передайте с его помощью аргумент null.

circle.setMap(null);

Отметим, что это метод не удаляет окружность окончательно, а лишь убирает ее с карты. Чтобы полностью удалить окружность, необходимо также задать для ее объекта значение null.

Редактируемые и перетаскиваемые фигуры

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

Изменения объектов, выполненные пользователями, не сохраняются между сеансами. Если вы хотите сохранять пользовательские правки, ваше приложение должно уметь записывать и сохранять их.

Как сделать фигуру редактируемой

Пользователь может редактировать ломаные линии, многоугольники, окружности и прямоугольники, если для параметра editable соответствующей фигуры установлено значение true.

var bounds = {
  north: 44.599,
  south: 44.490,
  east: -78.443,
  west: -78.649
};

// Define a rectangle and set its editable property to true.
var rectangle = new google.maps.Rectangle({
  bounds: bounds,
  editable: true
});

Посмотреть пример

Как сделать фигуру перетаскиваемой

Положение нарисованной на карте фигуры по умолчанию фиксировано. Чтобы разрешить пользователям перетаскивать фигуру, присвойте переменной draggable в настройках фигуры значение true.

var redCoords = [
  {lat: 25.774, lng: -80.190},
  {lat: 18.466, lng: -66.118},
  {lat: 32.321, lng: -64.757}
];

// Construct a draggable red triangle with geodesic set to true.
new google.maps.Polygon({
  map: map,
  paths: redCoords,
  strokeColor: '#FF0000',
  strokeOpacity: 0.8,
  strokeWeight: 2,
  fillColor: '#FF0000',
  fillOpacity: 0.35,
  draggable: true,
  geodesic: true
});

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

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

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

Подробнее о системах координат читайте в статье Координаты карт и фрагментов.

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

Посмотреть пример

Как отслеживать события редактирования

Ниже приведен список событий, которые активируются по завершении редактирования фигуры.

Фигура События
Окружность radius_changed
center_changed
Многоугольник insert_at
remove_at
set_at

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

Ломаная линия insert_at
remove_at
set_at

Прослушиватель требуется установить на контуре ломаной линии.

Прямоугольник bounds_changed

Полезные фрагменты кода:

google.maps.event.addListener(circle, 'radius_changed', function() {
  console.log(circle.getRadius());
});

google.maps.event.addListener(outerPath, 'set_at', function() {
  console.log('Vertex moved on outer path.');
});

google.maps.event.addListener(innerPath, 'insert_at', function() {
  console.log('Vertex removed from inner path.');
});

google.maps.event.addListener(rectangle, 'bounds_changed', function() {
  console.log('Bounds changed.');
});

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

Как отслеживать события перетаскивания

События активируются в начале, в конце и в процессе перетаскивания. Ниже перечислены события, активирующиеся с ломаными линиями, многоугольниками, окружностями и прямоугольниками.

Событие Описание
dragstart Активируется, когда пользователь начинает перетаскивать фигуру.
drag Активируется многократно во время перескакивания.
dragend Активируется, когда пользователь заканчивает перетаскивать фигуру.

Подробнее об обработке событий…