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. Ini adalah jenis peta default.satellite
menampilkan gambar satelit Google Earth.hybrid
menampilkan gabungan tampilan normal dan satelit.terrain
menampilkan peta fisik berdasarkan informasi medan.
Anda memodifikasi jenis peta yang digunakan oleh Map
dengan
menetapkan properti mapTypeId
, baik di dalam konstruktor melalui
penetapan 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.
Gambar 45°
Maps JavaScript API mendukung gambar 45° spesial untuk lokasi tertentu. Gambar resolusi tinggi ini memberikan tampilan perspektif terhadap setiap arah mata angin (Utara, Selatan, Timur, Barat). Gambar-gambar ini tersedia pada tingkat zoom yang lebih tinggi untuk jenis peta yang didukung.
Gambar berikut menampilkan tampilan perspektif 45° di New York City:
Jenis peta satellite
dan hybrid
mendukung gambar 45°
pada tingkat zoom tinggi (12 dan lebih besar) jika tersedia. Jika pengguna memperbesar tampilan lokasi yang terdapat gambar tersebut, jenis peta ini secara otomatis mengubah tampilannya dengan cara berikut:
- Gambar hibrida atau citra satelit diganti dengan gambar yang memberikan perspektif 45°, yang berpusat pada lokasi saat ini. Secara default, tampilan tersebut mengarah ke utara. Jika pengguna memperkecil tampilan, gambar hibrida atau citra satelit default akan muncul lagi. Perilaku ini bervariasi bergantung pada tingkat zoom dan nilai
tilt
: - Antara tingkat zoom 12 dan 18, peta dasar vertikal (0°) ditampilkan secara default, kecuali jika
tilt
ditetapkan ke 45. - Pada tingkat zoom 18 atau lebih besar, peta dasar 45° akan ditampilkan kecuali jika
tilt
ditetapkan ke 0. - Kontrol rotasi menjadi terlihat. Kontrol rotasi menyediakan opsi yang
memungkinkan pengguna mengubah kemiringan, dan dapat memutar tampilan dalam kenaikan 90°
ke salah satu arah. Untuk menyembunyikan kontrol rotasi, tetapkan
rotateControl
kefalse
.
Memperkecil tampilan dari jenis peta yang menampilkan gambar 45° akan mengembalikan setiap perubahan ini, menetapkan kembali jenis peta asal.
Mengaktifkan dan Menonaktifkan Gambar 45°
Anda dapat menonaktifkan citra 45° dengan memanggil setTilt(0)
pada objek Map
. Agar dapat mengaktifkan gambar 45° untuk jenis peta yang didukung, panggil setTilt(45)
. Metode getTilt()
Map
akan selalu mencerminkan tilt
saat ini yang ditampilkan di
peta; jika Anda menetapkan tilt
pada peta, lalu menghapus tilt
tersebut
(misalnya, dengan memperkecil peta), metode
getTilt()
peta akan menampilkan 0
.
Penting: Gambar 45° hanya didukung di peta raster; gambar ini tidak dapat digunakan dengan peta vektor.
Contoh berikut menampilkan tampilan 45° dari New York City:
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;
Mencoba Contoh
Memutar Gambar 45°
Gambar 45° sebenarnya terdiri dari sekumpulan gambar untuk setiap arah mata angin (Utara, Selatan, Timur, Barat). Setelah peta
menampilkan gambar 45°, Anda dapat mengorientasikan
gambar ke salah satu arah mata angin dengan memanggil
setHeading()
pada objek Map
, yang meneruskan
nilai angka yang dinyatakan sebagai derajat dari Utara.
Contoh berikut menampilkan peta udara dan memutar peta secara otomatis setiap 3 detik jika tombol diklik:
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;
Mencoba 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.
Untuk informasi selengkapnya tentang StyledMapType
, lihat panduan untuk peta bergaya.
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
, danterrain
. Anda dapat menambahkan jenis peta kustom ke arraymapTypes
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 jenisgoogle.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 adalah0
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 Menambahkan KontrolMapType
di bawah.)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 Menambahkan KontrolMapType
di bawah.)
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. MetodegetTile()
ini harus memiliki tanda tangan berikut:getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node
API menentukan apakah perlu memanggil
getTile()
berdasarkan propertitileSize
,minZoom
, danmaxZoom
dariMapType
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;
Mencoba 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;
Mencoba 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 jenisgoogle.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;
Mencoba 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 sebaliknya. 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 garis lintang dan garis bujur menjadi
bidang Kartesius dan sebaliknya. (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 nilaiLatLng
menjadi koordinat dunia. Metode ini digunakan untuk memosisikan overlay pada peta (dan memosisikan peta itu sendiri). - Metode
Projection.fromPointToLatLng()
mengonversi koordinat dunia menjadi nilaiLatLng
. 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 function initMap(): void { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false, } ); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords") as HTMLElement; map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.addListener("mousemove", (event: google.maps.MapMouseEvent) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng!.lat()) + ", " + "lng: " + Math.round(event.latLng!.lng()); }); // Add some markers to the map. map.data.setStyle((feature) => { return { title: feature.getProperty("name") as string, optimized: false, }; }); map.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/gall-peters_" + zoom + "_" + x + "_" + y + ".png" ); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters", }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function (latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point( GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)) ); }, fromPointToLatLng: function (point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng( (Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap ); }, }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" }, }, ], }; declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
// This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection function initMap() { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map(document.getElementById("map"), { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false, }); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords"); map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.addListener("mousemove", (event) => { coordsDiv.textContent = "lat: " + Math.round(event.latLng.lat()) + ", " + "lng: " + Math.round(event.latLng.lng()); }); // Add some markers to the map. map.data.setStyle((feature) => { return { title: feature.getProperty("name"), optimized: false, }; }); map.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function (coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/gall-peters_" + zoom + "_" + x + "_" + y + ".png" ); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters", }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function (latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point( GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)), ); }, fromPointToLatLng: function (point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng( (Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap, ); }, }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" }, }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" }, }, ], }; window.initMap = initMap;