Typy map

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
Wybierz platformę: Android iOS JavaScript

W tym dokumencie opisujemy typy map, które można wyświetlać za pomocą interfejsu Maps JavaScript API. Interfejs API używa obiektu MapType do przechowywania informacji o tych mapach. MapType to interfejs, który określa wyświetlanie i wykorzystywanie kafelków mapy oraz tłumaczenie systemów współrzędnych ze współrzędnych ekranu na współrzędne geograficzne (na mapie). Każdy element MapType musi zawierać kilka metod pobierania i udostępniania kafelków oraz właściwości, które definiują jego wygląd.

Podstawowe informacje o typach map w interfejsie Maps JavaScript API są zaawansowane. Większość deweloperów może korzystać z wymienionych niżej podstawowych typów map. Możesz jednak zmodyfikować sposób wyświetlania istniejących typów map w Mapach stylizowanych lub zdefiniować własne kafelki, korzystając z niestandardowych typów map. Jeśli udostępniasz niestandardowe typy map, musisz wiedzieć, jak zmienić rejestr rejestru map.

Podstawowe typy map

W interfejsie Maps JavaScript API dostępne są 4 typy map. Oprócz znanych malowanych fragmentów mapy drogi interfejs API JavaScript Map Google obsługuje również inne typy map.

W Maps API API są dostępne te typy map:

  • roadmap wyświetla domyślny widok mapy drogi. To jest domyślny typ mapy.
  • satellite wyświetla zdjęcia satelitarne Google Earth.
  • hybrid wyświetla widok normalny i satelitarny.
  • terrain wyświetla fizyczną mapę na podstawie informacji o terenie.

Możesz zmienić typ mapy, której używa Map, ustawiając jego właściwość mapTypeId w konstruktorze, ustawiając obiekt Map options lub wywołując metodę setMapTypeId() mapy. Właściwość mapTypeID przyjmuje domyślnie wartość roadmap.

Ustawianie mapTypeId podczas tworzenia:

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);

Dynamicznie modyfikując plik mapTypeId:

map.setMapTypeId('terrain');

Pamiętaj, że nie ustawiasz bezpośrednio typu mapy na mapie, tylko ustawiasz jej mapTypeId jako odwołanie do MapType za pomocą identyfikatora. Do zarządzania tymi odwołaniami interfejs Maps JavaScript API korzysta z rejestru typów map opisanego poniżej.

Zdjęcia pod kątem 45°

Interfejs Maps JavaScript API obsługuje specjalne zdjęcia 45° w niektórych lokalizacjach. Zdjęcia w wysokiej rozdzielczości pozwalają zobaczyć punkty widzenia we wszystkich kierunkach (północ, południe, wschód, zachód). Są one dostępne na wyższych poziomach powiększenia w przypadku obsługiwanych typów map.

Poniższa ilustracja przedstawia widok Nowego Jorku pod kątem 45°:

Typy mapy satellite i hybrid obsługują zdjęcia pod kątem 45°, przy wysokiej powiększeniu (12 lub wyższym), o ile są dostępne. Jeśli użytkownik powiększy lokalizację, w której znajdują się takie zdjęcia, te typy map automatycznie zmienią widok w taki sposób:

  • Zdjęcia satelitarne lub hybrydowe są zastępowane zdjęciami przedstawiającymi widok pod kątem 45° i wyśrodkowanymi na bieżącej lokalizacji. Domyślnie są one ustawione na północ. Jeśli użytkownik pomniejszy widok, ponownie pojawią się domyślne zdjęcia satelitarne lub hybrydowe. Działanie różni się w zależności od poziomu powiększenia i wartości tilt:
    • W przypadku poziomów powiększenia od 12 do 18 domyślnie wyświetlana jest mapa bazowa u góry (0°), chyba że tilt ma wartość 45.
    • W przypadku powiększenia o wartości co najmniej 18° wyświetla się mapa podstawowa 45°, chyba że tilt ma wartość 0.
  • Pojawi się element sterujący obrotem. Element sterujący obrotem udostępnia opcje, które pozwalają użytkownikowi przełączać się między pochyleniem a obrótem o 90° w obu kierunkach. Aby ukryć kontrolkę rotacji, ustaw rotateControl na false.

Pomniejszenie typu mapy, w którym wyświetlane są zdjęcia pod kątem 45°, powoduje cofnięcie każdej z tych zmian i ponowne utworzenie oryginalnych typów map.

Włączanie i wyłączanie zdjęć pod kątem 45°

Obrazy pod kątem 45° można wyłączyć, wywołując setTilt(0) w obiekcie Map. Aby włączyć obsługę zdjęć pod kątem 45° w przypadku obsługiwanych typów mapy, wywołaj setTilt(45). Metoda getTilt() obiektu Map zawsze odzwierciedla bieżący obiekt tilt wyświetlany na mapie. Jeśli ustawisz tilt na mapie, a później usuniesz ją (np. przez pomniejszenie mapy), metoda getTilt() mapy zwróci 0.

Ważne: zdjęcia 45° są obsługiwane tylko na mapach rastrowych. Nie można ich używać w mapach wektorowych.

Poniższy przykład pokazuje widok 45° Nowego Jorku:

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;
Zobacz przykład

Fragment

Zobacz przykład

Obracanie zdjęć pod kątem 45°

Obraz pod kątem 45° składa się z zestawu obrazów widocznych w każdym kierunku (północ, południe, wschód, zachód). Gdy na mapie pojawią się zdjęcia pod kątem 45°, możesz ustawić je w kierunku jednego z jego podstawowych kierunków, wywołując obiekt setHeading() w obiekcie Map, przekazując wartość liczbową wyrażoną jako stopni od północy.

Ten przykład pokazuje mapę z lotu ptaka i automatycznie obraca mapę co 3 sekundy po kliknięciu przycisku:

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;
Zobacz przykład

Fragment

Zobacz przykład

Modyfikowanie rejestru typu mapy

mapTypeId mapy to identyfikator ciągu znaków używany do powiązania wartości MapType z unikalną wartością. Każdy obiekt Map zawiera MapTypeRegistry, który zawiera zbiór dostępnych dla tej mapy obiektów MapType. Ten rejestr służy do wybierania typów map dostępnych na przykład w funkcji MapType MapType.

Nie czytaj bezpośrednio z rejestru typów map. Zamiast tego modyfikuj rejestr, dodając niestandardowe typy map i wiążąc je z wybranym identyfikatorem ciągu znaków. Nie można zmieniać ani zmieniać podstawowych typów map (chociaż można je usunąć z mapy, modyfikując wygląd powiązanego z nimi elementu mapTypeControlOptions).

Poniższy kod ustawia na mapie tylko mapTypeControlOptions typów mapy i zmienia rejestr, aby dodać powiązanie z tym identyfikatorem do rzeczywistej implementacji interfejsu 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);

Stylizowane Mapy Google

Komponent StyledMapType umożliwia dostosowywanie sposobu wyświetlania standardowych map podstawowych Google. Pozwala to zmieniać wygląd takich elementów jak drogi, parki i tereny zabudowane, tak aby uwzględniały inny styl niż ten używany w domyślnym typie mapy.

Więcej informacji o StyledMapType znajdziesz w przewodniku po mapach stylów.

Niestandardowe typy map

Interfejs Maps JavaScript API obsługuje wyświetlanie niestandardowych typów map i zarządzanie nimi, dzięki czemu możesz wdrażać własne obrazy map i nakładki na kafelki.

W interfejsie Maps JavaScript API dostępnych jest kilka różnych implementacji map:

  • Standardowe zestawy kafelków zawierające obrazy, które razem stanowią pełne mapy kartograficzne. Zestawy kafelków są też nazywane mapami podstawowymi. Te typy map działają i zachowują się jak istniejące domyślne typy map: roadmap, satellite, hybrid i terrain. Możesz dodać niestandardowy typ mapy do tablicy mapTypes mapy, aby umożliwić interfejsowi API JavaScript Map Google traktować go jako standardowy typ mapy (np. dodając go do elementu MapType).
  • Nakładki graficzne wyświetlane na istniejących podstawowych typach map. Ogólnie te typy map służą do uzupełnienia istniejącego typu mapy w celu wyświetlenia dodatkowych informacji. Często są one ograniczone do określonych lokalizacji lub poziomów powiększenia. Te kafelki mogą być przezroczyste, dzięki czemu możesz dodawać funkcje do istniejących map.
  • Typy map inne niż graficzne, które umożliwiają manipulowanie wyświetlaniem informacji na mapie na najbardziej podstawowym poziomie.

Każda z nich wymaga utworzenia klasy implementującej interfejs MapType. Klasa ImageMapType zawiera też wbudowane funkcje ułatwiające tworzenie typów map obrazów.

Interfejs MapType

Zanim utworzysz klasy, które implementują właściwość MapType, musisz zrozumieć, w jaki sposób Mapy Google określają współrzędne i decydują, które części mapy mają być wyświetlane. Musisz zastosować podobną logikę do każdego typu mapy bazowej lub nakładki. Przeczytaj przewodnik po współrzędnych map i kafelkach.

Niestandardowe typy map muszą implementować interfejs MapType. Ten interfejs określa niektóre właściwości i metody, które pozwalają interfejsowi API na wysyłanie żądań do Twoich typów map, gdy interfejs API wykryje, że w tym widoku będą wyświetlać fragmenty mapy w bieżącym widoku i poziomie powiększenia. Przetwarzasz te żądania, aby zdecydować, który kafelek ma wczytać.

Uwaga: aby wdrożyć ten interfejs, możesz utworzyć własną klasę. Jeśli masz zgodne obrazy, możesz też użyć klasy ImageMapType, która zawiera już ten interfejs.

Klasy implementujące interfejs interfejsu MapType wymagają zdefiniowania i uzupełnienia tych właściwości:

  • tileSize (wymagany) określa rozmiar kafelka (typu google.maps.Size). Rozmiary muszą być prostokątne, ale nie muszą być kwadratowe.
  • maxZoom (wymagane) określa maksymalny poziom powiększenia, przy którym wyświetlają się fragmenty mapy tego typu.
  • minZoom (opcjonalne) określa minimalny poziom powiększenia, na którym należy wyświetlać kafelek tego typu mapy. Domyślnie ta wartość to 0, co oznacza, że nie istnieje minimalny poziom powiększenia.
  • name (opcjonalnie) określa nazwę tego typu mapy. Ta właściwość jest potrzebna tylko wtedy, gdy chcesz, aby ten typ mapy można było wybrać w sekcji MapType. (patrz Dodawanie elementów sterujących MapType poniżej).
  • alt (opcjonalnie) określa tekst zastępczy tego typu mapy wyświetlany jako tekst po najechaniu kursorem myszy. Ta właściwość jest potrzebna tylko wtedy, gdy chcesz, aby ten typ mapy można było wybrać za pomocą elementu MapType. (patrz niżej: Dodawanie elementów sterujących MapType).

Klasy implementujące interfejs MapType muszą implementować te metody:

  • Parametr getTile() (wymagany) jest wywoływany za każdym razem, gdy interfejs API wykryje, że na danym obszarze mapy konieczne jest wyświetlanie nowych kafelków. Metoda getTile() musi mieć ten podpis:

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

    Interfejs API określa, czy należy go wywoływać getTile() na podstawie właściwości tileSize, minZoom i maxZoom właściwości MapType oraz bieżącego poziomu widocznego obszaru i powiększenia mapy. Moduł obsługi tej metody powinien zwracać element HTML na podstawie przekazanej współrzędnej, poziomu powiększenia i elementu DOM, w którym jest dołączany obraz kafelka.

  • Flaga releaseTile() (opcjonalnie) jest wywoływana za każdym razem, gdy interfejs API wykryje, że mapa musi usunąć kafelek, który zniknie z widoku. Ta metoda musi mieć następujący podpis:

    releaseTile(tile:Node)

    Zwykle po usunięciu wszystkich elementów dołączonej do map należy usunąć elementy. Jeśli na przykład załączasz detektory zdarzeń, aby mapować nakładki na kafelki, usuń je tutaj.

Metoda getTile() działa jako główny kontroler określający, które kafelki mają być wczytywane w danym widoku.

Podstawowe typy map

Utworzone w ten sposób typy map mogą działać oddzielnie lub łączyć się z innymi typami map jako nakładki. Samodzielne typy map są nazywane typami map podstawowych. Możesz zdecydować, aby interfejs API traktował takie niestandardowe obiekty MapType tak samo jak dowolne inne istniejące typy map podstawowych (ROADMAP, TERRAIN itd.). Aby to zrobić, dodaj niestandardową właściwość MapType do właściwości mapTypes w usłudze Map. Ta właściwość jest typu MapTypeRegistry.

Następujący kod tworzy bazową zasadę MapType, aby wyświetlać współrzędne fragmentu mapy i rysować kontur kafelków:

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;
Zobacz przykład

Fragment

Typy map nakładek

Niektóre typy map zostały opracowane tak, by działały na istniejących typach map. Tego typu mapy mogą mieć przezroczyste warstwy wskazujące ciekawe miejsca lub prezentować dodatkowe dane użytkownikowi.

W takich przypadkach nie chcesz, aby typ mapy był traktowany jako osobny element, ale jako nakładka. Możesz to zrobić, dodając typ mapy do istniejącego elementu MapType bezpośrednio za pomocą właściwości overlayMapTypes właściwości Map. Ta właściwość zawiera MVCArray z MapType. Wszystkie typy map (podstawa i nakładka) są renderowane w warstwie mapPane. Typy map nałożonych są wyświetlane nad mapą podstawową, do której są podłączone, w kolejności, w której występują na tablicy Map.overlayMapTypes (nakładki z wyższymi wartościami indeksu są wyświetlane przed nakładkami o niższych wartościach indeksu).

Poniższy przykład jest taki sam jak poprzedni, z tym że utworzyliśmy MapType nakładkę kafelkową nad mapą 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;
Zobacz przykład

Fragment

Typy map obrazów

Wdrożenie MapType jako mapy podstawowej może być czasochłonne i żmudne. Interfejs API udostępnia specjalną klasę, która implementuje interfejs MapType do najpopularniejszych typów map – typów map złożonych z kafelków z pojedynczych plików graficznych.

Ta klasa ImageMapType jest tworzona na podstawie specyfikacji obiektu ImageMapTypeOptions zdefiniowanej według tych wymaganych właściwości:

  • tileSize (wymagany) określa rozmiar kafelka (typu google.maps.Size). Rozmiary muszą być prostokątne, ale nie muszą być kwadratowe.
  • getTileUrl (wymagany) określa funkcję (zwykle wbudowaną literał funkcyjny) do wybierania odpowiedniego kafelka obrazu na podstawie przesłanych współrzędnych świata i poziomu powiększenia.

Poniższy kod implementuje podstawowy element ImageMapType przy użyciu kafelków księżycowych Google. W tym przykładzie użyto funkcji normalizacji, aby mieć pewność, że kafelki będą się powtarzać na osi X, ale nie na osi Y mapy.

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;
Zobacz przykład

Fragment

Prognozy

Ziemia to trójwymiarowe sfera (ok. powierzchnia), natomiast mapa jest płaską dwuwymiarową powierzchnią. Mapa, którą widzisz w interfejsie Maps JavaScript API, tak jak każda płaska mapa Ziemi, to odwzorowanie tej kuli na płaskiej powierzchni. Mówiąc najprościej, odwzorowanie można zdefiniować jako mapowanie wartości szerokości i długości geograficznej na współrzędne na mapie.

Prognozy w interfejsie Maps API API muszą implementować interfejs Projection. Implementacja Projection musi zapewniać mapowanie nie tylko z jednego systemu współrzędnych do drugiego, ale też z dwukierunkowego. Oznacza to, że musisz zdefiniować sposób tłumaczenia ze współrzędnych Earth (obiekty LatLng) na system współrzędnych światowych klasy Projection i odwrotnie. Mapy Google wykorzystują odwzorowanie Merkatora do tworzenia map na podstawie danych geograficznych i przekształcania zdarzeń na mapie w współrzędne geograficzne. Możesz uzyskać to odwzorowanie, wywołując getProjection() w Map (lub w dowolnym typie bazy MapType). W większości przypadków wystarczy standardowy Projection, ale możesz też zdefiniować i wykorzystać własne odwzorowania.

Wdrażanie projekcji

Implementując odwzorowanie niestandardowe, musisz zdefiniować kilka rzeczy:

  • Wzór do mapowania szerokości i długości geograficznej na kartę kartezjańską i na odwrót. (Interfejs Projection obsługuje tylko przekształcenia we współrzędne prostokątne).
  • Rozmiar kafelka podstawowego. Wszystkie kafelki muszą być prostokątne.
  • „Rozmiar świata” mapy za pomocą kafelka podstawowego ustawionego na poziomie powiększenia 0. Pamiętaj, że w przypadku map składających się z jednego kafelka w powiększenia 0 rozmiar świata i podstawowy kafelek są identyczne.

Przekształć współrzędne w prognozach

Każde odwzorowanie udostępnia 2 metody tłumaczenia między 2 systemami współrzędnych, co umożliwia przechodzenie między współrzędnymi geograficznymi i światowymi:

  • Metoda Projection.fromLatLngToPoint() konwertuje wartość LatLng na współrzędną światową. Ta metoda służy do określania pozycji na mapie (i do określania jej pozycji).
  • Metoda Projection.fromPointToLatLng() konwertuje współrzędną świata na wartość LatLng. Ta metoda służy do konwertowania zdarzeń takich jak kliknięcia na mapie na współrzędne geograficzne.

Mapy Google zakładają, że prognozy są prostokątne.

Ogólnie rzecz biorąc, odwzorowanie można zastosować w dwóch przypadkach: utworzyć mapę świata lub utworzyć mapę okolicy. W pierwszym przypadku upewnij się, że odwzorowanie jest proste i normalne we wszystkich długościach geograficznych. Niektóre odchylenia (szczególnie odwzorowania stożkowe) mogą być „lokalne „normalne” (np.wskazujące północ), ale odbiegać od rzeczywistej północy, np. bardziej umiejscowić mapę względem określonej długości geograficznej. Możesz używać takiego odwzorowania lokalnie, ale musi być niedokładne, a błędy przekształcania będą coraz bardziej odbiegać od odejmowanej długości geograficznej odniesienia.

Wybór fragmentu mapy w odwzorowaniach

Odwzorowania są przydatne nie tylko do określania położenia lokalizacji i nakładek, ale także do pozycjonowania fragmentów mapy. Interfejs Maps JavaScript API renderuje mapy podstawowe za pomocą interfejsu MapType, który musi deklarować zarówno właściwość projection do identyfikowania odwzorowania, jak i metodę getTile() pobierania fragmentów na podstawie wartości współrzędnych. Współrzędne fragmenty są oparte zarówno na podstawowym rozmiarze kafelka (który musi być prostokątny), jak i na „globalnym rozmiarze” mapy, czyli na pikselach miejsca na mapie, w którym użytkownik powiększa się na poziomie powiększenia 0. (w przypadku map zawierających 1 kafelek w zoomie 0 rozmiar kafelka jest taki sam jak na świecie).

Rozmiar podstawowego kafelka definiujesz we właściwości tileSize obiektu MapType. Rozmiar światowy jest określany bezpośrednio w metodach fromLatLngToPoint() i fromPointToLatLng() w prognozie.

Wybór obrazów zależy od tych przekazywanych wartości, dlatego warto nazwać obrazy, które można wybrać automatycznie na podstawie podanych wartości, np. map_zoom_tileX_tileY.png.

Ten przykład definiuje obiekt ImageMapType za pomocą prognozy 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"),
      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;
Zobacz przykład

Fragment