Матрица маршрута — это двумерный массив информации о маршруте, где строки соответствуют точкам отправления, а столбцы — точкам назначения. Имея список точек отправления и назначения, класс Route Matrix вычисляет расстояние и продолжительность маршрута, начинающегося в каждой точке отправления и заканчивающегося в каждой точке назначения. Используйте класс Route Matrix для вычисления расстояния и продолжительности маршрута для нескольких точек отправления и назначения.
См. полный пример исходного кода.
В этом примере показано, как использовать класс Route Matrix для расчета расстояний и продолжительности поездок между несколькими пунктами отправления и назначения.
Машинопись
// Initialize and add the map. let map; let markers: google.maps.marker.AdvancedMarkerElement[] = []; let center = { lat: 51.55, lng: -1.8 }; async function initMap(): Promise<void> { // Request the needed libraries. //prettier-ignore //@ts-ignore const [{Map}, {Place}, {AdvancedMarkerElement, PinElement}, {RouteMatrix}] = await Promise.all([ google.maps.importLibrary('maps') as Promise<google.maps.MapsLibrary>, google.maps.importLibrary('places') as Promise<google.maps.PlacesLibrary>, google.maps.importLibrary('marker') as Promise<google.maps.MarkerLibrary>, google.maps.importLibrary('routes') as Promise<google.maps.RoutesLibrary> ]); const bounds = new google.maps.LatLngBounds(); map = new Map(document.getElementById('map') as HTMLElement, { zoom: 8, center: center, mapId: 'DEMO_MAP_ID', }); // Build the request using Place instances. const origin1 = new Place({ id: 'ChIJ83WZp86p2EcRbMrkYqGncBQ', // Greenwich, London, UK }); const origin2 = new Place({ id: 'ChIJCSkVvleJc0gR8HHaTGpajKc', // Southampton, UK }); const destinationA = new Place({ id: 'ChIJYdizgWaDcUgRH9eaSy6y5I4', // Bristol, UK }); const destinationB = new Place({ id: 'ChIJ9VPsNNQCbkgRDmeGZdsGNBQ', // Cardiff, UK }); await Promise.all([ origin1.fetchFields({ fields: ['location', 'displayName'] }), origin2.fetchFields({ fields: ['location', 'displayName'] }), destinationA.fetchFields({ fields: ['location', 'displayName'] }), destinationB.fetchFields({ fields: ['location', 'displayName'] }), ]); const request = { origins: [origin1, origin2], destinations: [destinationA, destinationB], travelMode: 'DRIVING', units: google.maps.UnitSystem.METRIC, fields: ['distanceMeters', 'durationMillis', 'condition'], }; // Show the request. (document.getElementById('request') as HTMLDivElement).innerText = JSON.stringify(request, null, 2); // Get the RouteMatrix response. const response = await RouteMatrix.computeRouteMatrix(request); // Show the response. (document.getElementById('response') as HTMLDivElement).innerText = JSON.stringify(response, null, 2); // Add markers for the origins. for (const origin of request.origins) { if (origin.location) { const pin = new PinElement({ //@ts-ignore glyphText: 'O', glyphColor: 'white', background: '#137333', borderColor: 'white', }); const marker = new AdvancedMarkerElement({ map, position: origin.location, content: pin.element, title: `Origin: ${origin.displayName}`, }); markers.push(marker); bounds.extend(origin.location); } } // Add markers for the destinations. for (let i = 0; i < request.destinations.length; i++) { const destination = request.destinations[i]; if (destination.location) { const pin = new PinElement({ //@ts-ignore glyphText: 'D', glyphColor: 'white', background: '#C5221F', borderColor: 'white', }); const marker = new AdvancedMarkerElement({ map, position: destination.location, content: pin.element, title: `Destination: ${destination.displayName}`, }); markers.push(marker); bounds.extend(destination.location); } } // Fit the map to the bounds of all markers. map.fitBounds(bounds); } initMap();
JavaScript
// Initialize and add the map. let map; let markers = []; let center = { lat: 51.55, lng: -1.8 }; async function initMap() { // Request the needed libraries. //prettier-ignore //@ts-ignore const [{ Map }, { Place }, { AdvancedMarkerElement, PinElement }, { RouteMatrix }] = await Promise.all([ google.maps.importLibrary('maps'), google.maps.importLibrary('places'), google.maps.importLibrary('marker'), google.maps.importLibrary('routes') ]); const bounds = new google.maps.LatLngBounds(); map = new Map(document.getElementById('map'), { zoom: 8, center: center, mapId: 'DEMO_MAP_ID', }); // Build the request using Place instances. const origin1 = new Place({ id: 'ChIJ83WZp86p2EcRbMrkYqGncBQ', // Greenwich, London, UK }); const origin2 = new Place({ id: 'ChIJCSkVvleJc0gR8HHaTGpajKc', // Southampton, UK }); const destinationA = new Place({ id: 'ChIJYdizgWaDcUgRH9eaSy6y5I4', // Bristol, UK }); const destinationB = new Place({ id: 'ChIJ9VPsNNQCbkgRDmeGZdsGNBQ', // Cardiff, UK }); await Promise.all([ origin1.fetchFields({ fields: ['location', 'displayName'] }), origin2.fetchFields({ fields: ['location', 'displayName'] }), destinationA.fetchFields({ fields: ['location', 'displayName'] }), destinationB.fetchFields({ fields: ['location', 'displayName'] }), ]); const request = { origins: [origin1, origin2], destinations: [destinationA, destinationB], travelMode: 'DRIVING', units: google.maps.UnitSystem.METRIC, fields: ['distanceMeters', 'durationMillis', 'condition'], }; // Show the request. document.getElementById('request').innerText = JSON.stringify(request, null, 2); // Get the RouteMatrix response. const response = await RouteMatrix.computeRouteMatrix(request); // Show the response. document.getElementById('response').innerText = JSON.stringify(response, null, 2); // Add markers for the origins. for (const origin of request.origins) { if (origin.location) { const pin = new PinElement({ //@ts-ignore glyphText: 'O', glyphColor: 'white', background: '#137333', borderColor: 'white', }); const marker = new AdvancedMarkerElement({ map, position: origin.location, content: pin.element, title: `Origin: ${origin.displayName}`, }); markers.push(marker); bounds.extend(origin.location); } } // Add markers for the destinations. for (let i = 0; i < request.destinations.length; i++) { const destination = request.destinations[i]; if (destination.location) { const pin = new PinElement({ //@ts-ignore glyphText: 'D', glyphColor: 'white', background: '#C5221F', borderColor: 'white', }); const marker = new AdvancedMarkerElement({ map, position: destination.location, content: pin.element, title: `Destination: ${destination.displayName}`, }); markers.push(marker); bounds.extend(destination.location); } } // Fit the map to the bounds of all markers. map.fitBounds(bounds); } initMap();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ /* Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #container { height: 100%; display: flex; } #sidebar { flex-basis: 15rem; flex-grow: 1; padding: 1rem; max-width: 30rem; height: 100%; box-sizing: border-box; overflow: auto; } #map { flex-basis: 0; flex-grow: 4; height: 100%; } #sidebar { flex-direction: column; }
HTML
<html>
<head>
<title>Route matrix</title>
<link rel="stylesheet" type="text/css" href="./style.css" />
<script type="module" src="./index.js"></script>
</head>
<body>
<div id="container">
<div id="map"></div>
<div id="sidebar">
<h3 style="flex-grow: 0">Request</h3>
<pre style="flex-grow: 1" id="request"></pre>
<h3 style="flex-grow: 0">Response</h3>
<pre style="flex-grow: 1" id="response"></pre>
</div>
</div>
<!-- prettier-ignore -->
<script>(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: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "beta"});</script>
</body>
</html>Попробуйте образец
Ограничения на запросы
Метод computeRouteMatrix устанавливает следующие ограничения на количество запросов для путевых точек, использующих экземпляры address или Place, а также для элементов. Элементы — это маршруты между каждой точкой отправления и точкой назначения в матрице маршрутов, поэтому количество элементов равно количеству точек отправления, умноженному на количество точек назначения. Например, если у вас 10 точек отправления и 10 точек назначения, у вас будет 100 элементов:
- Количество товаров не может превышать 625 для маршрутов, не являющихся
TRANSIT. - Если вы указываете маршрут
TRANSIT, количество товаров не может превышать 100. - Если указать
TRAFFIC_AWARE_OPTIMAL, количество элементов не может превышать 100. - Если вы указываете пункты отправления или назначения с помощью адресов или экземпляров Place , вы можете указать таким образом до 50 пунктов.
Для получения дополнительной информации см. раздел «Получить маршрут общественного транспорта» .
Пример запроса матрицы маршрутов
В следующем примере показан вызов ComputeRouteMatrixRequest . В этом примере выполняются следующие действия:
- В примере задается массив из двух начальных и двух конечных путевых точек. Метод вычисляет маршрут от каждой начальной точки до каждой конечной точки, поэтому в ответе содержится четыре маршрута.
В массиве первый элемент имеет индекс 0, второй — индекс 1 и так далее. - Указывает поля для возврата. В этом примере запрос настроен на возврат
durationMillis,distanceMetersиconditionдля каждого маршрута.
Машинопись
const request = { origins: [origin1, origin2], destinations: [destinationA, destinationB], travelMode: 'DRIVING', units: google.maps.UnitSystem.METRIC, fields: ['distanceMeters', 'durationMillis', 'condition'], };
JavaScript
const request = { origins: [origin1, origin2], destinations: [destinationA, destinationB], travelMode: 'DRIVING', units: google.maps.UnitSystem.METRIC, fields: ['distanceMeters', 'durationMillis', 'condition'], };
В ответе представлены четыре возможных маршрута для комбинации всех начальных и конечных точек, как показано в следующем примере:
"matrix": { "rows": [ { "items": [ { "condition": "ROUTE_EXISTS", "distanceMeters": 202587, "durationMillis": 10040000 }, { "condition": "ROUTE_EXISTS", "distanceMeters": 252734, "durationMillis": 12240000 } ] }, { "items": [ { "condition": "ROUTE_EXISTS", "distanceMeters": 166135, "durationMillis": 6596000 }, { "condition": "ROUTE_EXISTS", "distanceMeters": 216282, "durationMillis": 8797000 } ] } ] }
Для идентификации каждого маршрута в результате используйте индексы начала и конца, чтобы найти соответствующий элемент RouteMatrixItem в двумерном массиве. Например, элемент RouteMatrixItem , описывающий маршрут, рассчитанный от начала с индексом 1 до конца с индексом 0 в запросе, будет находиться во втором элементе массива RouteMatrix.rows и в первом элементе массива RouteMatrixRow.items .
Приведенный ниже фрагмент кода показывает, как идентифицировать объект RouteMatrixItem для поиска маршрута до конкретного пункта отправления и назначения:
// Find the route for origin 'x' and destination 'y'. const {matrix} = await RouteMatrix.computeRouteMatrix(request); const myRouteMatrixItem = matrix.rows[x].items[y];
Выберите поля для возврата
При запросе матрицы маршрутов необходимо использовать маску поля, чтобы указать, какую информацию должен вернуть ответ.
Использование маски поля также гарантирует, что вы не будете запрашивать ненужные данные, что, в свою очередь, помогает уменьшить задержку ответа и избежать возврата информации, которая вашей системе не нужна.
Укажите список необходимых полей, задав свойство ComputeRoutesMatrixRequest.fields , как показано в следующем фрагменте кода:
fields: ['durationMillis', 'distanceMeters', 'condition'],
Определите, какие маски полей следует использовать.
Вот как можно определить, какие поля вы хотите использовать, и создать для них маски полей:
- Запросите все поля, используя маску поля
['*']. - Посмотрите на иерархию полей в классе
RouteMatrixItem, чтобы найти нужные вам поля. Создайте маски полей, используя иерархию полей, показанную на предыдущем шаге, в следующем формате:
topLevelField[.secondLevelField][.thirdLevelField][...]
Например, для этого RouteMatrixItem :
"travelAdvisory": { "fuelConsumptionMicroliters": 0, "tollInfo": { "estimatedPrices": [ { "currencyCode": "USD", "units": 4, "nanos": 400000000 } ] } },
Если вы хотите получить только поле tollInfo для элемента RouteMatrixItem , маска поля будет следующей:
fields: ['travelAdvisory.tollInfo']
Если же вы хотите запросить расчетный расход топлива, ваша полевая маска будет выглядеть следующим образом:
fields: ['travelAdvisory.fuelConsumptionMicroliters']
Если вы хотите запросить оба варианта, ваша маска поля будет следующей:
fields: ['travelAdvisory.fuelConsumptionMicroliters', 'travelAdvisory.tollInfo']
А если вы хотите запросить полный набор рекомендаций для путешественников, ваша защитная маска будет следующей:
fields: ['travelAdvisory']
Запросить матрицу маршрутов общественного транспорта
Получите схему маршрутов общественного транспорта, учитывающую доступные в регионе варианты передвижения. Варианты транспорта могут включать автобусы, метро, поезда и другие. Чтобы запросить схему маршрутов общественного транспорта:
- Установите
travelModeнаTRANSIT - Запросите поле
travelAdvisory.
Узнайте больше о маршрутах общественного транспорта .