Rechercher des points de prise en charge à l'aide de Location Selection (bêta)
Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
const MAPS_API_KEY = ''; // Put your API Key for Maps SDK here
const LS_API_KEY = ''; // Put your API Key for Location Selection APIs here
const MAPS_URL = `https://maps.googleapis.com/maps/api/js?key=${
MAPS_API_KEY}&libraries=places,geometry&callback=initMap`;
const LS_BASE_URL = 'https://locationselection.googleapis.com/v1beta';
const API_URL_PUPS_FOR_PLACE =
`${LS_BASE_URL}:findPickupPointsForPlace?key=${LS_API_KEY}`;
const API_URL_PUPS_FOR_LOCATION =
`${LS_BASE_URL}:findPickupPointsForLocation?key=${LS_API_KEY}`;
const API_URL_NEARBY_PLACES =
`${LS_BASE_URL}:findNearbyPlaces?key=${LS_API_KEY}`;
const FORM_ID_PUPS_FOR_LOCATION = 'form-pups-for-location';
const FORM_ID_PUPS_FOR_PLACE = 'form-pups-for-place';
const FORM_ID_NEARBY_PLACES = 'form-nearby-places';
const FORM_TO_API_URL_MAP = {
[FORM_ID_PUPS_FOR_LOCATION]: API_URL_PUPS_FOR_LOCATION,
[FORM_ID_PUPS_FOR_PLACE]: API_URL_PUPS_FOR_PLACE,
[FORM_ID_NEARBY_PLACES]: API_URL_NEARBY_PLACES,
};
const RED_PIN = 'http://maps.google.com/mapfiles/ms/icons/red-dot.png';
const GREEN_PIN = 'http://maps.google.com/mapfiles/ms/icons/green-dot.png';
const BLUE_PIN = 'http://maps.google.com/mapfiles/ms/icons/blue-dot.png';
const DEFAULT_ZOOM_LEVEL = 18;
// codepoint from https://fonts.google.com/icons
const SEARCH_LOCATION_MARKER = '\ue7f2';
const GOOGLEPLEX = {
lat: 37.422001,
lng: -122.084061
};
let map;
let polyLines = [];
let polygons = [];
let mapMarkers = [];
let entranceMarkers = [];
function loadMap() {
const script = document.createElement('script');
script.src = MAPS_URL;
document.body.appendChild(script);
}
function initMap() {
map = new google.maps.Map(
document.getElementById('map'),
{center: GOOGLEPLEX, zoom: DEFAULT_ZOOM_LEVEL});
}
function setupForm() {
const form = document.getElementsByTagName('form')[0];
form.addEventListener('submit', onFormSubmit);
}
function onFormSubmit(evt) {
evt.preventDefault();
evt.stopPropagation();
const formData = new FormData(evt.target);
fetchAPIResults(formData);
}
function transformFormData(fd) {
let transformedFd = {
localizationPreferences: {},
};
const formId = document.getElementsByTagName('form')[0].id;
if (formId === FORM_ID_PUPS_FOR_LOCATION ||
formId === FORM_ID_PUPS_FOR_PLACE) {
transformedFd = {localizationPreferences: {}, travelModes: []};
}
const addSearchLocation = () => {
if (transformedFd.searchLocation == null) {
transformedFd.searchLocation = {};
}
};
const addDestination = () => {
if (transformedFd.destination == null) {
transformedFd.destination = {};
}
};
fd.forEach((value, key) => {
switch (key) {
case 'travelModes':
transformedFd.travelModes.push(value);
break;
case 'languageCode':
transformedFd.localizationPreferences[key] = value;
break;
case 'regionCode':
transformedFd.localizationPreferences[key] = value;
break;
case 'searchLocation-latitude':
if (value) {
addSearchLocation();
transformedFd.searchLocation['latitude'] = value;
}
break;
case 'searchLocation-longitude':
if (value) {
addSearchLocation();
transformedFd.searchLocation['longitude'] = value;
}
break;
case 'destination-latitude':
if (value) {
addDestination();
transformedFd.destination['latitude'] = value;
}
break;
case 'destination-longitude':
if (value) {
addDestination();
transformedFd.destination['longitude'] = value;
}
break;
default:
transformedFd[key] = value;
break;
}
});
const json = JSON.stringify(transformedFd, undefined, 2);
return json;
}
async function fetchAPIResults(fd) {
const formId = document.getElementsByTagName('form')[0].id;
const url = FORM_TO_API_URL_MAP[formId];
const transformedFd = transformFormData(fd);
const response = await fetch(url, {method: 'POST', body: transformedFd});
const result = await response.json();
// Display JSON
displayAPIResults(result);
// Update map
let searchLocation = {};
if (JSON.parse(transformedFd).searchLocation) {
searchLocation = {
lat: Number(JSON.parse(transformedFd).searchLocation.latitude),
lng: Number(JSON.parse(transformedFd).searchLocation.longitude),
};
}
switch (formId) {
case FORM_ID_PUPS_FOR_PLACE:
markPickupPointsForPlace(result);
break;
case FORM_ID_PUPS_FOR_LOCATION:
markPickupPointsForLocation(result, searchLocation);
break;
case FORM_ID_NEARBY_PLACES:
markNearbyPlaces(result, searchLocation);
break;
default:
break;
}
}
function displayAPIResults(data) {
const output = document.getElementById('output');
output.textContent = JSON.stringify(data, undefined, 2);
}
function markNearbyPlaces(data, searchLocation) {
if (data.error) {
resetMap();
return;
}
const places = [];
for (const placeResult of data.placeResults) {
places.push(placeResult.place);
}
resetMap(searchLocation);
markPlaces(places, searchLocation);
for (const place of places) {
markEntrances(place.associatedCompounds, place);
}
markSearchLocation(searchLocation, '');
for (const place of places) {
mapPolygons(place.associatedCompounds);
}
}
function markPickupPointsForPlace(data) {
if (data.error) {
resetMap();
return;
}
const place = data.placeResult.place;
const pickupPoints = data.pickupPointResults;
const searchLocation = {
lat: place.geometry.location.latitude,
lng: place.geometry.location.longitude
};
resetMap(searchLocation);
markPickupPoints(place, pickupPoints, searchLocation);
markEntrances(place.associatedCompounds, place);
markSearchLocation(searchLocation, place.displayName);
createPolyLinesOneToMany(searchLocation, pickupPoints);
mapPolygons(place.associatedCompounds);
}
function markPickupPointsForLocation(data, searchLocation) {
if (data.error) {
resetMap();
return;
}
const placeIdToPlace = {};
// A dict, and the key is placeId(str)s and the value is a list of pups.
const placePickupPoints = {};
data.placeResults.forEach(result => {
placeIdToPlace[result.place.placeId] = result.place;
placePickupPoints[result.place.placeId] = [];
});
data.placePickupPointResults.forEach(result => {
placePickupPoints[result.associatedPlaceId].push(result.pickupPointResult);
})
resetMap(searchLocation);
for (const placeId in placePickupPoints) {
const place = placeIdToPlace[placeId];
const pups = placePickupPoints[placeId];
markEntrances(place.associatedCompounds, place);
markPickupPoints(place, pups, searchLocation);
createPolyLinesOneToMany(searchLocation, pups);
mapPolygons(place.associatedCompounds);
}
// update the marker rank to global order
for (let i = 0; i < mapMarkers.length; i++) {
mapMarkers[i].label = String(i);
}
markSearchLocation(searchLocation, '');
}
function markPlaces(places, searchLocation) {
for (const place of places) {
const placeLocation = place.geometry.location;
const infoWindow =
new google.maps.InfoWindow({content: createInfoWindow(place, null)});
const marker = new google.maps.Marker({
position: toLatLngLiteral(placeLocation),
animation: google.maps.Animation.DROP,
map: map,
});
marker.addListener('click', () => {
infoWindow.open(map, marker);
});
map.addListener('click', () => {
infoWindow.close();
});
mapMarkers.push(marker);
}
}
function markEntrances(compounds, place) {
if (!compounds) {
return;
}
for (const compound of compounds) {
if (!compound.entrances) {
continue;
}
for (const entrance of compound.entrances) {
const entranceMarker = new google.maps.Marker({
position: toLatLngLiteral(entrance.location),
icon: {
url: BLUE_PIN,
},
animation: google.maps.Animation.DROP,
map: map,
});
const infoWindow =
new google.maps.InfoWindow({content: createInfoWindow(place, null)});
entranceMarker.addListener('click', () => {
infoWindow.open(map, entranceMarker);
});
map.addListener('click', () => {
infoWindow.close();
});
entranceMarkers.push(entranceMarker);
}
}
}
function mapPolygons(many) {
if (!many) {
return;
}
for (const toPoint of many) {
const data = toPoint.geometry.displayBoundary;
if (data == null || data.coordinates == null) {
continue;
}
const value = data.coordinates;
const polyArray = JSON.parse(JSON.stringify(value))[0];
const usedColors = [];
const finalLatLngs = [];
let color = '';
for (let i = 0; i < polyArray.length; ++i) {
if (polyArray[i] != null && polyArray[i].length > 0) {
color = getColor(usedColors);
usedColors.push(color);
if (isArrLatLng(polyArray[i])) {
finalLatLngs.push({lat: polyArray[i][1], lng: polyArray[i][0]});
}
}
}
const poly = new google.maps.Polygon({
strokeColor: color,
strokeOpacity: 0.2,
strokeWeight: 5,
fillColor: color,
fillOpacity: 0.1,
paths: finalLatLngs,
map: map,
});
polygons.push(poly);
}
}
function getColor(usedColors) {
let color = generateStrokeColor();
while (usedColors.includes(color)) {
color = generateStrokeColor();
}
return color;
}
function generateStrokeColor() {
return Math.floor(Math.random() * 16777215).toString(16);
}
function isArrLatLng(currArr) {
if (!currArr || currArr.length !== 2) {
return false;
}
return ((typeof currArr[0]) === 'number') &&
((typeof currArr[1]) === 'number');
}
function toLatLngLiteral(latlng) {
return {lat: latlng.latitude, lng: latlng.longitude};
}
function pickupHasRestrictions(pickupPointData) {
let hasRestrictions = false;
const travelDetails = pickupPointData.travelDetails;
for (let i = 0; i < travelDetails.length; i++) {
if (travelDetails[i].trafficRestriction !== 'NO_RESTRICTION') {
hasRestrictions = true;
}
}
return hasRestrictions;
}
function markPickupPoints(place, pickupPoints, searchLocation) {
for (let i = 0; i < pickupPoints.length; i++) {
const pickupPointData = pickupPoints[i];
const pickupPoint = pickupPoints[i].pickupPoint;
const pupIcon =
pickupHasRestrictions(pickupPointData) ? RED_PIN : GREEN_PIN;
const contentString = createInfoWindow(place, pickupPoint);
const pupInfoWindow = new google.maps.InfoWindow({content: contentString});
const marker = new google.maps.Marker({
position: toLatLngLiteral(pickupPoint.location),
label: {
text: String(i),
fontWeight: 'bold',
fontSize: '20px',
color: '#000'
},
animation: google.maps.Animation.DROP,
map,
icon: {
url: pupIcon,
anchor: new google.maps.Point(14, 43),
labelOrigin: new google.maps.Point(-5, 5)
},
});
marker.addListener('click', () => {
pupInfoWindow.open(map, marker);
});
map.addListener('click', () => {
pupInfoWindow.close();
});
mapMarkers.push(marker);
}
}
function createInfoWindow(place, pickupPoint) {
let result = [];
const addResult = (value, key, map) =>
result.push(`<p><span class="info-label">${key}:</span> ${value}</p>`);
const formatAddress = (address) => address.lines.join(',');
const placeFieldMap = new Map();
if (place !== null) {
placeFieldMap.set('Place', '');
placeFieldMap.set('Name', place.displayName);
placeFieldMap.set('Place ID', place.placeId);
placeFieldMap.set('Address', formatAddress(place.address.formattedAddress));
}
const pickupPointFieldMap = new Map();
if (pickupPoint !== null) {
pickupPointFieldMap.set('Pickup point', '');
pickupPointFieldMap.set('Name', pickupPoint.displayName);
}
placeFieldMap.forEach(addResult);
result.push('<hr/>');
pickupPointFieldMap.forEach(addResult);
return result.join('');
}
function markSearchLocation(location, label) {
const infoWindow =
new google.maps.InfoWindow({content: `<p><b>Name: </b>${label}</p>`});
const marker = new google.maps.Marker({
position: location,
map,
label: {
text: SEARCH_LOCATION_MARKER,
fontFamily: 'Material Icons',
color: '#ffffff',
fontSize: '18px',
fontWeight: 'bold',
},
});
marker.addListener('click', () => {
infoWindow.open(map, marker);
});
map.addListener('click', () => {
infoWindow.close();
});
mapMarkers.push(marker);
}
function createPolyLinesOneToMany(one, many) {
const lineSymbol = {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
};
for (const toPoint of many) {
const line = new google.maps.Polyline({
path: [one, toLatLngLiteral(toPoint.pickupPoint.location)],
icons: [
{
icon: lineSymbol,
offset: '100%',
},
],
map: map,
});
polyLines.push(line);
}
}
/******* Reset the map ******/
function deleteMarkers() {
for (const mapMarker of mapMarkers) {
mapMarker.setMap(null);
}
mapMarkers = [];
}
function deletePolyLines() {
for (const polyLine of polyLines) {
polyLine.setMap(null);
}
polyLines = [];
}
function deleteEntranceMarkers() {
for (const entranceMarker of entranceMarkers) {
entranceMarker.setMap(null);
}
entranceMarkers = [];
}
function clearPolygons() {
for (let i = 0; i < polygons.length; i++) {
polygons[i].setMap(null);
}
polygons = [];
}
function resetMap(searchLocation) {
if (searchLocation) {
map.setCenter(searchLocation);
} else {
map.setCenter(GOOGLEPLEX);
}
map.setZoom(DEFAULT_ZOOM_LEVEL);
deleteMarkers();
deletePolyLines();
deleteEntranceMarkers();
clearPolygons();
}
// Initiate map & set form event handlers
loadMap();
setupForm();
Avant d'utiliser l'API Location Selection pour rechercher des points de prise en charge de trajets, suivez les instructions
d'intégration à la bibliothèque cliente.
Le service Location Selection fournit trois API pour la sélection des points de prise en charge et de dépose : FindNearbyPlaces, FindPickupPointsForPlace et FindPickupPointsForLocation.
Utilisez FindNearbyPlaces pour récupérer les lieux à proximité de la recherche ou de la position de l'appareil. Les lieux sont classés par proximité de l'emplacement et par importance pour le covoiturage. FindNearbyPlaces renvoie une liste de lieux qui peuvent être affichés pour permettre à l'utilisateur de faire le meilleur choix. Une fois un lieu sélectionné, utilisez FindPickupPointsForPlace pour récupérer les points de prise en charge de ce lieu.
Utilisez FindPickupPointsForLocation pour récupérer les lieux et leurs points de prise en charge associés à proximité de la recherche ou de la position de l'appareil dans le même appel RPC.
Chaque point de prise en charge est associé à un lieu. Les points de prise en charge sont classés par proximité de l'emplacement et par importance pour le covoiturage. Notez que les points de prise en charge de plusieurs lieux sont classés ensemble. FindPickupPointsForLocation combine FindNearbyPlaces et FindPickupPointsForPlace. Supposons, par exemple, que le lieu de la requête se trouve à proximité des lieux P1, P2 et P3. Si le meilleur point de prise en charge T1 est associé au lieu P2 et que le point de prise en charge suivant est associé au lieu P1, les résultats seront classés comme suit : [T1:P2, T2:P1, ...].
Si vous préférez afficher les lieux à l'utilisateur avant qu'il ne sélectionne les points de prise en charge, ou afficher les lieux à proximité en faisant glisser un repère, utilisez l'appel RPC suivant :
FindNearbyPlacesRequest find_nearby_places_request =
FindNearbyPlacesRequest.newBuilder()
.setLocalizationPreferences(LocalizationPreferences.newBuilder()
// Language used for localizing text such as name or address.
.setLanguageCode("en")
.setRegionCode("US")
.build())
// Rider's location or location of dragged pin.
.setSearchLocation(LatLng.newBuilder().setLatitude(37.365647).setLongitude(-121.925356))
// Number of places requested.
.setMaxResults(3)
.build();
FindNearbyPlacesResponse findNearbyPlacesResponse =
locationSelectionBetaClient.findNearbyPlaces(find_nearby_places_request);
L'appel RPC renvoie une liste classée de réponses de lieux qui répondent aux critères d'entrée, classées selon une combinaison de proximité et d'importance. Vous pouvez laisser le passager choisir un lieu ou utiliser le premier résultat et passer à la sélection du point de prise en charge. Chaque réponse de lieu possède un place_id unique qui peut être utilisé dans FindPickupPointsForPlaceRequest pour récupérer les points de prise en charge. Pour en savoir plus,
consultez Rechercher par ID de lieu.
FindPickupPointsForLocationRequest FindPickupPointsForLocationRequest =
FindPickupPointsForLocationRequest.newBuilder()
// Language used for localizing text such as name and address.
.setLocalizationPreferences(LocalizationPreferences.newBuilder().setRegionCode("US").setLanguageCode("en"))
// The search location of the rider or the dropped pin.
.setSearchLocation(LatLng.newBuilder().setLatitude(-23.482049).setLongitude(-46.602135))
// The max results returned.
.setMaxResults(5)
// List of travel modes. At least one of the travel modes must be supported by the pickup points.
.addTravelModes(TravelMode.DRIVING)
// Specifies the sorting order of matching pickup points.
.setOrderBy(PickupPointOrder.DISTANCE_FROM_SEARCH_LOCATION)
.build();
FindPickupPointsForLocationResponse FindPickupPointsForLocationResponse =
locationSelectionService.FindPickupPointsForLocation(
RpcClientContext.create(), FindPickupPointsForLocationRequest);
L'appel RPC renvoie une liste classée de points de prise en charge qui répondent aux critères d'entrée, classés selon une combinaison de proximité et d'importance. Cet appel RPC combine FindNearbyPlaces et FindPickupPointsForPlaceRequest, et peut être utilisé à la place des deux autres appels.
Rechercher par ID de lieu
Vous pouvez obtenir un place_id à l'aide de FindNearbyPlaces ou du service Autocomplete de l'API Places. Utilisez ensuite l'appel RPC suivant pour fournir des points de prise en charge optimaux pour le lieu spécifié :
FindPickupPointsForPlaceRequest findPickupPointsForPlaceRequest =
FindPickupPointsForPlaceRequest.newBuilder()
// Language used for localizing text such as name and address.
.setLocalizationPreferences(LocalizationPreferences.newBuilder().setRegionCode("US").setLanguageCode("en"))
// Place ID of the place for which pickup points are being fetched;
// for example, Hilton Hotel, Downtown San Jose.
.setPlaceId("ChIJwTUa-q_Mj4ARff4yludGH-M")
// List of travel modes. At least one of the travel modes must be supported by the pickup points.
.addTravelModes(TravelMode.DRIVING)
// Rider's location or location of dragged pin.
// It is recommended to use the same location that was used in `FindNearbyPlaces` for better quality.
.setSearchLocation(LatLng.newBuilder().setLatitude(37.329472).setLongitude(-121.890449))
.setOrderBy(PickupPointOrder.DISTANCE_FROM_SEARCH_LOCATION)
.setMaxResults(5)
.build();
FindPickupPointsForPlaceResponse findPickupPointsForPlaceResponse =
locationSelectionBetaClient.findPickupPointsForPlace(findPickupPointsForPlaceRequest);
FindPickupPointsForPlace renvoie des PickupPointResponses avec la latitude et la longitude des points où un passager peut être pris en charge.
Optimiser les prises en charge pour plusieurs trajets
Pour les trajets partagés ou consécutifs, FindPickupPointsForPlace permet de classer les points de prise en charge par DRIVING_ETA_FROM_PICKUP_POINT_TO_DESTINATION. Vous pouvez ainsi renvoyer un point de prise en charge pour le trajet suivant, optimisé en fonction de l'itinéraire actuel du conducteur.
Exemple
FindPickupPointsForPlaceRequest findPickupPointsForPlaceRequest =
FindPickupPointsForPlaceRequest.newBuilder()
// Language used for localizing text such as name and address.
.setLocalizationPreferences(LocalizationPreferences.newBuilder().setRegionCode("US").setLanguageCode("en"))
// Place ID of the place for which pickup points are being fetched;
// for example, Hilton Hotel, Downtown San Jose.
.setPlaceId("ChIJwTUa-q_Mj4ARff4yludGH-M")
// List of travel modes. At least one of the travel modes must be supported by the pickup points.
.addTravelModes(TravelMode.DRIVING)
// Second rider's location or location of dragged pin.
.setSearchLocation(LatLng.newBuilder().setLatitude(37.329472).setLongitude(-121.890449))
// Location of the driver's next drop off after picking up the second
// rider. Note, it is not necessarily the second rider's destination.
.setDestination(LatLng.newBuilder().setLatitude(37.329472).setLongitude(-121.890449))
.setOrderBy(PickupPointOrder.DRIVING_ETA_FROM_PICKUP_POINT_TO_DESTINATION)
.setComputeDrivingEta(true)
.setMaxResults(5)
.build();
FindPickupPointsForPlaceResponse findPickupPointsForPlaceResponse =
locationSelectionBetaClient.findPickupPointsForPlace(findPickupPointsForPlaceRequest);
Afficher les contours, les entrées et les sorties des bâtiments
Dans le message de réponse proto du lieu, le
associatedCompounds
champ identifie les composés associés au lieu. Le message composé contient trois types d'informations :
Type de composé : l'une des quatre options
compoundBuilding : un bâtiment autonome unique, tel qu'un centre commercial ou un
supermarché.
compoundSection : un composé au sein d'un composé plus grand, tel qu'un seul
magasin dans un centre commercial.
compoundGrounds : tout ce qui est associé à un compoundBuilding,
tel qu'un centre commercial, son parking et tout autre bâtiment
situé dans ce parking.
unrecognized : la valeur par défaut
Géométrie : les coordonnées du polygone délimité, stockées dans une structure GeoJSON dans le champ displayBoundary. Ces coordonnées sont utilisées pour construire le contour de la section, du bâtiment ou du terrain.
Entrées : les coordonnées de latitude et de longitude de toutes les entrées et sorties trouvées.
Location Selection renvoie n'importe quel type de composé associé au lieu de recherche. Si le lieu de recherche se trouve dans un magasin particulier d'
un centre commercial, Location Selection renvoie :
* le magasin spécifique, ses entrées et sorties, et son contour
* le bâtiment composé (le centre commercial), ses entrées et sorties, et son contour
* le terrain composé (le centre commercial + le parking), ses entrées et sorties, et le contour de l'ensemble du terrain
Cette image montre les trois types de composés renvoyés.
Cette image montre plusieurs lieux à l'intérieur d'un aéroport, avec la limite d'un bâtiment de l'aéroport et la limite de l'aéroport et de tous ses terrains associés.
Sauf indication contraire, le contenu de cette page est régi par une licence Creative Commons Attribution 4.0, et les échantillons de code sont régis par une licence Apache 2.0. Pour en savoir plus, consultez les Règles du site Google Developers. Java est une marque déposée d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2026/05/20 (UTC).
[[["Facile à comprendre","easyToUnderstand","thumb-up"],["J'ai pu résoudre mon problème","solvedMyProblem","thumb-up"],["Autre","otherUp","thumb-up"]],[["Il n'y a pas l'information dont j'ai besoin","missingTheInformationINeed","thumb-down"],["Trop compliqué/Trop d'étapes","tooComplicatedTooManySteps","thumb-down"],["Obsolète","outOfDate","thumb-down"],["Problème de traduction","translationIssue","thumb-down"],["Mauvais exemple/Erreur de code","samplesCodeIssue","thumb-down"],["Autre","otherDown","thumb-down"]],["Dernière mise à jour le 2026/05/20 (UTC)."],[],["This application uses Google Maps and Location Selection APIs to display location data. Users input details like `placeId`, language/region codes, and coordinates to find pickup points. The form data is transformed into JSON and sent to the APIs. Results are displayed both as raw JSON and visually on a map. The map shows markers for places, pickup points, entrances, and polylines connecting locations and polygons for compound boundaries. Users can interact with markers to view info windows. It uses javascript functions for each action in order to process and display the results.\n"]]