Tipe Peta

Pilih platform: Android iOS JavaScript

Dokumen ini membahas jenis peta yang dapat Anda tampilkan menggunakan Maps JavaScript API. API tersebut menggunakan objek MapType untuk menyimpan informasi tentang peta ini. MapType adalah antarmuka yang menentukan tampilan dan penggunaan ubin peta serta terjemahan sistem koordinat dari koordinat layar ke koordinat dunia (pada peta). Setiap MapType harus berisi beberapa metode untuk menangani proses pengambilan dan pelepasan ubin, serta properti yang menentukan perilaku visualnya.

Cara kerja internal jenis peta di Maps JavaScript API adalah topik lanjutan. Sebagian besar developer dapat menggunakan jenis peta dasar yang disebutkan di bawah ini. Namun, Anda juga dapat memodifikasi tampilan jenis peta yang ada menggunakan Maps Bergaya atau menentukan ubin peta Anda sendiri menggunakan jenis peta kustom. Saat memberikan jenis peta kustom, Anda perlu memahami cara memodifikasi Registry Jenis Peta.

Jenis Peta Dasar

Ada empat jenis peta yang tersedia dalam Maps JavaScript API. Selain ubin peta jalan "berwarna" yang sudah dikenal, Maps JavaScript API juga mendukung jenis peta lainnya.

Jenis peta berikut ini tersedia di Maps JavaScript API:

  • roadmap menampilkan tampilan peta jalan default dengan label peta dasar.
  • satellite menampilkan peta fotorealistik berdasarkan citra udara.
  • hybrid menampilkan tampilan peta satelit dengan label peta dasar.
  • terrain menampilkan peta fisik berdasarkan informasi medan.

Anda memodifikasi jenis peta yang digunakan oleh Map dengan menetapkan properti mapTypeId, baik di dalam konstruktor dengan menetapkan objek Map options, atau dengan memanggil metode setMapTypeId(). Secara default, properti mapTypeID ditetapkan ke roadmap.

Menetapkan mapTypeId saat pembuatan:

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

Mengubah mapTypeId secara dinamis:

map.setMapTypeId('terrain');

Perhatikan bahwa Anda sebenarnya tidak menetapkan jenis peta untuk peta tersebut secara langsung, tetapi menetapkan mapTypeId untuk mereferensikan MapType menggunakan ID. Maps JavaScript API menggunakan registry jenis peta, yang dijelaskan di bawah, untuk mengelola referensi ini.

Peta 3D

Maps JavaScript API mendukung gambar 3D. Banyak tindakan dan kemampuan penyesuaian yang tersedia untuk peta 2D juga tersedia untuk peta 3D.

Pelajari lebih lanjut peta 3D di ringkasan peta 3D.

Contoh berikut menampilkan tampilan perspektif 3D San Francisco:

Pelajari lebih lanjut Peta 3D di ringkasan peta 3D.

Gambar 45° (tidak digunakan lagi)

Contoh berikut menunjukkan cara mendapatkan tampilan perspektif 45° di San Francisco menggunakan peta 3D:

TypeScript

async function init() {
    const { Map3DElement } = await google.maps.importLibrary('maps3d');
    const map = new Map3DElement({
        center: {
            lat: 37.789,
            lng: -122.401,
            altitude: 0,
        },
        range: 2200,
        tilt: 45,
        heading: 188,
    });
    map.mode = 'SATELLITE';
    document.body.append(map);
}

void init();

JavaScript

async function init() {
    const { Map3DElement } = await google.maps.importLibrary('maps3d');
    const map = new Map3DElement({
        center: {
            lat: 37.789,
            lng: -122.401,
            altitude: 0,
        },
        range: 2200,
        tilt: 45,
        heading: 188,
    });
    map.mode = 'SATELLITE';
    document.body.append(map);
}

void init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#gmp-map-3d {
    height: 100%;
}
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

HTML

<html>
    <head>
        <title>3d map 45-degree perspective</title>
        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
                key: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <div id="map"></div>
    </body>
</html>
Lihat contoh

Memodifikasi Registry Jenis Peta

mapTypeId peta adalah ID string yang digunakan untuk mengaitkan MapType dengan nilai yang unik. Setiap objek Map mempertahankan MapTypeRegistry yang berisi kumpulan MapType yang tersedia untuk peta tersebut. Misalnya, registry ini digunakan untuk memilih jenis peta yang tersedia dalam kontrol MapType dari Map tersebut.

Anda tidak membaca langsung dari registry jenis peta. Melainkan, Anda memodifikasi registry dengan menambahkan jenis peta kustom dan mengaitkannya dengan ID string yang dipilih. Anda tidak dapat memodifikasi atau mengubah jenis peta dasar (meskipun Anda dapat menghapusnya dari peta dengan mengubah tampilan mapTypeControlOptions yang terkait dengan peta).

Kode berikut menetapkan peta untuk hanya menampilkan dua jenis peta dalam mapTypeControlOptions peta dan memodifikasi registry untuk menambahkan pengaitan dengan ID ini ke penerapan antarmuka MapType yang sesungguhnya.

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

Peta Bergaya

StyledMapType memungkinkan Anda menyesuaikan penyajian peta dasar Google standar, mengubah tampilan visual elemen seperti jalan, taman, dan area padat bangunan untuk mencerminkan gaya yang berbeda daripada yang digunakan dalam jenis peta default. StyledMapType hanya memengaruhi jenis peta roadmap default.

Untuk mengetahui informasi selengkapnya tentang StyledMapType, lihat Menggunakan deklarasi gaya JSON tersemat.

Jenis Peta Kustom

Maps JavaScript API mendukung tampilan dan pengelolaan jenis peta kustom, sehingga Anda dapat menerapkan gambar peta atau overlay ubin Anda sendiri.

Beberapa kemungkinan penerapan jenis peta tersedia dalam Maps JavaScript API:

  • Kumpulan ubin standar yang terdiri dari gambar yang secara kolektif membentuk peta kartografi lengkap. Kumpulan ubin ini juga disebut sebagai jenis peta dasar. Jenis peta ini berfungsi dan berperilaku seperti jenis peta default yang ada: roadmap, satellite, hybrid, dan terrain. Anda dapat menambahkan jenis peta kustom ke array mapTypes Peta untuk mengizinkan UI dalam Maps JavaScript API memperlakukan jenis peta kustom sebagai jenis peta standar (dengan menyertakannya dalam kontrol MapType, misalnya).
  • Overlay ubin gambar yang ditampilkan di atas jenis peta dasar yang sudah ada. Biasanya, jenis peta ini digunakan untuk meningkatkan jenis peta yang ada guna menampilkan informasi tambahan dan sering kali dibatasi pada lokasi dan/atau tingkat zoom tertentu. Perhatikan, ubin ini mungkin transparan, yang memungkinkan Anda menambahkan fitur ke peta yang ada.
  • Jenis peta bukan-gambar, yang memungkinkan Anda memanipulasi tampilan informasi peta pada tingkat yang paling mendasar.

Setiap opsi ini bergantung pada pembuatan class yang mengimplementasikan antarmuka MapType. Selain itu, class ImageMapType menyediakan beberapa perilaku bawaan untuk menyederhanakan pembuatan jenis peta gambar.

Antarmuka MapType

Sebelum membuat class yang menerapkan MapType, Anda harus memahami cara Google Maps menentukan koordinat dan memutuskan bagian peta yang akan ditampilkan. Anda perlu menerapkan logika serupa untuk setiap jenis peta dasar atau overlay. Baca panduan untuk koordinat peta dan ubin.

Jenis peta kustom harus mengimplementasikan antarmuka MapType. Antarmuka ini menetapkan beberapa properti dan metode yang memungkinkan API membuat permintaan ke jenis peta Anda jika API perlu menampilkan ubin peta dalam area tampilan yang terlihat dan tingkat zoom saat ini. Anda menangani permintaan ini untuk memutuskan ubin mana yang dimuat.

Catatan: Anda dapat membuat class sendiri untuk menerapkan antarmuka ini. Atau, jika memiliki gambar yang kompatibel, Anda dapat menggunakan class ImageMapType yang telah mengimplementasikan antarmuka ini.

Class yang mengimplementasikan antarmuka MapType mengharuskan Anda menentukan dan mengisi properti berikut:

  • tileSize (diperlukan) menentukan ukuran ubin (dengan jenis google.maps.Size). Ukuran harus persegi panjang meskipun tidak perlu berbentuk persegi.
  • maxZoom (diperlukan) menentukan tingkat zoom maksimum untuk menampilkan ubin jenis peta ini.
  • minZoom (opsional) menentukan tingkat zoom minimum untuk menampilkan ubin jenis peta ini. Secara default, nilai ini adalah 0 yang menunjukkan bahwa tidak ada tingkat zoom minimum.
  • name (opsional) menentukan nama untuk jenis peta ini. Properti ini hanya diperlukan jika Anda ingin jenis peta ini dapat dipilih dalam kontrol MapType. (Lihat Opsi Kontrol.)
  • alt (opsional) menentukan teks alternatif untuk jenis peta ini, yang ditampilkan sebagai teks pengarahan kursor. Properti ini hanya diperlukan jika ingin jenis peta ini dapat dipilih dalam kontrol MapType. (Lihat Opsi Kontrol.)

Selain itu, class yang mengimplementasikan antarmuka MapType perlu mengimplementasikan metode berikut:

  • getTile() (diperlukan) dipanggil setiap kali API menentukan bahwa peta perlu menampilkan ubin baru untuk area tampilan tertentu. Metode getTile() ini harus memiliki tanda tangan berikut:

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

    API menentukan apakah perlu memanggil getTile() berdasarkan properti tileSize, minZoom, dan maxZoom dari MapType serta area tampilan dan tingkat zoom saat ini di peta. Pengendali untuk metode ini akan menampilkan elemen HTML dengan memberikan koordinat yang diteruskan, tingkat zoom, dan elemen DOM yang akan ditambahkan gambar ubin.

  • releaseTile() (opsional) dipanggil setiap kali API menentukan bahwa peta perlu menghapus ubin karena tidak masuk area tampilan. Metode ini harus memiliki tanda tangan berikut:

    releaseTile(tile:Node)

    Anda biasanya harus menangani penghapusan elemen yang terlampir ke ubin peta saat penambahan ke peta. Misalnya, jika Anda melampirkan pemroses peristiwa untuk memetakan overlay ubin peta, Anda harus menghapusnya di sini.

Metode getTile() berfungsi sebagai pengontrol utama untuk menentukan ubin yang akan dimuat dalam area tampilan tertentu.

Jenis Peta Dasar

Jenis peta yang Anda buat dengan cara ini dapat berdiri sendiri atau dikombinasikan dengan jenis peta lain sebagai overlay. Jenis peta mandiri dikenal sebagai jenis peta dasar. Anda mungkin ingin agar API memperlakukan MapType kustom tersebut seperti halnya jenis peta dasar lainnya yang sudah ada (ROADMAP, TERRAIN, dll.). Untuk melakukannya, tambahkan MapType kustom Anda ke properti mapTypes Map. Properti ini berjenis MapTypeRegistry.

Kode berikut membuat MapType dasar untuk menampilkan koordinat ubin peta dan menggambar garis luar ubin:

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;
Lihat contoh

Jenis Peta Overlay

Beberapa jenis peta didesain untuk berfungsi sebagai tambahan atas jenis peta yang ada. Jenis peta tersebut mungkin memiliki lapisan transparan yang menunjukkan tempat menarik, atau menampilkan data tambahan kepada pengguna.

Dalam hal ini, Anda tidak ingin jenis peta tersebut diperlakukan sebagai entitas terpisah tetapi sebagai overlay. Anda dapat melakukannya dengan menambahkan jenis peta ke MapType yang ada secara langsung menggunakan properti overlayMapTypes dari Map. Properti ini berisi MVCArray dari MapType. Semua jenis peta (dasar dan overlay) dirender dalam lapisan mapPane. Jenis peta overlay akan ditampilkan di atas peta dasar yang terkait dengannya, sesuai dengan urutan kemunculannya dalam array Map.overlayMapTypes (overlay dengan nilai indeks yang lebih tinggi ditampilkan di depan overlay dengan nilai indeks yang lebih rendah).

Contoh berikut identik dengan sebelumnya kecuali jika kami telah membuat overlay ubin MapType sebagai tambahan atas jenis peta 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;
Lihat contoh

Jenis Peta Gambar

Mengimplementasikan MapType untuk berfungsi sebagai jenis peta dasar bisa menjadi tugas yang memakan waktu dan melelahkan. API ini menyediakan class khusus yang mengimplementasikan antarmuka MapType untuk jenis peta paling umum: jenis peta yang terdiri dari ubin yang terdiri dari file gambar tunggal.

Class ini, class ImageMapType, dibuat menggunakan spesifikasi objek ImageMapTypeOptions yang menentukan properti yang diperlukan berikut ini:

  • tileSize (diperlukan) menentukan ukuran ubin (dengan jenis google.maps.Size). Ukuran harus persegi panjang meskipun tidak perlu berbentuk persegi.
  • getTileUrl (diperlukan) menetapkan fungsi, biasanya disediakan sebagai literal fungsi segaris, untuk menangani pemilihan ubin gambar yang tepat berdasarkan koordinat dunia dan tingkat zoom yang diberikan.

Kode berikut menerapkan ImageMapType dasar menggunakan ubin bulan Google. Contoh ini menggunakan fungsi normalisasi untuk memastikan ubin diulang di sepanjang sumbu x, tetapi tidak di sepanjang sumbu y pada peta Anda.

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;
Lihat contoh

Proyeksi

Bumi adalah sebuah bola tiga dimensi (kurang-lebih), sedangkan sebuah peta adalah permukaan datar dua dimensi. Peta yang Anda lihat dalam Maps JavaScript API, seperti peta datar Bumi pada umumnya, adalah proyeksi bola bumi pada permukaan datar. Dalam istilah paling sederhana, proyeksi bisa didefinisikan sebagai pemetaan dari nilai garis lintang/garis bujur ke dalam koordinat pada peta proyeksi.

Proyeksi di Maps JavaScript API harus menerapkan antarmuka Projection. Implementasi Projection tidak hanya harus memberikan pemetaan dari satu sistem koordinat ke sistem koordinat lainnya, tetapi juga pemetaan dua arah. Artinya, Anda harus menentukan cara menerjemahkan dari koordinat Earth (objek LatLng) ke sistem koordinat dunia dari class Projection, dan dari sistem koordinat dunia kembali ke koordinat Earth. Google Maps menggunakan proyeksi Mercator untuk membuat peta dari data geografis dan mengonversi peristiwa di peta ke dalam koordinat geografis. Anda dapat memperoleh proyeksi ini dengan memanggil getProjection() pada Map (atau salah satu jenis MapType dasar standar.) Untuk sebagian besar penggunaan, Projection standar ini sudah cukup, tetapi Anda juga dapat menentukan dan menggunakan proyeksi kustom Anda sendiri.

Mengimplementasikan Proyeksi

Saat mengimplementasikan proyeksi khusus, Anda perlu mendefinisikan beberapa hal:

  • Rumus untuk memetakan koordinat lintang dan bujur menjadi bidang Kartesius dan rumus yang sesuai untuk memetakan dari bidang Kartesius ke koordinat lintang dan bujur. (Antarmuka Projection hanya mendukung transformasi menjadi koordinat garis lurus.)
  • Ukuran ubin dasar. Semua ubin harus persegi panjang.
  • "Ukuran dunia" pada peta menggunakan ubin dasar yang ditetapkan pada tingkat zoom 0. Perhatikan, untuk peta yang terdiri dari satu ubin di tingkat zoom 0, ukuran bumi dan ukuran ubin dasar identik.

Transformasi Koordinat dalam Proyeksi

Setiap proyeksi menyediakan dua metode yang menerjemahkan dua sistem koordinat ini, yang memungkinkan Anda mengonversi antara koordinat geografis dan koordinat dunia:

  • Metode Projection.fromLatLngToPoint() mengonversi nilai LatLng menjadi koordinat dunia. Metode ini digunakan untuk memosisikan overlay pada peta (dan memosisikan peta itu sendiri).
  • Metode Projection.fromPointToLatLng() mengonversi koordinat dunia menjadi nilai LatLng. Metode ini digunakan untuk mengonversi peristiwa seperti klik yang terjadi di peta menjadi koordinat geografis.

Google Maps beranggapan proyeksi berupa garis lurus.

Biasanya, Anda dapat menggunakan proyeksi untuk dua kasus: untuk membuat peta dunia, atau untuk membuat peta area lokal. Dalam kasus pertama, Anda harus memastikan proyeksi tersebut berupa garis lurus dan normal pada semua garis bujur. Beberapa proyeksi (terutama proyeksi kerucut) mungkin "secara lokal normal" (yaitu titik utara), tetapi menyimpang dari utara sebenarnya, misalnya, makin jauh peta diposisikan sesuai dengan beberapa garis bujur referensi. Anda dapat menggunakan proyeksi tersebut secara lokal, tetapi perhatikan bahwa proyeksi tersebut tentunya tidak akurat dan kesalahan transformasi akan menjadi jelas jika Anda makin jauh menyimpang dari garis bujur referensi.

Pilihan Ubin Peta dalam Proyeksi

Proyeksi tidak hanya berguna untuk menentukan posisi lokasi atau overlay, juga untuk memosisikan ubin peta itu sendiri. Maps JavaScript API merender peta dasar menggunakan MapType, yang harus mendeklarasikan properti projection untuk mengidentifikasi proyeksi peta dan metode getTile() untuk mengambil ubin peta berdasarkan koordinat ubin. Koordinat ubin berdasarkan pada ukuran ubin dasar Anda (yang harus persegi panjang) dan "ukuran dunia" peta Anda, yang merupakan ukuran piksel dari peta dunia Anda pada tingkat zoom 0. (Untuk peta yang terdiri dari satu ubin pada tingkat zoom 0, ukuran ubin dan ukuran dunia adalah identik.)

Anda menentukan ukuran ubin dasar dalam properti tileSize MapType. Anda menentukan ukuran dunia secara implisit dalam metode fromLatLngToPoint() dan fromPointToLatLng() proyeksi.

Karena pemilihan gambar bergantung pada nilai yang diteruskan ini, sebaiknya beri nama pada gambar yang dapat dipilih secara terprogram dengan nilai yang diteruskan tersebut, seperti map_zoom_tileX_tileY.png.

Contoh berikut menentukan ImageMapType menggunakan proyeksi Gall-Peters:

TypeScript

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
const mapElement = document.querySelector('gmp-map')!;
let innerMap: google.maps.Map;

async function init() {
    // Request the needed libraries.
    await google.maps.importLibrary('maps');

    // Create a map.
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });

    // Set the Gall-Peters map type.
    const gallPetersMapType = await initGallPeters();
    innerMap.mapTypes.set('gallPeters', gallPetersMapType);
    innerMap.setMapTypeId('gallPeters');

    // Show the lat and lng under the mouse cursor.
    const coordsDiv = document.getElementById('coords')!;

    innerMap.addListener('mousemove', (event: google.maps.MapMouseEvent) => {
        coordsDiv.textContent = `lat: ${String(Math.round(event.latLng!.lat()))}, lng: ${String(Math.round(event.latLng!.lng()))}`;
    });

    // Add some markers to the map.
    innerMap.data.setStyle((feature) => {
        return {
            title: feature.getProperty('name') as string,
            optimized: false,
        };
    });
    innerMap.data.addGeoJson(cities);
}

async function initGallPeters(): Promise<google.maps.ImageMapType> {
    const [{ ImageMapType }, { Size, Point, LatLng }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('core'),
    ]);

    const GALL_PETERS_RANGE_X = 800;
    const GALL_PETERS_RANGE_Y = 512;

    // Fetch Gall-Peters tiles stored locally on our server.
    const gallPetersMapType = new ImageMapType({
        getTileUrl(coord, zoom) {
            const scale = 1 << zoom;

            // Wrap tiles horizontally.
            const x = ((coord.x % scale) + scale) % scale;

            // Don't wrap tiles vertically.
            const y = coord.y;

            if (y < 0 || y >= scale) return '';

            return `gall-peters_${String(zoom)}_${String(x)}_${String(y)}.png`;
        },
        tileSize: new 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(latLng: google.maps.LatLng) {
            const latRadians = (latLng.lat() * Math.PI) / 180;
            return new Point(
                GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
                GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))
            );
        },
        fromPointToLatLng(point: google.maps.Point, noWrap?: boolean) {
            const x = point.x / GALL_PETERS_RANGE_X;
            const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));

            return new LatLng(
                (Math.asin(1 - 2 * y) * 180) / Math.PI,
                -180 + 360 * x,
                noWrap
            );
        },
    };

    return gallPetersMapType;
}

// 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' },
        },
    ],
};

void init();

JavaScript

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
const mapElement = document.querySelector('gmp-map');
let innerMap;

async function init() {
    // Request the needed libraries.
    await google.maps.importLibrary('maps');

    // Create a map.
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });

    // Set the Gall-Peters map type.
    const gallPetersMapType = await initGallPeters();
    innerMap.mapTypes.set('gallPeters', gallPetersMapType);
    innerMap.setMapTypeId('gallPeters');

    // Show the lat and lng under the mouse cursor.
    const coordsDiv = document.getElementById('coords');

    innerMap.addListener('mousemove', (event) => {
        coordsDiv.textContent = `lat: ${String(Math.round(event.latLng.lat()))}, lng: ${String(Math.round(event.latLng.lng()))}`;
    });

    // Add some markers to the map.
    innerMap.data.setStyle((feature) => {
        return {
            title: feature.getProperty('name'),
            optimized: false,
        };
    });
    innerMap.data.addGeoJson(cities);
}

async function initGallPeters() {
    const [{ ImageMapType }, { Size, Point, LatLng }] = await Promise.all([
        google.maps.importLibrary('maps'),
        google.maps.importLibrary('core'),
    ]);

    const GALL_PETERS_RANGE_X = 800;
    const GALL_PETERS_RANGE_Y = 512;

    // Fetch Gall-Peters tiles stored locally on our server.
    const gallPetersMapType = new ImageMapType({
        getTileUrl(coord, zoom) {
            const scale = 1 << zoom;

            // Wrap tiles horizontally.
            const x = ((coord.x % scale) + scale) % scale;

            // Don't wrap tiles vertically.
            const y = coord.y;

            if (y < 0 || y >= scale) return '';

            return `gall-peters_${String(zoom)}_${String(x)}_${String(y)}.png`;
        },
        tileSize: new 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(latLng) {
            const latRadians = (latLng.lat() * Math.PI) / 180;
            return new Point(
                GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
                GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))
            );
        },
        fromPointToLatLng(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 LatLng(
                (Math.asin(1 - 2 * y) * 180) / Math.PI,
                -180 + 360 * x,
                noWrap
            );
        },
    };

    return gallPetersMapType;
}

// 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' },
        },
    ],
};

void init();
Lihat contoh