במסמך הזה מפורט על סוגי המפות שאפשר להציג באמצעות
API של JavaScript של מפות Google. ה-API משתמש באובייקט MapType
כדי לשמור מידע על המפות האלה. MapType
הוא ממשק שמגדיר את התצוגה של קטעי המפה והשימוש בהם
ואת התרגום של מערכות הקואורדינטות מקואורדינטות במסך לקואורדינטות עולם (במפה). כל MapType
צריך לכלול כמה שיטות לטיפול באחזור ובשחרור של משבצות, ומאפיינים שמגדירים את ההתנהגות החזותית שלו.
התהליך הפנימי של סוגי מפות ב-API של JavaScript של מפות Google הוא נושא מתקדם. רוב המפתחים יכולים להשתמש ב סוגי המפות הבסיסיים שמפורטים בהמשך. עם זאת, תוכל גם לשנות את ההצגה של סוגי מפות קיימים באמצעות מפות סגנונות או להגדיר קטעי מפה משלך באמצעות סוגי מפות מותאמים אישית. כשמספקים סוגי מפות מותאמים אישית, צריך להבין איך לשנות את מרשם סוגי המפה של המפה.
סוגי מפה בסיסיים
קיימים ארבעה סוגי מפות הזמינים ב-Maps JavaScript API. בנוסף לקטעי המפה ה "צבועים" המוכרים של מפת הדרכים, JavaScript API של מפות Google תומך גם בסוגי מפות אחרים.
סוגי המפות הבאים זמינים ב-Maps JavaScript API:
roadmap
מציג את תצוגת ברירת המחדל של מפת הדרכים. זהו סוג המפה שמוגדר כברירת מחדל.satellite
מציג תמונות לוויין של Google Earth.- ב-
hybrid
מוצג שילוב של תצוגות רגילות וצילומי לוויין. terrain
מציג מפה פיזית על סמך מידע על פני השטח.
כדי לשנות את סוג המפה שבשימוש על ידי Map
, אתם יכולים להגדיר את המאפיין mapTypeId
של המפה בתוך ה-constructor, או להגדיר את האובייקט Map options
שלו, או לשלוח קריאה ל-method 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°
ה-JavaScript API של מפות Google תומך בתמונות מיוחדות ב-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)
. השיטה getTilt()
של Map
תשקף תמיד את ה-tilt
הנוכחי שמוצג
במפה. אם מגדירים tilt
במפה ולאחר מכן מסירים את
tilt
הזה (למשל, על ידי הקטנת התצוגה של המפה), השיטה
getTilt()
של המפה תחזיר 0
.
חשוב: תמונות ב-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;
כדאי לנסות דוגמה
שינוי מרשם סוגי המפה
mapTypeId
של מפה הוא מזהה מחרוזת
שמשמש לשיוך MapType
לערך ייחודי. כל אובייקט Map
שומר MapTypeRegistry
שמכיל את האוסף של MapType
ים שזמינים למפה הזו. לדוגמה, המרשם הזה משמש לבחירת סוגי המפות שזמינים בפקד 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
, אפשר לעיין במדריך
למפות מעוצבות.
סוגי מפה מותאמים אישית
הממשק JavaScript API של מפות Google תומך בהצגה ובניהול של סוגי מפות מותאמים אישית, כדי שתוכלו להטמיע תמונות מפה או שכבות-על של משבצות.
ב-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. (ראו הוספת פקדים שלMapType
בהמשך).alt
(אופציונלי) מציין את הטקסט החלופי של סוג המפה הזה, שמוצג כטקסט כשמציבים את סמן העכבר. המאפיין הזה נדרש רק אם רוצים שניתן יהיה לבחור את סוג המפה הזה בפקד MapType. (ראו הוספת פקדים שלMapType
בהמשך).
בנוסף, מחלקות שמטמיעות את הממשק MapType
צריכות להטמיע את השיטות הבאות:
-
מתבצעת קריאה אל
getTile()
(חובה) בכל פעם שה-API קובע שהמפה צריכה להציג משבצות חדשות עבור אזור התצוגה הנתון. ה-methodgetTile()
חייב לכלול את החתימה הבאה:getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node
ה-API קובע אם הוא צריך לקרוא ל-
getTile()
על סמך המאפייניםtileSize
,minZoom
ו-maxZoom
שלMapType
ורמת התצוגה והזום הנוכחית של המפה. ה-handler של השיטה הזו צריך להחזיר רכיב HTML עם הקואורדינטה שהועברה, רמת הזום ורכיב ה-DOM שאליהם צריך לצרף את תמונת המשבצת. -
קוראים לפונקציה
releaseTile()
(אופציונלי) בכל פעם שה-API קובע שצריך להסיר כרטיס מידע מהמפה כי הוא יוצא מהתצוגה. השיטה הזו חייבת לכלול את החתימה הבאה:releaseTile(tile:Node)
בדרך כלל צריך לטפל בהסרה של רכיבים שצורפו למשבצות המפה בזמן ההוספה למפה. לדוגמה, אם צירפת פונקציות event listener לשכבות-על של משבצות מפה, עליך להסיר אותן כאן.
ה-method 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, כמו כל מפה שטוחה של כדור הארץ, היא היטל של הכדור הזה על משטח ישר. במונחים הפשוטים ביותר, אפשר להגדיר היטל כמיפוי של ערכי קווי אורך ורוחב לקואורדינטות במפה של ההיטל.
החיזויים ב-API JavaScript של מפות Google חייבים להטמיע את הממשק של Projection
. הטמעה של
Projection
חייבת לספק לא רק מיפוי ממערכת קואורדינטות אחת לאחרת, אלא גם מיפוי דו-כיווני. כלומר צריך להגדיר איך לתרגם מקואורדינטות של Earth (אובייקטים מסוג LatLng
) למערכת הקואורדינטות בעולם של המחלקה Projection
, ולהפך. במפות Google נעשה שימוש
בהיטל של Mercator כדי ליצור את המפות שלו
מנתונים גיאוגרפיים, ולהמיר אירועים במפה
לקואורדינטות גיאוגרפיות. אפשר לקבל את התחזית הזו על ידי קריאה ל-getProjection()
ב-Map
(או בכל אחד מסוגי הבסיס הסטנדרטי MapType
). לרוב השימושים יספיק Projection
הרגיל הזה, אבל אפשר גם להגדיר תחזיות בהתאמה אישית ולהשתמש בהן.
יישום תחזית
כשמטמיעים היטל מותאם אישית, צריך להגדיר מספר דברים:
- הנוסחה למיפוי קואורדינטות של קווי רוחב ואורך
למישור קרטזי ולהפך. (הממשק
Projection
תומך רק בטרנספורמציות לקואורדינטות ישר). - גודל אריח הבסיס. כל המשבצות חייבות להיות מלבניות.
- 'גודל העולם' של מפה באמצעות משבצת הבסיס שמוגדרת ברמת הזום 0. חשוב לשים לב שלמפות שמורכבות ממשבצת אחת בזום 0, גודל העולם וגודל אריח הבסיס זהים.
תיאום טרנספורמציות בתחזיות
כל היטל מספק שתי שיטות שמתורגמות בין שתי מערכות הקואורדינטות האלה, וכך אפשר להמיר בין קואורדינטות גיאוגרפיות וקואורדינטות עולמיות:
- ה-method
Projection.fromLatLngToPoint()
ממירה ערךLatLng
לקואורדינטה עולמית. השיטה הזו משמשת למיקום של שכבות-על במפה (ולמיקום המפה עצמה). - ה-method
Projection.fromPointToLatLng()
ממירה קואורדינטות עולמיות לערךLatLng
. השיטה הזו משמשת כדי להמיר אירועים כמו קליקים שמתרחשים במפה לקואורדינטות גיאוגרפיות.
ההנחה במפות Google היא שהתחזיות הן ליניאריות.
באופן כללי, אפשר להשתמש בהיטל לשני מקרים: כדי ליצור מפת העולם או כדי ליצור מפה של אזור מקומי. במקרה הקודם, צריך לוודא שההיטל הוא גם ישר ורגיל בכל קווי האורך. תחזיות מסוימות (במיוחד תחזיות חרוטות) עשויות להיות "נורמליות באופן מקומי" (כלומר, הכיוון הצפוני) אבל סטיות מהצפון האמיתי. לדוגמה, ככל שהמפה ממוקמת רחוק יותר ביחס לקו אורך מסוים להתייחסות. אפשר להשתמש בהיטל כזה באופן מקומי, אבל חשוב לזכור שההיטל הוא בהכרח לא מדויק, וככל הנראה שגיאות הטרנספורמציה יתרחקו ככל שקו האורך בהתייחסות לסטייה רחוק יותר.
בחירת אריחי מפה בהקרנות
ההיטלים שימושיים לא רק לקביעת המיקומים של מיקומים או שכבות-על, אלא גם לצורך מיקום אריחי המפה עצמם.
ה-API של JavaScript של מפות Google מעבד מפות בסיסיות באמצעות ממשק MapType
, שחייב להצהיר גם על המאפיין projection
כדי לזהות את ההיטל של המפה וגם על השיטה getTile()
לאחזור המפה על סמך ערכי קואורדינטות של משבצות. הקואורדינטות של המשבצות מבוססות על גודל המשבצת הבסיסי (שחייב להיות מלבני) ועל 'גודל העולם' במפה, שהוא גודל הפיקסלים של העולם במפה ברמת מרחק מ-0. (למפות שמורכבות מאריח אחד בזום 0, גודל המשבצת וגודל העולם זהים).
הגודל של משבצת הבסיס מוגדר בנכס tileSize
של MapType
. מגדירים את גודל העולם במרומז ב-methods 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;