במסמך הזה נפרט אילו סוגי מפות אפשר להציג באמצעות 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 תומך בהצגה ובניהול של סוגי מפות בהתאמה אישית, ומאפשר לכם להטמיע תמונות מפה משלכם או שכבות-על של משבצות.
קיימים כמה יישומים אפשריים של סוגי מפות בממשק API של JavaScript במפות Google:
- קבוצות של קטעי מפה שכוללות תמונות שביחד יוצרות מפות קרטוגרפיות מלאות. הם נקראים גם סוגי מפות בסיסיים. סוגי המפות האלה פועלים ומתנהגים כמו סוגי המפות הקיימים שמוגדרים כברירת מחדל:
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 function initMap(): void { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false, } ); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords") as HTMLElement; map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.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. map.data.setStyle((feature) => { return { title: feature.getProperty("name") as string, optimized: false, }; }); map.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 ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/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" }, }, ], }; declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
// This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection function initMap() { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map(document.getElementById("map"), { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false, }); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords"); map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.addListener("mousemove", (event) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng.lat()) + ", " + "lng: " + Math.round(event.latLng.lng()); }); // Add some markers to the map. map.data.setStyle((feature) => { return { title: feature.getProperty("name"), optimized: false, }; }); map.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 ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/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" }, }, ], }; window.initMap = initMap;