Crea marcadores para las paradas de la ruta llamando a createWaypointAdvancedMarkers().
De forma predeterminada, createWaypointAdvancedMarkers() crea marcadores para la ruta etiquetada como "A", "B", "C", etcétera, para cada punto de referencia. Puedes personalizar aún más los marcadores pasando opciones para modificar el diseño del marcador según el índice o las propiedades del RouteLeg correspondiente.
Consulta el ejemplo de código fuente completo
En la siguiente muestra de código, se muestra cómo crear marcadores personalizados para los puntos de referencia de la ruta.
TypeScript
let mapPolylines: google.maps.Polyline[] = []; const mapElement = document.querySelector('gmp-map')!; let innerMap: google.maps.Map; // Initialize and add the map. async function init() { // Request the needed libraries. const [{ event }] = await Promise.all([ google.maps.importLibrary('core'), google.maps.importLibrary('maps'), ]); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, mapId: 'DEMO_MAP_ID', }); // Call the function after the map is loaded. event.addListenerOnce(innerMap, 'idle', () => { void getDirections(); }); } async function getDirections() { // Request the needed libraries. const [{ Route }, { PinElement }] = await Promise.all([ google.maps.importLibrary('routes'), google.maps.importLibrary('marker'), ]); // Define routes request with an intermediate stop. const request: google.maps.routes.ComputeRoutesRequest = { origin: 'Parking lot, Christmas Tree Point Rd, San Francisco, CA 94131', destination: '100 Spinnaker Dr, Sausalito, CA 94965', // We're having a yummy lunch! intermediates: [{ location: '300 Finley Rd San Francisco, CA 94129' }], // But first, we golf! travelMode: 'DRIVING', fields: ['path', 'legs', 'viewport'], }; // Call computeRoutes to get the directions. const result = await Route.computeRoutes(request); if (!result.routes || result.routes.length === 0) { console.warn('No routes found'); return; } // Alter style based on marker index. function markerOptionsMaker( defaultOptions: google.maps.marker.AdvancedMarkerElementOptions, waypointMarkerDetails: google.maps.routes.WaypointMarkerDetails ) { const { index, totalMarkers } = waypointMarkerDetails; // Style the origin waypoint. if (index === 0) { return { ...defaultOptions, title: 'Origin', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'green', borderColor: 'green', scale: 1.5, }), }; } // Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; } // Style the destination waypoint. if (index === totalMarkers - 1) { return { ...defaultOptions, title: 'Destination', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'red', borderColor: 'red', scale: 1.5, }), }; } return { ...defaultOptions, map: innerMap }; } await result.routes[0].createWaypointAdvancedMarkers(markerOptionsMaker); // Fit the map to the route. innerMap.fitBounds(result.routes[0].viewport!); innerMap.setHeading(270); // Create polylines and add them to the map. mapPolylines = result.routes[0].createPolylines(); mapPolylines.forEach((polyline) => { polyline.setMap(innerMap); }); } void init();
JavaScript
let mapPolylines = []; const mapElement = document.querySelector('gmp-map'); let innerMap; // Initialize and add the map. async function init() { // Request the needed libraries. const [{ event }] = await Promise.all([ google.maps.importLibrary('core'), google.maps.importLibrary('maps'), ]); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, mapId: 'DEMO_MAP_ID', }); // Call the function after the map is loaded. event.addListenerOnce(innerMap, 'idle', () => { void getDirections(); }); } async function getDirections() { // Request the needed libraries. const [{ Route }, { PinElement }] = await Promise.all([ google.maps.importLibrary('routes'), google.maps.importLibrary('marker'), ]); // Define routes request with an intermediate stop. const request = { origin: 'Parking lot, Christmas Tree Point Rd, San Francisco, CA 94131', destination: '100 Spinnaker Dr, Sausalito, CA 94965', // We're having a yummy lunch! intermediates: [{ location: '300 Finley Rd San Francisco, CA 94129' }], // But first, we golf! travelMode: 'DRIVING', fields: ['path', 'legs', 'viewport'], }; // Call computeRoutes to get the directions. const result = await Route.computeRoutes(request); if (!result.routes || result.routes.length === 0) { console.warn('No routes found'); return; } // Alter style based on marker index. function markerOptionsMaker(defaultOptions, waypointMarkerDetails) { const { index, totalMarkers } = waypointMarkerDetails; // Style the origin waypoint. if (index === 0) { return { ...defaultOptions, title: 'Origin', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'green', borderColor: 'green', scale: 1.5, }), }; } // Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; } // Style the destination waypoint. if (index === totalMarkers - 1) { return { ...defaultOptions, title: 'Destination', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'red', borderColor: 'red', scale: 1.5, }), }; } return { ...defaultOptions, map: innerMap }; } await result.routes[0].createWaypointAdvancedMarkers(markerOptionsMaker); // Fit the map to the route. innerMap.fitBounds(result.routes[0].viewport); innerMap.setHeading(270); // Create polylines and add them to the map. mapPolylines = result.routes[0].createPolylines(); mapPolylines.forEach((polyline) => { polyline.setMap(innerMap); }); } void init();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; }
HTML
<html>
<head>
<title>Get directions</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="37.447646, -122.113878" zoom="12"></gmp-map>
</body>
</html>Cómo agregar marcadores predeterminados
Para agregar marcadores con el diseño predeterminado, llama a createWaypointAdvancedMarkers() pasando una opción de marcador para especificar el mapa actual, como se muestra en el siguiente fragmento de código.
// Create markers using default style. const markers = await result.routes[0].createWaypointAdvancedMarkers({ map: innerMap });
Agrega marcadores con un estilo personalizado
Para agregar marcadores con un estilo personalizado, llama a createWaypointAdvancedMarkers() y pasa opciones de marcadores que incluyan propiedades de estilo personalizadas. Cuando aplicas estilos como este, todos los marcadores se diseñan de la misma manera. En el siguiente fragmento de código, se muestra cómo crear marcadores con un estilo personalizado.
// Create markers with a custom style. const markerOptions = { map: innerMap, content: new PinElement({ scale: 1.5, background: '#8C0DD1', borderColor: '#6D0AA5', glyphColor: '#6D0AA5', }).element } const markers = await result.routes[0].createWaypointAdvancedMarkers(markerOptions);
Cómo aplicar un estilo personalizado a marcadores individuales
Para aplicar un estilo personalizado a marcadores individuales, pasa una función a createWaypointAdvancedMarkers() para establecer opciones de estilo de marcadores basadas en el índice del marcador o en las propiedades de RouteLeg.
En el siguiente fragmento de código, se muestra una función para crear marcadores y aplicarles un diseño según el índice del marcador:
TypeScript
// Alter style based on marker index. function markerOptionsMaker( defaultOptions: google.maps.marker.AdvancedMarkerElementOptions, waypointMarkerDetails: google.maps.routes.WaypointMarkerDetails ) { const { index, totalMarkers } = waypointMarkerDetails; // Style the origin waypoint. if (index === 0) { return { ...defaultOptions, title: 'Origin', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'green', borderColor: 'green', scale: 1.5, }), }; } // Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; } // Style the destination waypoint. if (index === totalMarkers - 1) { return { ...defaultOptions, title: 'Destination', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'red', borderColor: 'red', scale: 1.5, }), }; } return { ...defaultOptions, map: innerMap }; } await result.routes[0].createWaypointAdvancedMarkers(markerOptionsMaker);
JavaScript
// Alter style based on marker index. function markerOptionsMaker(defaultOptions, waypointMarkerDetails) { const { index, totalMarkers } = waypointMarkerDetails; // Style the origin waypoint. if (index === 0) { return { ...defaultOptions, title: 'Origin', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'green', borderColor: 'green', scale: 1.5, }), }; } // Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; } // Style the destination waypoint. if (index === totalMarkers - 1) { return { ...defaultOptions, title: 'Destination', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'red', borderColor: 'red', scale: 1.5, }), }; } return { ...defaultOptions, map: innerMap }; } await result.routes[0].createWaypointAdvancedMarkers(markerOptionsMaker);
Cómo hacer que los marcadores sean accesibles
Puedes mejorar la accesibilidad de los marcadores de las siguientes maneras:
- Proporciona un título: Establece la propiedad
titleen las opciones del marcador para proporcionar una etiqueta para el marcador. Los lectores de pantalla y las tecnologías de asistencia usan esta etiqueta. - Distingue los puntos de ruta intermedios: Cuando pases una función de diseño a
createWaypointAdvancedMarkers(), usa los parámetrosindexytotalMarkersdeWaypointMarkerDetailspara asignar títulos y etiquetas únicos y descriptivos a los puntos de ruta intermedios (por ejemplo,Waypoint ${(index + 1).toString()}) de modo que los usuarios de lectores de pantalla puedan distinguirlos del origen y el destino. - Habilita la navegación con el teclado y los eventos de clic: Configura
gmpClickable: trueen las opciones del marcador para que los marcadores interactivos se puedan enfocar con el teclado (con las teclas Tab y de flecha) y puedan responder a las entradas del teclado y el mouse. - Aumenta el tamaño del marcador: Establece la propiedad
scaleenPinElement(por ejemplo,scale: 1.5) para reducir la precisión necesaria para interactuar con los marcadores, en especial en dispositivos de pantalla táctil. Los marcadores predeterminados cumplen con el estándar de tamaño mínimo AA de WCAG, y aumentar la escala ayuda a cumplir con el estándar de tamaño objetivo AAA de WCAG. - Mantén el contraste de color: Cuando personalices los colores de
PinElement, elige valores deglyphColorybackgroundcon suficiente contraste para que las etiquetas de los puntos de referencia sigan siendo legibles.
En el siguiente fragmento de código, se muestra cómo aplicar un diseño a un marcador para que sea accesible. Tiene un title para proporcionar una etiqueta para los lectores de pantalla. El título usa el índice para distinguir los puntos de referencia intermedios. La propiedad gmpClickable se establece en true para habilitar la navegación con el teclado y los eventos de clic, y se aumentó scale para que sea más fácil interactuar con los marcadores.
TypeScript
// Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; }
JavaScript
// Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; }
Para obtener más detalles, consulta Cómo configurar los marcadores para que sean accesibles y permitan la posibilidad de hacer clics.
Ver el ejemplo completo
TypeScript
let mapPolylines: google.maps.Polyline[] = []; const mapElement = document.querySelector('gmp-map')!; let innerMap: google.maps.Map; // Initialize and add the map. async function init() { // Request the needed libraries. const [{ event }] = await Promise.all([ google.maps.importLibrary('core'), google.maps.importLibrary('maps'), ]); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, mapId: 'DEMO_MAP_ID', }); // Call the function after the map is loaded. event.addListenerOnce(innerMap, 'idle', () => { void getDirections(); }); } async function getDirections() { // Request the needed libraries. const [{ Route }, { PinElement }] = await Promise.all([ google.maps.importLibrary('routes'), google.maps.importLibrary('marker'), ]); // Define routes request with an intermediate stop. const request: google.maps.routes.ComputeRoutesRequest = { origin: 'Parking lot, Christmas Tree Point Rd, San Francisco, CA 94131', destination: '100 Spinnaker Dr, Sausalito, CA 94965', // We're having a yummy lunch! intermediates: [{ location: '300 Finley Rd San Francisco, CA 94129' }], // But first, we golf! travelMode: 'DRIVING', fields: ['path', 'legs', 'viewport'], }; // Call computeRoutes to get the directions. const result = await Route.computeRoutes(request); if (!result.routes || result.routes.length === 0) { console.warn('No routes found'); return; } // Alter style based on marker index. function markerOptionsMaker( defaultOptions: google.maps.marker.AdvancedMarkerElementOptions, waypointMarkerDetails: google.maps.routes.WaypointMarkerDetails ) { const { index, totalMarkers } = waypointMarkerDetails; // Style the origin waypoint. if (index === 0) { return { ...defaultOptions, title: 'Origin', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'green', borderColor: 'green', scale: 1.5, }), }; } // Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; } // Style the destination waypoint. if (index === totalMarkers - 1) { return { ...defaultOptions, title: 'Destination', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'red', borderColor: 'red', scale: 1.5, }), }; } return { ...defaultOptions, map: innerMap }; } await result.routes[0].createWaypointAdvancedMarkers(markerOptionsMaker); // Fit the map to the route. innerMap.fitBounds(result.routes[0].viewport!); innerMap.setHeading(270); // Create polylines and add them to the map. mapPolylines = result.routes[0].createPolylines(); mapPolylines.forEach((polyline) => { polyline.setMap(innerMap); }); } void init();
JavaScript
let mapPolylines = []; const mapElement = document.querySelector('gmp-map'); let innerMap; // Initialize and add the map. async function init() { // Request the needed libraries. const [{ event }] = await Promise.all([ google.maps.importLibrary('core'), google.maps.importLibrary('maps'), ]); innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, mapId: 'DEMO_MAP_ID', }); // Call the function after the map is loaded. event.addListenerOnce(innerMap, 'idle', () => { void getDirections(); }); } async function getDirections() { // Request the needed libraries. const [{ Route }, { PinElement }] = await Promise.all([ google.maps.importLibrary('routes'), google.maps.importLibrary('marker'), ]); // Define routes request with an intermediate stop. const request = { origin: 'Parking lot, Christmas Tree Point Rd, San Francisco, CA 94131', destination: '100 Spinnaker Dr, Sausalito, CA 94965', // We're having a yummy lunch! intermediates: [{ location: '300 Finley Rd San Francisco, CA 94129' }], // But first, we golf! travelMode: 'DRIVING', fields: ['path', 'legs', 'viewport'], }; // Call computeRoutes to get the directions. const result = await Route.computeRoutes(request); if (!result.routes || result.routes.length === 0) { console.warn('No routes found'); return; } // Alter style based on marker index. function markerOptionsMaker(defaultOptions, waypointMarkerDetails) { const { index, totalMarkers } = waypointMarkerDetails; // Style the origin waypoint. if (index === 0) { return { ...defaultOptions, title: 'Origin', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'green', borderColor: 'green', scale: 1.5, }), }; } // Style all intermediate waypoints. if (!(index === 0 || index === totalMarkers - 1)) { return { ...defaultOptions, title: `Waypoint ${(index + 1).toString()}`, // Provide label for screenreaders map: innerMap, gmpClickable: true, // Make marker focusable and allow keyboard navigation content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'blue', borderColor: 'blue', scale: 1.5, // Increase size for better visibilty }), }; } // Style the destination waypoint. if (index === totalMarkers - 1) { return { ...defaultOptions, title: 'Destination', map: innerMap, gmpClickable: true, content: new PinElement({ glyphText: (index + 1).toString(), glyphColor: 'white', background: 'red', borderColor: 'red', scale: 1.5, }), }; } return { ...defaultOptions, map: innerMap }; } await result.routes[0].createWaypointAdvancedMarkers(markerOptionsMaker); // Fit the map to the route. innerMap.fitBounds(result.routes[0].viewport); innerMap.setHeading(270); // Create polylines and add them to the map. mapPolylines = result.routes[0].createPolylines(); mapPolylines.forEach((polyline) => { polyline.setMap(innerMap); }); } void init();
CSS
/* * Always set the map height explicitly to define the size of the div element * that contains the map. */ #map { height: 100%; } /* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; }
HTML
<html>
<head>
<title>Get directions</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="37.447646, -122.113878" zoom="12"></gmp-map>
</body>
</html>