במסמך הזה מוסבר על סוגי המפות שאפשר להציג באמצעות Maps JavaScript API. ה-API משתמש באובייקט MapType
כדי לאחסן מידע על המפות האלה. MapType
הוא ממשק שמגדיר את התצוגה והשימוש במשבצות מפה ואת התרגום של מערכות קואורדינטות מקואורדינטות מסך לקואורדינטות עולמיות (במפה). כל רכיב MapType
צריך להכיל כמה שיטות לטיפול באחזור ובשחרור של אריחים, ומאפיינים שמגדירים את ההתנהגות החזותית שלו.
הפעולות הפנימיות של סוגי מפות ב-Maps JavaScript API הן נושא מתקדם. רוב המפתחים יכולים להשתמש ב סוגי המפות הבסיסיים שמפורטים בהמשך. עם זאת, אפשר גם לשנות את הצגת סוגי המפות הקיימים באמצעות מפות עם סגנון או להגדיר משבצות מפה משלכם באמצעות סוגי מפות בהתאמה אישית. כשמספקים סוגי מפות בהתאמה אישית, צריך להבין איך לשנות את הרישום של סוגי המפות.
סוגים בסיסיים של מפות
יש ארבעה סוגים של מפות שזמינים בממשק API של JavaScript במפות Google. בנוסף למשבצות המוכרות של מפת הדרכים, ממשק API של JavaScript במפות Google תומך גם בסוגים אחרים של מפות.
סוגי המפות הבאים זמינים בממשק API של JavaScript במפות Google:
roadmap
מציג את תצוגת ברירת המחדל של מפת הדרכים. זהו סוג המפה שמוגדר כברירת מחדל.-
satellite
מציג תמונות לוויין של Google Earth. -
hybrid
מוצג שילוב של תצוגות רגילות ותצוגות לוויין. -
terrain
מציג מפה פיזית שמבוססת על מידע על פני השטח.
כדי לשנות את סוג המפה שבה נעשה שימוש ב-Map
, צריך להגדיר את המאפיין mapTypeId
שלו, או בתוך ה-constructor על ידי הגדרת האובייקט Map options
שלו, או על ידי קריאה לשיטה setMapTypeId()
של המפה. ערך ברירת המחדל של המאפיין mapTypeID
הוא roadmap
.
הגדרת mapTypeId
במהלך הבנייה:
var myLatlng = new google.maps.LatLng(-34.397, 150.644); var mapOptions = { zoom: 8, center: myLatlng, mapTypeId: 'satellite' }; var map = new google.maps.Map(document.getElementById('map'), mapOptions);
שינוי mapTypeId
באופן דינמי:
map.setMapTypeId('terrain');
שימו לב: לא מגדירים את סוג המפה של המפה ישירות, אלא מגדירים את mapTypeId
שלה כך שתפנה אל MapType
באמצעות מזהה.
ממשק ה-API של JavaScript במפות Google משתמש במאגר של סוגי מפות, שמפורט בהמשך, כדי לנהל את ההפניות האלה.
תמונות בזווית של 45°
Maps JavaScript API תומך בתמונות מיוחדות בזווית של 45° במיקומים מסוימים. התמונות האלה ברזולוציה גבוהה ומספקות תצוגות פרספקטיבה לכל אחד מהכיוונים הראשיים (צפון, דרום, מזרח, מערב). התמונות האלה זמינות ברמות זום גבוהות יותר בסוגי מפות נתמכים.
בתמונה הבאה אפשר לראות את העיר ניו יורק מנקודת מבט של 45 מעלות:
סוגי המפות satellite
ו-hybrid
תומכים בתמונות בזווית של 45° ברמות זום גבוהות (12 ומעלה) במקומות שבהם התמונות האלה זמינות. אם המשתמש מגדיל תצוגה של מיקום שיש לו תמונות כאלה, סוגי המפות האלה משנים את התצוגה באופן אוטומטי בצורה הבאה:
- תמונות הלוויין או התמונות ההיברידיות מוחלפות בתמונות שמציגות פרספקטיבה של 45°
עם מיקום מרכזי במיקום הנוכחי. כברירת מחדל, התצוגות האלה מכוונות לצפון. אם המשתמש מבצע זום אאוט, תמונות הלוויין או התמונות ההיברידיות שמוגדרות כברירת מחדל מופיעות שוב. ההתנהגות משתנה בהתאם לרמת הזום
ולערך של
tilt
: - בין רמות הזום 12 ו-18, מפת הבסיס מלמעלה למטה (0°) מוצגת כברירת מחדל, אלא אם הערך של
tilt
מוגדר ל-45. - במפות בסיס ברמות זום של 18 ומעלה מוצגת מפת בסיס בזווית של 45 מעלות, אלא אם הערך של
tilt
הוא 0. - פקד הסיבוב מוצג. אמצעי הבקרה לסיבוב מספק אפשרויות שמאפשרות למשתמש להחליף את ההטיה ולסובב את התצוגה במרווחים של 90° בכל אחד מהכיוונים. כדי להסתיר את לחצן הסיבוב, מגדירים את
rotateControl
ל-false
.
אם מתרחקים מתצוגה של סוג מפה שמציג תמונות בזווית של 45°, כל השינויים האלה מתבטלים וסוגי המפות המקוריים חוזרים.
הפעלה והשבתה של תמונות בזווית של 45°
כדי להשבית את התמונות בזווית של 45°, צריך להפעיל את setTilt(0)
באובייקט Map
. כדי להפעיל תמונות בזווית של 45 מעלות בסוגי מפות נתמכים, צריך להתקשר למספר setTilt(45)
. השיטה Map
של getTilt()
תמיד תשקף את tilt
הנוכחי שמוצג במפה. אם מגדירים tilt
במפה ואז מסירים אותו (לדוגמה, על ידי הרחקת התצוגה של המפה), השיטה getTilt()
של המפה תחזיר 0
.tilt
חשוב: תמונות בזווית של 45° נתמכות רק במפות רסטר. אי אפשר להשתמש בתמונות האלה במפות וקטוריות.
בדוגמה הבאה מוצגת תצוגה של 45° של העיר ניו יורק:
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", } ); map.setTilt(45); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", }); map.setTilt(45); } window.initMap = initMap;
דוגמה לניסיון
סיבוב תמונות ב-45°
תמונות בזווית של 45° הן למעשה אוסף של תמונות לכל כיוון ראשי (צפון, דרום, מזרח ומערב). אחרי שהתמונות במפה מוצגות בזווית של 45°, אפשר לכוון את התמונות לאחד הכיוונים הראשיים על ידי קריאה ל-setHeading()
באובייקט Map
והעברת ערך מספרי שמייצג מעלות מצפון.
בדוגמה הבאה מוצג מפה אווירית, והמפה מסתובבת אוטומטית כל 3 שניות כשלוחצים על הלחצן:
TypeScript
let map: google.maps.Map; function initMap(): void { map = new google.maps.Map(document.getElementById("map") as HTMLElement, { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", heading: 90, tilt: 45, }); // add listener to button document.getElementById("rotate")!.addEventListener("click", autoRotate); } function rotate90(): void { const heading = map.getHeading() || 0; map.setHeading(heading + 90); } function autoRotate(): void { // Determine if we're showing aerial imagery. if (map.getTilt() !== 0) { window.setInterval(rotate90, 3000); } } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
let map; function initMap() { map = new google.maps.Map(document.getElementById("map"), { center: { lat: 40.76, lng: -73.983 }, zoom: 15, mapTypeId: "satellite", heading: 90, tilt: 45, }); // add listener to button document.getElementById("rotate").addEventListener("click", autoRotate); } function rotate90() { const heading = map.getHeading() || 0; map.setHeading(heading + 90); } function autoRotate() { // Determine if we're showing aerial imagery. if (map.getTilt() !== 0) { window.setInterval(rotate90, 3000); } } window.initMap = initMap;
דוגמה לניסיון
שינוי של Map Type Registry
mapTypeId
של מיפוי הוא מזהה מחרוזת
שמשמש לשיוך MapType
לערך ייחודי. כל אובייקט Map
שומר על MapTypeRegistry
שמכיל את האוסף של MapType
s שזמינים למפה הזו. המאגר הזה משמש לבחירת סוגי המפות שזמינות בפקד MapType של המפה, למשל.
אתם לא קוראים ישירות ממאגר סוגי המפות. במקום זאת, משנים את הרישום על ידי הוספת סוגי מפות בהתאמה אישית ושיוך שלהם למזהה מחרוזת לבחירתכם. אי אפשר לשנות את סוגי המפות הבסיסיים (אבל אפשר להסיר אותם מהמפה על ידי שינוי המראה של mapTypeControlOptions
שמשויך למפה).
הקוד הבא מגדיר את המפה כך שיוצגו בה רק שני סוגים של מפות ב-mapTypeControlOptions
שלה, ומשנה את הרישום כדי להוסיף את השיוך למזהה הזה להטמעה בפועל של הממשק MapType
.
// Modify the control to only display two maptypes, the // default ROADMAP and the custom 'mymap'. // Note that because this is an association, we // don't need to modify the MapTypeRegistry beforehand. var MY_MAPTYPE_ID = 'mymaps'; var mapOptions = { zoom: 12, center: brooklyn, mapTypeControlOptions: { mapTypeIds: ['roadmap', MY_MAPTYPE_ID] }, mapTypeId: MY_MAPTYPE_ID }; // Create our map. This creation will implicitly create a // map type registry. map = new google.maps.Map(document.getElementById('map'), mapOptions); // Create your custom map type using your own code. // (See below.) var myMapType = new MyMapType(); // Set the registry to associate 'mymap' with the // custom map type we created, and set the map to // show that map type. map.mapTypes.set(MY_MAPTYPE_ID, myMapType);
מפות מסוגננות
האפשרות StyledMapType
מאפשרת להתאים אישית את הצגת מפות הבסיס הרגילות של Google, ולשנות את התצוגה החזותית של רכיבים כמו כבישים, פארקים ואזורים בנויים, כך שתשקף סגנון שונה מזה שמשמש בסוג המפה שמוגדר כברירת מחדל. ההגדרה StyledMapType
משפיעה רק על סוג המפה שמוגדר כברירת מחדל roadmap
.
מידע נוסף על StyledMapType
זמין במאמר שימוש בהצהרות מוטמעות בסגנון JSON.
סוגי מפות בהתאמה אישית
ממשק Maps JavaScript API תומך בהצגה ובניהול של סוגי מפות בהתאמה אישית, ומאפשר לכם להטמיע תמונות מפה משלכם או שכבות-על של משבצות.
קיימים כמה יישומים אפשריים של סוגי מפות ב-Maps JavaScript API:
- קבוצות משבצות רגילות שמורכבות מתמונות שביחד יוצרות מפות קרטוגרפיות מלאות. ערכות המשבצות האלה נקראות גם סוגי מפות בסיסיות. סוגי המפות האלה פועלים ומתנהגים כמו סוגי המפות הקיימים שמוגדרים כברירת מחדל:
roadmap
,satellite
,hybrid
ו-terrain
. אתם יכולים להוסיף את סוג המפה המותאם אישית שלכם למערךmapTypes
של Map כדי לאפשר לממשק המשתמש ב-Maps JavaScript API להתייחס לסוג המפה המותאם אישית שלכם כאל סוג מפה רגיל (למשל, על ידי הכללתו באמצעי הבקרה MapType). - שכבות-על של משבצות תמונה שמוצגות מעל סוגי מפות בסיסיות קיימים. בדרך כלל, סוגי המפות האלה משמשים להוספת מידע למפה קיימת, ולעתים קרובות הם מוגבלים למיקומים ספציפיים או לרמות זום מסוימות. שימו לב שהמשבצות האלה עשויות להיות שקופות, כך שתוכלו להוסיף תכונות למפות קיימות.
- סוגי מפות שאינם תמונות, שמאפשרים לכם לשנות את התצוגה של פרטי המפה ברמה הבסיסית ביותר.
כל אחת מהאפשרויות האלה מסתמכת על יצירת מחלקה שמטמיעה את הממשק MapType
. בנוסף, המחלקה
ImageMapType
מספקת התנהגות מובנית מסוימת כדי לפשט את היצירה של סוגי מפות של תמונות.
הממשק של MapType
לפני שיוצרים מחלקות שמטמיעות את MapType
,
חשוב להבין איך מפות Google קובעות
קואורדינטות ומחליטות אילו חלקים של המפה להציג. צריך להטמיע לוגיקה דומה לכל סוגי המפות הבסיסיות או מפות השכבות.
מומלץ לקרוא את המדריך בנושא קואורדינטות של מפות ומשבצות.
סוגי מפות מותאמים אישית צריכים להטמיע את הממשק MapType
. הממשק הזה מציין מאפיינים ושיטות מסוימים שמאפשרים ל-API ליזום בקשות לסוגי המפות כש-API קובע שהוא צריך להציג משבצות מפה בתוך אזור התצוגה הנוכחי ורמת הזום. אתם מטפלים בבקשות האלה כדי להחליט איזו משבצת לטעון.
הערה: אתם יכולים ליצור מחלקה משלכם כדי להטמיע את הממשק הזה. לחלופין, אם יש לכם תמונות תואמות, אתם יכולים להשתמש במחלקה
ImageMapType
שכבר מטמיעה את הממשק הזה.
במחלקה שמטמיעה את הממשק MapType
, צריך להגדיר ולאכלס את המאפיינים הבאים:
-
tileSize
(חובה) מציין את גודל המשבצת (מסוגgoogle.maps.Size
). הגדלים צריכים להיות מלבניים, אבל לא בהכרח ריבועיים. -
maxZoom
(חובה) מציין את רמת הזום המקסימלית שבה יוצגו משבצות של סוג המפה הזה. -
minZoom
(אופציונלי) מציין את רמת הזום המינימלית שבה יוצג אריח של סוג המפה הזה. ערך ברירת המחדל הוא0
, שמשמעותו שאין רמת זום מינימלית. -
name
(אופציונלי) מציין את השם של סוג המפה הזה. המאפיין הזה נדרש רק אם רוצים לאפשר בחירה בסוג המפה הזה באמצעות רכיב MapType. (ראו אפשרויות שליטה). alt
(אופציונלי) מציין את הטקסט החלופי לסוג המפה הזה, שמוצג כטקסט כשמעבירים את העכבר מעל המפה. המאפיין הזה נדרש רק אם רוצים לאפשר בחירה של סוג המפה הזה באמצעות רכיב MapType. (לעיון באפשרויות השליטה).
בנוסף, מחלקות שמטמיעות את הממשק MapType
צריכות להטמיע את השיטות הבאות:
-
getTile()
(נדרש) נקרא בכל פעם שממשק ה-API קובע שהמפה צריכה להציג משבצות חדשות עבור אזור התצוגה הנתון. ל-getTile()
method צריכה להיות החתימה הבאה:getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node
ממשק ה-API קובע אם צריך לקרוא ל-
getTile()
על סמך המאפייניםMapType
,tileSize
,minZoom
ו-maxZoom
שלgetTile()
, אזור התצוגה הנוכחי של המפה ורמת הזום. ה-handler של השיטה הזו צריך להחזיר אלמנט HTML בהינתן קואורדינטה, רמת זום ואלמנט DOM שצריך לצרף אליו את תמונת המשבצת. -
releaseTile()
(אופציונלי) מופעל בכל פעם שממשק ה-API קובע שצריך להסיר משבצת מהמפה כי היא לא מוצגת יותר. לשיטה הזו צריכה להיות החתימה הבאה:releaseTile(tile:Node)
בדרך כלל, צריך לטפל בהסרה של כל הרכיבים שצורפו למשבצות של המפה כשהם נוספו למפה. לדוגמה, אם צירפתם event listeners לשכבות-על של משבצות מפה, אתם צריכים להסיר אותם כאן.
השיטה getTile()
פועלת כבקר הראשי לקביעת האריחים שייטענו באזור תצוגה נתון.
סוגי מפות בסיסיות
סוגי מפות שיוצרים בדרך הזו יכולים להיות עצמאיים או לשמש כשכבות-על בשילוב עם סוגי מפות אחרים. סוגי מפות עצמאיים נקראים סוגי מפות בסיס. יכול להיות שתרצו שממשק ה-API יתייחס ל-MapType
בהתאמה אישית כמו לכל סוג אחר של מפת בסיס (ROADMAP
, TERRAIN
וכו'). כדי לעשות את זה, מוסיפים את MapType
המותאם אישית לנכס mapTypes
של Map
. סוג הנכס הוא
MapTypeRegistry
.
הקוד הבא יוצר בסיס MapType
להצגת קואורדינטות של משבצות במפה ומשרטט מתאר של המשבצות:
TypeScript
/* * This demo demonstrates how to replace default map tiles with custom imagery. * In this case, the CoordMapType displays gray tiles annotated with the tile * coordinates. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType { tileSize: google.maps.Size; maxZoom = 19; name = "Tile #s"; alt = "Tile Coordinate Map Type"; constructor(tileSize: google.maps.Size) { this.tileSize = tileSize; } getTile( coord: google.maps.Point, zoom: number, ownerDocument: Document ): HTMLElement { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; div.style.backgroundColor = "#E5E3DF"; return div; } releaseTile(tile: HTMLElement): void {} } function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 10, center: { lat: 41.85, lng: -87.65 }, streetViewControl: false, mapTypeId: "coordinate", mapTypeControlOptions: { mapTypeIds: ["coordinate", "roadmap"], style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, }, } ); map.addListener("maptypeid_changed", () => { const showStreetViewControl = (map.getMapTypeId() as string) !== "coordinate"; map.setOptions({ streetViewControl: showStreetViewControl, }); }); // Now attach the coordinate map type to the map's registry. map.mapTypes.set( "coordinate", new CoordMapType(new google.maps.Size(256, 256)) ); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
/* * This demo demonstrates how to replace default map tiles with custom imagery. * In this case, the CoordMapType displays gray tiles annotated with the tile * coordinates. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType { tileSize; maxZoom = 19; name = "Tile #s"; alt = "Tile Coordinate Map Type"; constructor(tileSize) { this.tileSize = tileSize; } getTile(coord, zoom, ownerDocument) { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; div.style.backgroundColor = "#E5E3DF"; return div; } releaseTile(tile) {} } function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 10, center: { lat: 41.85, lng: -87.65 }, streetViewControl: false, mapTypeId: "coordinate", mapTypeControlOptions: { mapTypeIds: ["coordinate", "roadmap"], style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, }, }); map.addListener("maptypeid_changed", () => { const showStreetViewControl = map.getMapTypeId() !== "coordinate"; map.setOptions({ streetViewControl: showStreetViewControl, }); }); // Now attach the coordinate map type to the map's registry. map.mapTypes.set( "coordinate", new CoordMapType(new google.maps.Size(256, 256)), ); } window.initMap = initMap;
דוגמה לניסיון
סוגי מפות שמוצגות בשכבת-על
חלק מסוגי המפות מיועדים לפעול על גבי סוגי מפות קיימים. סוגי מפות כאלה יכולים לכלול שכבות שקופות שמציינות נקודות עניין או להציג למשתמש נתונים נוספים.
במקרים כאלה, לא רוצים שסוג המפה יטופל כישות נפרדת אלא כשכבת-על.
כדי לעשות את זה, מוסיפים את סוג המיפוי ל-MapType
קיים ישירות באמצעות המאפיין overlayMapTypes
של Map
. הנכס הזה מכיל MVCArray
של MapType
. כל סוגי המפות (מפת בסיס ומפת שכבת-על) עוברים רינדור בשכבה mapPane
. סוגי מפות של שכבות-על יוצגו מעל מפת הבסיס שאליה הם מצורפים, בסדר שבו הם מופיעים במערך Map.overlayMapTypes
(שכבות-על עם ערכי אינדקס גבוהים יותר מוצגות לפני שכבות-על עם ערכי אינדקס נמוכים יותר).
הדוגמה הבאה זהה לדוגמה הקודמת,
אבל יצרנו בה שכבת כיסוי של משבצות MapType
מעל סוג המפה ROADMAP
:
TypeScript
/* * This demo illustrates the coordinate system used to display map tiles in the * API. * * Tiles in Google Maps are numbered from the same origin as that for * pixels. For Google's implementation of the Mercator projection, the origin * tile is always at the northwest corner of the map, with x values increasing * from west to east and y values increasing from north to south. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType implements google.maps.MapType { tileSize: google.maps.Size; alt: string|null = null; maxZoom: number = 17; minZoom: number = 0; name: string|null = null; projection: google.maps.Projection|null = null; radius: number = 6378137; constructor(tileSize: google.maps.Size) { this.tileSize = tileSize; } getTile( coord: google.maps.Point, zoom: number, ownerDocument: Document ): HTMLElement { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; return div; } releaseTile(tile: Element): void {} } function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 10, center: { lat: 41.85, lng: -87.65 }, } ); // Insert this overlay map type as the first overlay map type at // position 0. Note that all overlay map types appear on top of // their parent base map. const coordMapType = new CoordMapType(new google.maps.Size(256, 256)) map.overlayMapTypes.insertAt( 0, coordMapType ); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
/* * This demo illustrates the coordinate system used to display map tiles in the * API. * * Tiles in Google Maps are numbered from the same origin as that for * pixels. For Google's implementation of the Mercator projection, the origin * tile is always at the northwest corner of the map, with x values increasing * from west to east and y values increasing from north to south. * * Try panning and zooming the map to see how the coordinates change. */ class CoordMapType { tileSize; alt = null; maxZoom = 17; minZoom = 0; name = null; projection = null; radius = 6378137; constructor(tileSize) { this.tileSize = tileSize; } getTile(coord, zoom, ownerDocument) { const div = ownerDocument.createElement("div"); div.innerHTML = String(coord); div.style.width = this.tileSize.width + "px"; div.style.height = this.tileSize.height + "px"; div.style.fontSize = "10"; div.style.borderStyle = "solid"; div.style.borderWidth = "1px"; div.style.borderColor = "#AAAAAA"; return div; } releaseTile(tile) {} } function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 10, center: { lat: 41.85, lng: -87.65 }, }); // Insert this overlay map type as the first overlay map type at // position 0. Note that all overlay map types appear on top of // their parent base map. const coordMapType = new CoordMapType(new google.maps.Size(256, 256)); map.overlayMapTypes.insertAt(0, coordMapType); } window.initMap = initMap;
דוגמה לניסיון
סוגים של מפות תמונה
הטמעה של MapType
שתשמש כסוג של מפת בסיס יכולה להיות משימה ארוכה ומייגעת. ה-API
מספק מחלקה מיוחדת שמטמיעה את הממשק MapType
עבור סוגי המפות הנפוצים ביותר: סוגי מפות שמורכבות מאריחים שמבוססים על קובצי תמונה בודדים.
המחלקות האלה, כולל המחלקה ImageMapType
, מורכבות ממפרט של אובייקט ImageMapTypeOptions
שמגדיר את מאפייני החובה הבאים:
-
tileSize
(חובה) מציין את גודל המשבצת (מסוגgoogle.maps.Size
). הגדלים צריכים להיות מלבניים, אבל לא בהכרח ריבועיים. -
getTileUrl
(חובה) מציין את הפונקציה, שבדרך כלל מסופקת כמחרוזת של פונקציה מוטבעת, כדי לטפל בבחירה של משבצת התמונה המתאימה על סמך קואורדינטות העולם ורמת הזום שסופקו.
הקוד הבא מיישם ImageMapType
בסיסי באמצעות משבצות של הירח מ-Google. בדוגמה נעשה שימוש בפונקציית נורמליזציה כדי לוודא שהמשבצות חוזרות לאורך ציר x, אבל לא לאורך ציר y במפה.
TypeScript
function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { center: { lat: 0, lng: 0 }, zoom: 1, streetViewControl: false, mapTypeControlOptions: { mapTypeIds: ["moon"], }, } ); const moonMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom): string { const normalizedCoord = getNormalizedCoord(coord, zoom); if (!normalizedCoord) { return ""; } const bound = Math.pow(2, zoom); return ( "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" + "/" + zoom + "/" + normalizedCoord.x + "/" + (bound - normalizedCoord.y - 1) + ".jpg" ); }, tileSize: new google.maps.Size(256, 256), maxZoom: 9, minZoom: 0, // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions' radius: 1738000, name: "Moon", }); map.mapTypes.set("moon", moonMapType); map.setMapTypeId("moon"); } // Normalizes the coords that tiles repeat across the x axis (horizontally) // like the standard Google map tiles. function getNormalizedCoord(coord, zoom) { const y = coord.y; let x = coord.x; // tile range in one direction range is dependent on zoom level // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc const tileRange = 1 << zoom; // don't repeat across y-axis (vertically) if (y < 0 || y >= tileRange) { return null; } // repeat across x-axis if (x < 0 || x >= tileRange) { x = ((x % tileRange) + tileRange) % tileRange; } return { x: x, y: y }; } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
function initMap() { const map = new google.maps.Map(document.getElementById("map"), { center: { lat: 0, lng: 0 }, zoom: 1, streetViewControl: false, mapTypeControlOptions: { mapTypeIds: ["moon"], }, }); const moonMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const normalizedCoord = getNormalizedCoord(coord, zoom); if (!normalizedCoord) { return ""; } const bound = Math.pow(2, zoom); return ( "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" + "/" + zoom + "/" + normalizedCoord.x + "/" + (bound - normalizedCoord.y - 1) + ".jpg" ); }, tileSize: new google.maps.Size(256, 256), maxZoom: 9, minZoom: 0, // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions' radius: 1738000, name: "Moon", }); map.mapTypes.set("moon", moonMapType); map.setMapTypeId("moon"); } // Normalizes the coords that tiles repeat across the x axis (horizontally) // like the standard Google map tiles. function getNormalizedCoord(coord, zoom) { const y = coord.y; let x = coord.x; // tile range in one direction range is dependent on zoom level // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc const tileRange = 1 << zoom; // don't repeat across y-axis (vertically) if (y < 0 || y >= tileRange) { return null; } // repeat across x-axis if (x < 0 || x >= tileRange) { x = ((x % tileRange) + tileRange) % tileRange; } return { x: x, y: y }; } window.initMap = initMap;
דוגמה לניסיון
תחזיות
כדור הארץ הוא כדור תלת-ממדי (בערך), ומפה היא משטח דו-ממדי שטוח. המפה שמוצגת בממשק API של JavaScript במפות Google, כמו כל מפה שטוחה של כדור הארץ, היא הטלה של הכדור על משטח שטוח. במילים פשוטות, אפשר להגדיר היטל כמיפוי של ערכי קו רוחב/אורך לקואורדינטות במפה של ההיטל.
ההטלות ב-Maps JavaScript API צריכות להטמיע את הממשק Projection
. הטמעה של Projection
חייבת לספק לא רק מיפוי ממערכת קואורדינטות אחת למערכת אחרת, אלא מיפוי דו-כיווני. כלומר, צריך להגדיר איך לתרגם מקואורדינטות של כדור הארץ (אובייקטים של LatLng
) למערכת הקואורדינטות העולמית של המחלקה Projection
, וממערכת הקואורדינטות העולמית בחזרה לקואורדינטות של כדור הארץ.
מפות Google משתמשת בהטלת מרקטור כדי ליצור את המפות שלה מנתונים גאוגרפיים ולהמיר אירועים במפה לקואורדינטות גאוגרפיות. אפשר לקבל את התחזית הזו על ידי קריאה ל-getProjection()
ב-Map
(או בכל אחד מסוגי הבסיס הרגילים של MapType
). ברוב המקרים, התקן Projection
הזה יספיק, אבל אפשר גם להגדיר ולהשתמש בהטלות מותאמות אישית משלכם.
יישום של תחזית
כשמטמיעים הקרנה בהתאמה אישית, צריך להגדיר כמה דברים:
- הנוסחאות למיפוי קואורדינטות של קו רוחב וקו אורך למישור קרטזיאני, והנוסחאות המתאימות למיפוי ממישור קרטזיאני לקואורדינטות של קו רוחב וקו אורך. (ממשק
Projection
תומך רק בהמרות לקואורדינטות קרטזיות). - גודל הבסיס של קטע המפה. כל המשבצות חייבות להיות מלבניות.
- הגודל של מפה ברמת העולם באמצעות קבוצת משבצות הבסיס ברמת זום 0. שימו לב: במפות שמורכבות ממשבצת אחת ברמת זום 0, גודל העולם וגודל משבצת הבסיס זהים.
המרות של מערכות קואורדינטות בהטלות
כל הטלה מספקת שתי שיטות לתרגום בין שתי מערכות הקואורדינטות האלה, שמאפשרות לכם להמיר בין קואורדינטות גיאוגרפיות לקואורדינטות עולמיות:
- השיטה
Projection.fromLatLngToPoint()
ממירה ערךLatLng
לקואורדינטה עולמית. השיטה הזו משמשת למיקום שכבות-על במפה (ולמיקום המפה עצמה). - השיטה
Projection.fromPointToLatLng()
ממירה קואורדינטה עולמית לערךLatLng
. השיטה הזו משמשת להמרת אירועים כמו קליקים שמתרחשים במפה לקואורדינטות גאוגרפיות.
מפות Google מניחות שההטלות הן ישרות.
בדרך כלל, אפשר להשתמש בהטלה בשני מקרים: כדי ליצור מפה של העולם או כדי ליצור מפה של אזור מקומי. במקרה הראשון, צריך לוודא שההטלה שלכם היא גם ישרה וגם רגילה בכל קווי האורך. חלק מההטלות (במיוחד הטלות חרוטיות) עשויות להיות 'נורמליות באופן מקומי' (כלומר, מצביעות צפונה) אבל להיות שונות מהצפון האמיתי. לדוגמה, ככל שהמפה ממוקמת רחוק יותר ביחס לקו אורך מסוים. אפשר להשתמש בהקרנה כזו באופן מקומי, אבל צריך לזכור שההקרנה לא מדויקת, ושגיאות בהמרה יהיו ברורות יותר ככל שיהיה מרחק גדול יותר בין קו האורך של ההפניה לבין קו האורך של המיקום.
בחירת משבצות במפה בחיזויים
ההטלות שימושיות לא רק לקביעת המיקומים של מקומות או שכבות-על, אלא גם למיקום של משבצות המפה עצמן.
ממשק API של JavaScript במפות Google מעבד מפות בסיס באמצעות ממשק MapType
שבו צריך להצהיר על מאפיין projection
לזיהוי ההטלה של המפה ועל שיטה getTile()
לאחזור משבצות מפה על סמך ערכי קואורדינטות של משבצת. קואורדינטות של אריחים מבוססות על גודל האריח הבסיסי (שחייב להיות מלבני) ועל 'גודל העולם' של המפה, שהוא גודל הפיקסלים של עולם המפה ברמת זום 0. (במפות שמורכבות ממשבצת אחת ברמת זום 0, גודל המשבצת וגודל העולם זהים).
מגדירים את גודל אריח הבסיס במאפיין MapType
's
tileSize
. אתם מגדירים את גודל העולם באופן מרומז בשיטות fromLatLngToPoint()
ו-fromPointToLatLng()
של ההטלה.
מכיוון שהבחירה של התמונה תלויה בערכים האלה, כדאי לתת שמות לתמונות שאפשר לבחור באופן פרוגרמטי בהתאם לערכים האלה, למשל map_zoom_tileX_tileY.png
.
בדוגמה הבאה מוגדר ImageMapType
באמצעות ההטלה
Gall-Peters:
TypeScript
// This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection const mapElement = document.querySelector("gmp-map") as google.maps.MapElement; let innerMap; async function initMap() { // Request the needed libraries. await google.maps.importLibrary("maps"); // Create a map. innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, }); // Set the Gall-Peters map type. initGallPeters(); innerMap.mapTypes.set("gallPeters", gallPetersMapType); innerMap.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords") as HTMLElement; innerMap.addListener("mousemove", (event: google.maps.MapMouseEvent) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng!.lat()) + ", " + "lng: " + Math.round(event.latLng!.lng()); }); // Add some markers to the map. innerMap.data.setStyle((feature) => { return { title: feature.getProperty("name") as string, optimized: false, }; }); innerMap.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ( "gall-peters_" + zoom + "_" + x + "_" + y + ".png" ); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters", }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function (latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point( GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)) ); }, fromPointToLatLng: function (point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng( (Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap ); }, }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" }, }, ], }; initMap();
JavaScript
// This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection const mapElement = document.querySelector("gmp-map"); let innerMap; async function initMap() { // Request the needed libraries. await google.maps.importLibrary("maps"); // Create a map. innerMap = mapElement.innerMap; innerMap.setOptions({ mapTypeControl: false, }); // Set the Gall-Peters map type. initGallPeters(); innerMap.mapTypes.set("gallPeters", gallPetersMapType); innerMap.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords"); innerMap.addListener("mousemove", (event) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng.lat()) + ", " + "lng: " + Math.round(event.latLng.lng()); }); // Add some markers to the map. innerMap.data.setStyle((feature) => { return { title: feature.getProperty("name"), optimized: false, }; }); innerMap.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ("gall-peters_" + zoom + "_" + x + "_" + y + ".png"); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters", }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function (latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point(GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))); }, fromPointToLatLng: function (point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng((Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap); }, }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" }, }, ], }; initMap();