כדי ליצור סמנים לציוני דרך במסלול, קוראים ל-createWaypointAdvancedMarkers().
כברירת מחדל, הפונקציה createWaypointAdvancedMarkers() יוצרת סמנים למסלול עם התוויות 'A', 'B', 'C' וכו' לכל נקודת ציון. אפשר להתאים אישית את הסמנים עוד יותר על ידי העברת אפשרויות לשינוי הסגנון של הסמן על סמך אינדקס הסמן או המאפיינים של RouteLeg.
קוד מקור מלא לדוגמה
בדוגמת הקוד הבאה מוצג איך ליצור סמנים מותאמים אישית לנקודות ציון במסלול.
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>הוספת סמנים שמוגדרים כברירת מחדל
כדי להוסיף סמנים באמצעות סגנון ברירת המחדל, קוראים ל-createWaypointAdvancedMarkers() ומעבירים אפשרות סמן כדי לציין את המפה הנוכחית, כמו בקטע הקוד הבא.
// Create markers using default style. const markers = await result.routes[0].createWaypointAdvancedMarkers({ map: innerMap });
הוספת סמנים עם סגנון אישי
כדי להוסיף סמנים באמצעות סגנון אישי, קוראים ל-createWaypointAdvancedMarkers()
ומעבירים אפשרויות סמן שכוללות מאפייני סגנון אישי. כשמחילים סגנונות בצורה הזו,
כל הסמנים מקבלים את אותו הסגנון. בקטע הקוד הבא אפשר לראות איך יוצרים סמנים עם סגנון אישי.
// 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);
החלת סגנון מותאם אישית על סמנים ספציפיים
כדי להחיל סגנון אישי על סמנים בודדים, מעבירים פונקציה אל createWaypointAdvancedMarkers()
כדי להגדיר אפשרויות סגנון של סמנים על סמך אינדקס הסמן או מאפייני RouteLeg.
בקטע הקוד הבא מוצגת פונקציה ליצירת סמנים ולעיצוב שלהם על סמך אינדקס הסמנים:
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);
הגדרת נגישות לסמנים
כדי לשפר את הנגישות של הסמנים, אפשר:
- הוספת כותרת: מגדירים את המאפיין
titleבאפשרויות של הסמן כדי לספק תווית לסמן. התווית הזו משמשת קוראי מסך וטכנולוגיות מסייעות. - הבחנה בין נקודות ציון ביניים: כשמעבירים פונקציית סגנון אל
createWaypointAdvancedMarkers(), משתמשים בפרמטריםindexו-totalMarkersמ-WaypointMarkerDetailsכדי להקצות שמות ותוויות ייחודיים ותיאוריים לנקודות ציון ביניים (לדוגמה,Waypoint ${(index + 1).toString()}), כך שמשתמשים בקורא מסך יוכלו להבחין ביניהן לבין נקודת המוצא והיעד. - הפעלת ניווט במקלדת ואירועי קליק: מגדירים את האפשרות
gmpClickable: trueבאפשרויות הסמן כדי לאפשר התמקדות בסמנים אינטראקטיביים באמצעות המקלדת (באמצעות מקש Tab ומקשי החיצים) וכדי לאפשר להם להגיב לקלט מהמקלדת ומהעכבר. - הגדלת הגודל של סמן: מגדירים את המאפיין
scaleב-PinElement(לדוגמה,scale: 1.5) כדי לצמצם את רמת הדיוק שנדרשת לאינטראקציה עם סמנים, במיוחד במכשירים עם מסך מגע. סמני ברירת המחדל עומדים בתקן של גודל מינימלי לפי WCAG AA, והגדלת קנה המידה עוזרת לעמוד בתקן של גודל יעד לפי WCAG AAA. - שמירה על ניגודיות בין הצבעים: כשמתאימים אישית את הצבעים של
PinElement, צריך לבחור ערכים שלglyphColorושלbackgroundעם ניגודיות מספקת כדי שתוויות נקודות הציון יישארו קריאות.
בקטע הקוד הבא מוצג איך מעצבים סמן לנגישות. יש לו title כדי לספק תווית לקוראי מסך. הכותרת משתמשת באינדקס כדי להבדיל בין נקודות ציון ביניים. המאפיין gmpClickable מוגדר לערך
true כדי להפעיל ניווט במקלדת ואירועי קליקים, והערך של scale
הוגדל כדי להקל על האינטראקציה עם הסמנים.
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 }), }; }
פרטים נוספים זמינים במאמר הוספת אפשרות ללחיצה על סמנים והנגשתם.
דוגמה מלאה
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>