סוגי מפות

קל לארגן דפים בעזרת אוספים אפשר לשמור ולסווג תוכן על סמך ההעדפות שלך.
בחירת פלטפורמה: Android iOS JavaScript

מסמך זה דן בסוגי המפות שניתן להציג באמצעות Maps JavaScript API. ה-API משתמש באובייקט MapType כדי לשמור מידע על המפות האלה. MapType הוא ממשק שמגדיר את התצוגה והשימוש באריחי מפה ואת התרגום של מערכות קואורדינטות מקואורדינטות מסך לקואורדינטות של העולם (במפה). לכל MapType יש מספר שיטות לטיפול באחזור ובשחרור של אריחים, ובמאפיינים שמגדירים את ההתנהגות החזותית שלו.

העבודה הפנימית של סוגי מפות ב-Maps JavaScript API היא נושא מתקדם. רוב המפתחים יכולים להשתמש ב סוגי המפות הבסיסיים המפורטים למטה. עם זאת, ניתן גם לשנות את ההצגה של סוגי מפות קיימים באמצעות מפות מסוגננות או להגדיר אריחי מפה משלך באמצעות סוגי מפות מותאמים אישית. כשמציינים סוגי מפות מותאמים אישית, צריך להבין איך לשנות את המפה ברישום סוג המפה.

סוגי מפות בסיסיים

יש ארבעה סוגי מפות שזמינות ב-Maps JavaScript API. בנוסף למשבצות המוכרות " Painted" , Maps JavaScript API תומך גם בסוגי מפות אחרים.

סוגי המפות הבאים זמינים ב-Maps JavaScript API:

  • 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 של מפות Google משתמש ברישום של סוג מפה, כפי שמוסבר בהמשך, לניהול קובצי העזר האלה.

תמונות ב-45°

ה-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). השיטה Map של # getTilt() תשקף תמיד את 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 שזמינים למפה. הרישום הזה משמש לבחירת סוגי המפות הזמינים בפקד 'מיפוי' של מפות.

לא קוראים ישירות מהמרשם של סוגי המפה. במקום זאת, אפשר לשנות את הרישום על ידי הוספת סוגי מפות מותאמים אישית, ושיוך שלהם למזהה מחרוזת לבחירתך. לא ניתן לשנות או לשנות את סוגי המפה הבסיסיים (למרות שניתן להסיר אותם מהמפה על ידי שינוי המראה של המפה המשויכת ל-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, ניתן לעיין במדריך למפות מסוגננות.

סוגי מפות בהתאמה אישית

ה-API של Maps JavaScript תומך בתצוגה ובניהול של סוגי מפות בהתאמה אישית, וכך אפשר להטמיע תמונות מפה או שכבות-על של אריחים.

קיימים מספר הטמעות אפשריות של סוגי מפות ב-Maps JavaScript API:

  • קבוצות אריחים סטנדרטיות מורכבות מתמונות שמכילות ביחד מפות קרטוגרפיות מלאות. קבוצות האריחים האלה נקראות גם סוגי מפות בסיסיים. סוגי מפות אלה מתנהגים ומתנהגים כמו סוגי המפות הקיימים כברירת מחדל: roadmap, satellite, hybrid וterrain. אפשר להוסיף את סוג המפה המותאמת אישית למערך mapTypes של מפות Google כדי לאפשר לממשק המשתמש של ממשק ה-API של Maps JavaScript להתייחס לסוג המפה המותאם אישית כאל סוג מפה רגיל (לדוגמה, אם תוסיפו אותו לאמצעי הבקרה של מיפוי סוג).
  • שכבות-על של אריח תמונה שמוצגות מעל סוגי המפה הבסיסית. באופן כללי, סוגי המפות האלה משמשים להרחבת סוג מפה קיים להצגת מידע נוסף, ולרוב הם מוגבלים למיקומים ספציפיים או למרחק מהתצוגה. חשוב לשים לב שהמשבצות האלה עשויות להיות שקופות וכך לאפשר לך להוסיף תכונות למפות קיימות.
  • סוגי מפות שאינם תמונות, שמאפשרים לך לשנות את הצגת פרטי המפה ברמה הבסיסית ביותר שלהם.

בכל אחת מהאפשרויות האלה צריך ליצור כיתה שמטמיעה את הממשק 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() חייבת לכלול את החתימה הבאה:

    getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node

    ממשק ה-API קובע אם הוא צריך להתקשר אל getTile() על סמך המאפיינים MapType's tileSize, minZoom, maxZoom ואזור התצוגה והזום הנוכחיים של המפה. ה-handler בשיטה הזו צריך להחזיר רכיב HTML על סמך קואורדינטת הקואורדינטות, רמת המרחק מהתצוגה ורכיב ה-DOM שבהם רוצים להוסיף את תמונת המשבצת.

  • מופעלת קריאה ל-releaseTile() (אופציונלי) בכל פעם שה-API קובע שהמפה צריכה להסיר משבצת שהיא לא מופיעה. השיטה הזו חייבת לכלול את החתימה הבאה:

    releaseTile(tile:Node)

    בדרך כלל יש לטפל בהסרה של רכיבים שצורפו למשבצות המפה לאחר ההוספה למפה. לדוגמה, אם צירפת מאזינים לאירועים כדי למפות שכבות-על של משבצות, עליך להסיר אותן כאן.

השיטה getTile() משמשת כבקר הראשי לקביעת המשבצות שצריך לטעון בתוך אזור תצוגה נתון.

סוגים בסיסיים של מפות

סוגי המפות שיוצרים באופן זה יכולים לעמוד באופן עצמאי או בשילוב עם סוגי מפות אחרים כשכבות-על. סוגי המפות העצמאיים נקראים סוגי מפות בסיס. מומלץ להגדיר את ה-API כך שיתייחס ל-MapType כזה בהתאמה אישית כמו לכל סוג אחר של מפת בסיס (ROADMAP, TERRAIN וכו'). כדי לעשות את זה, צריך להוסיף את MapType המותאם אישית לנכס Map's mapTypes. הנכס הזה מסוג 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 קיים ישירות באמצעות המאפיין Map של overlayMapTypes. הנכס הזה מכיל 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 ב-Maps, כמו כל מפה שטוחה של כדור הארץ, היא קרינה של הכדור הזה על פני משטח שטוח. במונחים הפשוטים ביותר, ניתן להגדיר תחזית כמיפוי של ערכי קו רוחב/אורך בקואורדינטות של מפת ההקרנה.

תחזיות ב-Maps JavaScript API חייבות להטמיע את הממשק Projection. הטמעה של Projection חייבת לספק מיפוי של מערכת קואורדינטות אחת וגם מיפוי דו-כיווני. כלומר, צריך להגדיר איך לתרגם מהקואורדינטות של Earth (LatLng אובייקטים) למערכת Projection הקואורדינטות של העולם, ולהיפך. המערכת של מפות Google משתמשת בתחזית של Mercator כדי ליצור מפות מנתונים גיאוגרפיים ולהמיר אירועים במפה לקואורדינטות גיאוגרפיות. כדי לקבל את התחזית הזו, צריך להתקשר אל getProjection() בMap (או באחד מסוגי הבסיס הרגילים של MapType). לרוב השימושים, תקן Projection הרגיל הזה יספיק, אבל אפשר גם להגדיר חיזויים מותאמים אישית ולהשתמש בהם.

הטמעת תחזית

כשמטמיעים תחזית מותאמת אישית, צריך להגדיר כמה דברים:

  • הנוסחה למיפוי קואורדינטות של קווי אורך ורוחב במטוס קרטזי, ולהפך. (הממשק של Projection תומך רק בטרנספורמציות של קואורדינטות דיאקריטיות).
  • גודל אריח הבסיס. כל כרטיסי המידע חייבים להיות מלבניים.
  • "world size" של מפה באמצעות אריח הבסיס שהוגדר ברמת זום 0. חשוב לשים לב שעבור מפות שמורכבות מאריח אחד בזום 0, גודל העולם וגודל המשבצת הבסיסית זהים.

ניהול הטרנספורמציות בתחזיות

כל תחזית מספקת שתי שיטות שמתורגמות בין שתי מערכות הקואורדינטות האלה, ומאפשרות לך לבצע המרה בין קואורדינטות גיאוגרפיות וגלובליות:

  • השיטה Projection.fromLatLngToPoint() ממירה ערך של LatLng לקואורדינטות עולמי. השיטה הזו משמשת למיקום שכבות-על במפה (ולמיקום המפה עצמה).
  • השיטה Projection.fromPointToLatLng() ממירה קואורדינטות בעולם לערך LatLng. השיטה הזו משמשת להמרת אירועים כמו קליקים שמתרחשים במפה לקואורדינטות גיאוגרפיות.

במפות Google ההנחה היא שהתחזיות הן מקוטעות.

באופן כללי, אפשר להשתמש בתחזית לשני מקרים: כדי ליצור מפת העולם, או ליצור מפה של אזור מקומי. במקרה הקודם, עליך לוודא שהקרינה שלך היא גם רצפתית ורגילה בכל קווי האורך. חלק מהתחזיות (בעיקר תחזיות חרוט) עשויות להיות &ציטוט; מקומי מקומי" (כלומר בנקודה צפון) אך לסטות מצפון אמיתי. לדוגמה, ככל שהמפה תמוקם קרוב יותר לקו האורך הזה. ניתן להשתמש בתחזית הזו באופן מקומי, אבל חשוב לזכור שהסבירות לחיזוי היא לא מדויקת מספיק, וששגיאות בטרנספורמציה הופכות למרוחות יותר מאורך קו האורך.

בחירת אריחי מפה בהקרנות

תחזיות לא רק משפיעות על קביעת המיקום של מיקומים או שכבות-על, אלא גם על מיקום אריחי המפה עצמם. ה-API של מפות Google מאפשר עיבוד של מפות בסיס באמצעות ממשק MapType, שחייב להיות הצהרה על נכס projection גם לצורך זיהוי התחזית של המפה וגם שיטה getTile() לאחזור משבצות מפה על סמך ערכי קואורדינטות האריחים. נקודות הציון של האריחים מבוססות על גודל האריחים הבסיסיים (שחייבים להיות מלבניים) ועל ה&מירכאות;הגודל של העולם והציטוט של המפה: גודל הפיקסל של עולם המפה ברמת הזום 0. (עבור מפות הכוללות אריח אחד בזום 0, גודל האריחים וגודל העולם זהים).

ההגדרה של גודל אריח הבסיס בנכס MapType'tileSize היא. אתה מגדיר את הגודל העולמי באופן לא מפורש בשיטות ההקרנה שלך fromLatLngToPoint() ו-fromPointToLatLng().

מכיוון שבחרת תמונות תלויה בערכים שמועברים האלה, כדאי לתת שמות לתמונות שניתן לבחור באופן פרוגרמטי בהתאם לערכים שהועברו, כמו map_zoom_tileX_tileY.png.

בדוגמה הבאה מוגדר ImageMapType באמצעות ההקרנה Gallet 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"),
      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;
לצפייה בדוגמה

דוגמה