בדף הזה מתוארים אירועים בממשק המשתמש ואירועי שגיאה שאפשר להאזין להם ולטפל בהם באופן פרוגרמטי.
אירועים בממשק המשתמש
JavaScript בדפדפן מבוסס על אירועים, כלומר, JavaScript מגיב לאינטראקציות על ידי יצירת אירועים, ומצפה מתוכנית להאזין לאירועים מעניינים. יש שני סוגים של אירועים:
- אירועי משתמשים (כמו אירועי עכבר מסוג click) מועברים מ-DOM אל Maps JavaScript API. האירועים האלה נפרדים ושונים מאירועי DOM רגילים.
- ההתראות על שינוי מצב ב-MVC משקפות שינויים באובייקטים של Maps JavaScript API, והשמות שלהן נקבעים לפי מוסכמת
property_changed.
כל אובייקט ב-Maps JavaScript API מייצא מספר אירועים עם שמות.
תוכניות שמתעניינות באירועים מסוימים ירשמו מאזיני אירועים ב-JavaScript לאירועים האלה ויפעילו קוד כשהאירועים האלה יתקבלו על ידי קריאה ל-addListener() כדי לרשום גורמים מטפלים באירועים באובייקט.
בדוגמה הבאה מוצגים האירועים שמופעלים על ידי google.maps.Map
כשמבצעים אינטראקציה עם המפה.
רשימה מלאה של האירועים מופיעה בחומר העזר בנושא Maps JavaScript API. האירועים מופיעים בקטע נפרד לכל אובייקט שמכיל אירועים.
אירועים בממשק המשתמש
חלק מהאובייקטים ב-Maps JavaScript API מיועדים להגיב לאירועים של משתמשים, כמו אירועים של עכבר או מקלדת. לדוגמה, אלה כמה אירועים של משתמשים שאובייקט google.maps.marker.AdvancedMarkerElement יכול להאזין להם:
'click''drag''dragend''dragstart''gmp-click'
הרשימה המלאה מופיעה בסוג AdvancedMarkerElement. יכול להיות שהאירועים האלה ייראו כמו אירועי DOM רגילים, אבל הם למעשה חלק מ-Maps JavaScript API. דפדפנים שונים מיישמים מודלים שונים של אירועי DOM, ולכן ממשק ה-API של JavaScript במפות Google מספק את המנגנונים האלה להאזנה לאירועי DOM ולתגובה להם, בלי צורך לטפל במוזרויות השונות של דפדפנים שונים. בדרך כלל האירועים האלה מעבירים גם ארגומנטים בתוך האירוע, שמציינים מצב מסוים של ממשק המשתמש (כמו מיקום העכבר).
שינויים במצב של MVC
אובייקטים של MVC בדרך כלל מכילים מצב. בכל פעם שמשתנה מאפיין של אובייקט,
ממשק API של JavaScript במפות Google יפעיל אירוע שהמאפיין השתנה.
לדוגמה, ה-API יפעיל אירוע zoom_changed במפה כשמשנים את רמת הזום של המפה. אפשר ליירט את שינויי המצב האלה על ידי קריאה ל-addListener() כדי לרשום גם את מטפלי האירועים באובייקט.
אירועים של משתמשים ושינויים במצב של MVC עשויים להיראות דומים, אבל צריך להתייחס אליהם באופן שונה בקוד. לדוגמה, אירועי MVC לא מעבירים ארגומנטים בתוך האירוע. בודקים את המאפיין שהשתנה בשינוי מצב של MVC על ידי קריאה למתודה המתאימה getProperty באובייקט הזה.
טיפול באירועים
כדי להירשם לקבלת התראות לגבי אירועים, משתמשים ב-גורם מטפל באירועים addListener(). השיטה הזו מקבלת אירוע להאזנה ופונקציה להפעלה כשהאירוע שצוין מתרחש.
דוגמה: אירועים של מפה וסמן
בדוגמה הבאה של קוד יש ערבוב של אירועי משתמשים עם אירועים של שינוי מצב. בדוגמה הזו מצורף גורם מטפל באירועים לסמן שמגדיל את התצוגה של המפה כשלוחצים עליו. בנוסף, הוא מצרף גורם מטפל באירועים למפה כדי לטפל בשינויים בנכס center, ומזיז את המפה חזרה לסמן אחרי 3 שניות מרגע קבלת האירוע center_changed.
TypeScript
async function initMap() { // Request needed libraries. (await google.maps.importLibrary('maps')) as google.maps.MapsLibrary; (await google.maps.importLibrary('marker')) as google.maps.MarkerLibrary; // Retrieve the map element. const mapElement = document.querySelector( 'gmp-map' ) as google.maps.MapElement; // Get the inner map from the map element. const innerMap = mapElement.innerMap; const center = mapElement.center; const marker = new google.maps.marker.AdvancedMarkerElement({ position: center, map: innerMap, title: 'Click to zoom', gmpClickable: true, }); innerMap.addListener('center_changed', () => { // 3 seconds after the center of the map has changed, // pan back to the marker. window.setTimeout(() => { innerMap.panTo(marker.position as google.maps.LatLng); }, 3000); }); // Zoom in when the marker is clicked. marker.addListener('gmp-click', () => { innerMap.setZoom(8); innerMap.setCenter(marker.position as google.maps.LatLng); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. (await google.maps.importLibrary('maps')); (await google.maps.importLibrary('marker')); // Retrieve the map element. const mapElement = document.querySelector('gmp-map'); // Get the inner map from the map element. const innerMap = mapElement.innerMap; const center = mapElement.center; const marker = new google.maps.marker.AdvancedMarkerElement({ position: center, map: innerMap, title: 'Click to zoom', gmpClickable: true, }); innerMap.addListener('center_changed', () => { // 3 seconds after the center of the map has changed, // pan back to the marker. window.setTimeout(() => { innerMap.panTo(marker.position); }, 3000); }); // Zoom in when the marker is clicked. marker.addListener('gmp-click', () => { innerMap.setZoom(8); innerMap.setCenter(marker.position); }); } initMap();
דוגמה לניסיון
טיפ: אם אתם מנסים לזהות שינוי באזור התצוגה, הקפידו להשתמש באירוע הספציפי bounds_changed ולא באירועים המרכיבים zoom_changed ו-center_changed. ממשק API של JavaScript במפות Google מפעיל את האירועים האלה באופן עצמאי, ולכן יכול להיות ש-getBounds() לא ידווח על תוצאות שימושיות עד אחרי שחל שינוי סמכותי באזור התצוגה. אם רוצים getBounds() אחרי אירוע כזה, חשוב להאזין לאירוע bounds_changed במקום זאת.
דוגמה: אירועים של עריכת צורה וגרירה
כשעורכים או גוררים צורה, מופעל אירוע עם השלמת הפעולה. רשימת האירועים וכמה קטעי קוד מופיעים במאמר בנושא צורות.
גישה לארגומנטים באירועים של ממשק המשתמש
אירועים בממשק המשתמש ב-Maps JavaScript API בדרך כלל מעבירים ארגומנט של אירוע, שניתן לגשת אליו באמצעות event listener, וכולל את מצב ממשק המשתמש כשאירוע התרחש. לדוגמה, אירוע בממשק משתמש 'click' בדרך כלל מעביר MouseEvent שמכיל מאפיין latLng שמציין את המיקום במפה שעליו לחצו. חשוב לדעת שההתנהגות הזו ייחודית לאירועים של ממשק המשתמש. שינויים במצב של MVC לא מעבירים ארגומנטים באירועים שלהם.
אפשר לגשת לארגומנטים של האירוע בתוך event listener באותה דרך שבה ניגשים למאפיינים של אובייקט. בדוגמה הבאה מתווסף event listener למפה, ונוצר סמן כשמשתמש לוחץ על המפה במיקום של הקליק.
TypeScript
async function initMap() { // Request needed libraries. await google.maps.importLibrary("maps") as google.maps.MapsLibrary; await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; const mapElement = document.querySelector('gmp-map') as google.maps.MapElement; const innerMap = mapElement.innerMap; innerMap.addListener("click", (e) => { placeMarkerAndPanTo(e.latLng, innerMap); }); } function placeMarkerAndPanTo(latLng: google.maps.LatLng, map: google.maps.Map) { new google.maps.marker.AdvancedMarkerElement({ position: latLng, map: map, }); map.panTo(latLng); } initMap();
JavaScript
async function initMap() { // Request needed libraries. await google.maps.importLibrary("maps"); await google.maps.importLibrary("marker"); const mapElement = document.querySelector('gmp-map'); const innerMap = mapElement.innerMap; innerMap.addListener("click", (e) => { placeMarkerAndPanTo(e.latLng, innerMap); }); } function placeMarkerAndPanTo(latLng, map) { new google.maps.marker.AdvancedMarkerElement({ position: latLng, map: map, }); map.panTo(latLng); } initMap();
דוגמה לניסיון
שימוש ב-Closures ב-Event Listeners
כשמבצעים event listener, לעיתים קרובות כדאי לצרף לאובייקט נתונים פרטיים ונתונים קבועים. JavaScript לא תומך בנתוני מופע 'פרטיים', אבל הוא תומך בסגירות שמאפשרות לפונקציות פנימיות לגשת למשתנים חיצוניים. סגירות שימושיות בתוך מאזיני אירועים כדי לגשת למשתנים שבדרך כלל לא מצורפים לאובייקטים שבהם מתרחשים אירועים.
בדוגמה הבאה נעשה שימוש בסגירת פונקציה (closure) ב-event listener כדי להקצות הודעה סודית לקבוצת סמנים. בלחיצה על כל סמן יוצג חלק מההודעה הסודית, שלא כלולה בסמן עצמו.
TypeScript
async function initMap() { // Request needed libraries. (await google.maps.importLibrary('maps')) as google.maps.MapsLibrary; (await google.maps.importLibrary('marker')) as google.maps.MarkerLibrary; const mapElement = document.querySelector( 'gmp-map' ) as google.maps.MapElement; const innerMap = mapElement.innerMap; const bounds: google.maps.LatLngBoundsLiteral = { north: -25.363882, south: -31.203405, east: 131.044922, west: 125.244141, }; // Display the area between the location southWest and northEast. innerMap.fitBounds(bounds); // Add 5 markers to map at random locations. // For each of these markers, give them a title with their index, and when // they are clicked they should open an infowindow with text from a secret // message. const secretMessages = ['This', 'is', 'the', 'secret', 'message']; const lngSpan = bounds.east - bounds.west; const latSpan = bounds.north - bounds.south; for (let i = 0; i < secretMessages.length; ++i) { const marker = new google.maps.marker.AdvancedMarkerElement({ position: { lat: bounds.south + latSpan * Math.random(), lng: bounds.west + lngSpan * Math.random(), }, map: innerMap, }); attachSecretMessage(marker, secretMessages[i]); } } // Attaches an info window to a marker with the provided message. When the // marker is clicked, the info window will open with the secret message. function attachSecretMessage( marker: google.maps.marker.AdvancedMarkerElement, secretMessage: string ) { const infowindow = new google.maps.InfoWindow({ content: secretMessage, }); marker.addListener('gmp-click', () => { infowindow.open(marker.map, marker); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. (await google.maps.importLibrary('maps')); (await google.maps.importLibrary('marker')); const mapElement = document.querySelector('gmp-map'); const innerMap = mapElement.innerMap; const bounds = { north: -25.363882, south: -31.203405, east: 131.044922, west: 125.244141, }; // Display the area between the location southWest and northEast. innerMap.fitBounds(bounds); // Add 5 markers to map at random locations. // For each of these markers, give them a title with their index, and when // they are clicked they should open an infowindow with text from a secret // message. const secretMessages = ['This', 'is', 'the', 'secret', 'message']; const lngSpan = bounds.east - bounds.west; const latSpan = bounds.north - bounds.south; for (let i = 0; i < secretMessages.length; ++i) { const marker = new google.maps.marker.AdvancedMarkerElement({ position: { lat: bounds.south + latSpan * Math.random(), lng: bounds.west + lngSpan * Math.random(), }, map: innerMap, }); attachSecretMessage(marker, secretMessages[i]); } } // Attaches an info window to a marker with the provided message. When the // marker is clicked, the info window will open with the secret message. function attachSecretMessage(marker, secretMessage) { const infowindow = new google.maps.InfoWindow({ content: secretMessage, }); marker.addListener('gmp-click', () => { infowindow.open(marker.map, marker); }); } initMap();
דוגמה לניסיון
קבלת מאפיינים והגדרת מאפיינים בתוך גורמים שמטפלים באירועים
אף אחד מאירועי שינוי הסטטוס של MVC במערכת האירועים של Maps JavaScript API לא מעביר ארגומנטים כשהאירוע מופעל. (אירועים ברמת המשתמש מעבירים ארגומנטים שאפשר לבדוק). אם אתם צריכים לבדוק מאפיין בשינוי מצב של MVC, אתם צריכים לקרוא באופן מפורש לשיטת getProperty() המתאימה באובייקט הזה. בבדיקה הזו תמיד יאוחזר המצב הנוכחי של אובייקט MVC, שיכול להיות שונה מהמצב שבו האירוע הופעל בפעם הראשונה.
הערה: הגדרה מפורשת של מאפיין בתוך גורם מטפל באירועים שמגיב לשינוי במצב של אותו מאפיין ספציפי עלולה להוביל להתנהגות בלתי צפויה או לא רצויה. הגדרת מאפיין כזה תפעיל אירוע חדש, למשל, ואם תמיד תגדירו מאפיין בתוך גורם מטפל באירועים זה, יכול להיות שתיווצר לולאה אינסופית.
בדוגמה הבאה אפשר לראות איך מגדירים גורם מטפל באירועים כדי להגיב לאירועי שינוי מרחק התצוגה על ידי הצגת חלון מידע עם הרמה.
TypeScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922); const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 4, center: originalMapCenter, } ); const infowindow = new google.maps.InfoWindow({ content: "Change the zoom level", position: originalMapCenter, }); infowindow.open(map); map.addListener("zoom_changed", () => { infowindow.setContent("Zoom: " + map.getZoom()!); }); } initMap();
JavaScript
async function initMap() { // Request needed libraries. const { Map } = await google.maps.importLibrary("maps"); const originalMapCenter = new google.maps.LatLng(-25.363882, 131.044922); const map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: originalMapCenter, }); const infowindow = new google.maps.InfoWindow({ content: "Change the zoom level", position: originalMapCenter, }); infowindow.open(map); map.addListener("zoom_changed", () => { infowindow.setContent("Zoom: " + map.getZoom()); }); } initMap();
דוגמה לניסיון
הסרת פונקציות מסוג Event Listener
כדי להסיר event listener ספציפי, צריך להקצות אותו למשתנה. אחר כך אפשר להתקשר אל removeListener(),
ולהעביר את שם המשתנה שאליו הוקצה המאזין.
var listener1 = marker.addListener('click', aFunction); google.maps.event.removeListener(listener1);
כדי להסיר את כל מאזיני האירועים ממופע מסוים, קוראים לפונקציה clearInstanceListeners() ומעבירים את שם המופע.
var listener1 = marker.addListener('click', aFunction); var listener2 = marker.addListener('mouseover', bFunction); // Remove listener1 and listener2 from marker instance. google.maps.event.clearInstanceListeners(marker);
כדי להסיר את כל מאזיני האירועים מסוג אירוע ספציפי במופע ספציפי, צריך לקרוא ל-clearListeners() ולהעביר את שם המופע ואת שם האירוע.
marker.addListener('click', aFunction); marker.addListener('click', bFunction); marker.addListener('click', cFunction); // Remove all click listeners from marker instance. google.maps.event.clearListeners(marker, 'click');
למידע נוסף, אפשר לעיין במאמרי העזרה בנושא מרחב השמות google.maps.event.
האזנה לשגיאות אימות
אם רוצים לזהות באופן פרוגרמטי כשל באימות (לדוגמה, כדי לשלוח באופן אוטומטי אות beacon), אפשר להכין פונקציית קריאה חוזרת.
אם מוגדרת הפונקציה הגלובלית הבאה, המערכת תקרא לה כשהאימות ייכשל.
function gm_authFailure() { /* Code */ };
ב-TypeScript, יכול להיות שיהיה צורך להוסיף את הפונקציה להיקף הגלובלי, כמו שמוצג בהמשך:
// Define the callback function. window.gm_authFailure = () => { console.error("Google Maps failed to authenticate."); /* Code */ }; // Add gm_authFailure to the global scope. declare global { interface Window { gm_authFailure?: () => void; } } export {};