Questo documento descrive i tipi di mappe che puoi visualizzare utilizzando l'API Maps JavaScript. L'API usa un oggetto MapType
che contiene le informazioni su queste mappe. Un MapType
è un'interfaccia che definisce la visualizzazione e l'utilizzo dei riquadri della mappa e
la conversione dei sistemi di coordinate dalle coordinate dello schermo alle coordinate
mondiali (sulla mappa). Ogni MapType
deve contenere
alcuni metodi per gestire il recupero e il rilascio dei riquadri e le proprietà
che ne definiscono il comportamento visivo.
Il funzionamento interno dei tipi di mappe nell'API Maps JavaScript è un argomento avanzato. La maggior parte degli sviluppatori può utilizzare i tipi di mappe di base indicati di seguito. Tuttavia, puoi anche modificare la presentazione dei tipi di mappa esistenti utilizzando Styled Maps o definire le tue tessere della mappa utilizzando tipi di mappa personalizzati. Quando fornisci tipi di mappe personalizzati, devi capire come modificare il Registro dei tipi di mappe.
Tipi di mappe di base
Esistono quattro tipi di mappe disponibili nell'API Maps JavaScript. Oltre alle familiari tessere della mappa stradale "dipinte", l'API Maps JavaScript supporta anche altri tipi di mappe.
Nell'API Maps JavaScript sono disponibili i seguenti tipi di mappa:
roadmap
mostra la visualizzazione predefinita della mappa stradale. Questo è il tipo di mappa predefinito.satellite
mostra le immagini satellitari di Google Earth.hybrid
mostra un mix di visualizzazioni normale e satellitare.terrain
mostra una mappa fisica basata sulle informazioni del terreno.
Modifica il tipo di mappa in uso in Map
impostando la relativa proprietà
mapTypeId
all'interno del costruttore impostando
il relativo oggetto Map options
o chiamando il metodo
setMapTypeId()
della mappa. La proprietà mapTypeID
è impostata su roadmap
per impostazione predefinita.
Impostazione di mapTypeId
durante la costruzione:
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);
Modifica dinamica di mapTypeId
:
map.setMapTypeId('terrain');
Tieni presente che non imposti direttamente il tipo di mappa della mappa,
ma imposti invece il relativo mapTypeId
in modo che faccia riferimento a un
MapType
utilizzando un identificatore.
L'API Maps JavaScript utilizza un registro dei tipi di mappa, spiegato di seguito, per gestire questi riferimenti.
Immagini a 45°
L'API Maps JavaScript supporta immagini speciali a 45° per determinate località. Queste immagini ad alta risoluzione forniscono viste prospettiche verso ciascuna delle direzioni cardinali (nord, sud, est, ovest). Queste immagini sono disponibili a livelli di zoom più elevati per i tipi di mappe supportati.
L'immagine seguente mostra una vista prospettica a 45° di New York City:
I tipi di mappa satellite
e hybrid
supportano immagini a 45°
a livelli di zoom elevati (12 e superiori) dove disponibili. Se l'utente
ingrandisce una località per la quale esistono queste immagini, questi tipi di mappe
modificano automaticamente le loro visualizzazioni nel seguente modo:
- Le immagini satellitari o ibride vengono sostituite con immagini che offrono una prospettiva di 45°
centrata sulla posizione attuale. Per impostazione predefinita, queste visualizzazioni sono
orientate verso nord. Se l'utente riduce lo zoom, vengono visualizzate di nuovo le immagini satellitari o
ibride predefinite. Il comportamento varia a seconda del livello di zoom
e del valore di
tilt
: - Tra i livelli di zoom 12 e 18, la mappa di base dall'alto (0°) viene visualizzata per
impostazione predefinita, a meno che
tilt
non sia impostato su 45. - Ai livelli di zoom 18 o superiori, viene visualizzata la basemap a 45° a meno che
tilt
non sia impostato su 0. - Il controllo di rotazione diventa visibile. Il controllo di rotazione offre opzioni
che consentono all'utente di attivare/disattivare l'inclinazione e di ruotare la visualizzazione di 90°
in entrambe le direzioni. Per nascondere il controllo di rotazione, imposta
rotateControl
sufalse
.
Se diminuisci lo zoom di un tipo di mappa che mostra immagini a 45°, tutte queste modifiche vengono annullate e vengono ripristinati i tipi di mappa originali.
Attivare e disattivare le immagini a 45°
Puoi disattivare le immagini a 45° chiamando setTilt(0)
sull'oggetto
Map
. Per attivare le immagini a 45° per i tipi di mappe supportati,
chiama il numero setTilt(45)
. Il metodo Map
's getTilt()
rifletterà sempre l'tilt
corrente visualizzato sulla
mappa; se imposti un tilt
su una mappa e poi lo rimuovi (ad esempio, riducendo lo zoom della mappa), il metodo
getTilt()
della mappa restituirà 0
.tilt
Importante: le immagini a 45° sono supportate solo sulle mappe raster; queste immagini non possono essere utilizzate con le mappe vettoriali.
L'esempio seguente mostra una visualizzazione a 45° di 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;
Prova campione
Ruota le immagini di 45°
Le immagini a 45° sono in realtà costituite da una raccolta di immagini
per ogni direzione cardinale (nord, sud, est, ovest). Una volta che la mappa
mostra le immagini a 45°, puoi orientarle
verso uno dei punti cardinali chiamando
setHeading()
sull'oggetto Map
, passando
un valore numerico espresso in gradi rispetto al nord.
Il seguente esempio mostra una mappa aerea e la rotazione automatica della mappa ogni 3 secondi quando viene fatto clic sul pulsante:
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;
Prova campione
Modificare il registro dei tipi di mappa
L'mapTypeId
di una mappa è un identificatore stringa
utilizzato per associare un MapType
a un
valore univoco. Ogni oggetto Map
gestisce un
MapTypeRegistry
che contiene la raccolta di
MapType
disponibili per quella mappa. Questo registro
viene utilizzato per selezionare i tipi di mappe disponibili
nel controllo MapType della mappa, ad esempio.
Non leggi direttamente dal registro dei tipi di mappe. In alternativa,
modifica il registro aggiungendo tipi di mappe personalizzati e associandoli
a un identificatore stringa a tua scelta. Non puoi modificare
o alterare i tipi di mappe di base (anche se puoi rimuoverli dalla
mappa modificando l'aspetto del relativo
mapTypeControlOptions
).
Il seguente codice imposta la mappa in modo da mostrare solo
due tipi di mappa nel mapTypeControlOptions
della mappa
e modifica il registro per aggiungere l'associazione a
questo identificatore all'implementazione effettiva dell'interfaccia
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);
Mappe con stile
Il StyledMapType
ti consente di personalizzare la presentazione delle mappe di base standard di Google, modificando la visualizzazione di elementi come strade, parchi e aree edificate per riflettere uno stile diverso da quello utilizzato nel tipo di mappa predefinito. L'opzione StyledMapType
influisce solo sul tipo di mappa roadmap
predefinito.
Per ulteriori informazioni su StyledMapType
, consulta
Utilizzo di dichiarazioni di stile JSON incorporate.
Tipi di mappe personalizzate
L'API Maps JavaScript supporta la visualizzazione e la gestione di tipi di mappe personalizzati, consentendoti di implementare le tue immagini della mappa o i tuoi overlay delle tessere.
Esistono diverse possibili implementazioni del tipo di mappa all'interno dell'API Maps JavaScript:
- Set di riquadri standard costituiti da immagini che
costituiscono collettivamente mappe cartografiche complete. Questi set
di riquadri sono noti anche come tipi di mappe base. Questi tipi di mappe
si comportano come i tipi di mappe predefiniti esistenti:
roadmap
,satellite
,hybrid
eterrain
. Puoi aggiungere il tuo tipo di mappa personalizzato all'arraymapTypes
di una mappa per consentire all'UI all'interno dell'API Maps JavaScript di trattare il tuo tipo di mappa personalizzato come un tipo di mappa standard (includendolo, ad esempio, nel controllo MapType). - Overlay dei riquadri immagine che vengono visualizzati sopra i tipi di mappe di base esistenti. In genere, questi tipi di mappe vengono utilizzati per integrare un tipo di mappa esistente per visualizzare ulteriori informazioni e sono spesso limitati a località specifiche e/o livelli di zoom. Tieni presente che queste tessere potrebbero essere trasparenti, consentendoti di aggiungere funzionalità alle mappe esistenti.
- Tipi di mappe non basati su immagini, che consentono di manipolare la visualizzazione delle informazioni della mappa al livello più fondamentale.
Ciascuna di queste opzioni si basa sulla creazione di una classe che
implementa l'interfaccia MapType
. Inoltre, la classe
ImageMapType
fornisce alcuni comportamenti
integrati per semplificare la creazione di tipi di mappe di immagini.
L'interfaccia MapType
Prima di creare classi che implementano MapType
,
è importante capire come Google Maps determina
le coordinate e decide quali parti della mappa mostrare. Devi
implementare una logica simile per tutti i tipi di mappe di base o di overlay.
Leggi la guida alle coordinate
della mappa e delle tessere.
I tipi di mappa personalizzati devono implementare l'interfaccia MapType
. Questa interfaccia specifica determinate proprietà e
metodi che consentono all'API di avviare richieste ai tuoi tipi di mappa
quando l'API determina che deve visualizzare i riquadri della mappa
all'interno della finestra e del livello di zoom correnti. Gestisci
queste richieste per decidere quale riquadro caricare.
Nota: puoi creare la tua
classe per implementare questa interfaccia. In alternativa, se hai
immagini compatibili, puoi utilizzare la classe
ImageMapType
che implementa già
questa interfaccia.
Le classi che implementano l'interfaccia MapType
richiedono la definizione e il popolamento delle seguenti proprietà:
tileSize
(obbligatorio) specifica le dimensioni del riquadro (di tipogoogle.maps.Size
). Le dimensioni devono essere rettangolari anche se non devono essere quadrate.maxZoom
(obbligatorio) specifica il livello di zoom massimo a cui visualizzare i riquadri di questo tipo di mappa.minZoom
(facoltativo) specifica il livello di zoom minimo a cui visualizzare il riquadro di questo tipo di mappa. Per impostazione predefinita, questo valore è0
, a indicare che non esiste un livello di zoom minimo.name
(facoltativo) specifica il nome di questo tipo di mappa. Questa proprietà è necessaria solo se vuoi che questo tipo di mappa sia selezionabile all'interno di un controllo MapType. (Consulta la sezione Opzioni di controllo.)alt
(facoltativo) specifica il testo alternativo per questo tipo di mappa, visualizzato come testo al passaggio del mouse. Questa proprietà è necessaria solo se vuoi che questo tipo di mappa sia selezionabile all'interno di un controllo MapType. Consulta la sezione Opzioni di controllo.
Inoltre, le classi che implementano l'interfaccia MapType
devono implementare i seguenti metodi:
-
getTile()
(obbligatorio) viene chiamato ogni volta che l'API determina che la mappa deve visualizzare nuove tessere per l'area visibile specificata. Il metodogetTile()
deve avere la seguente firma:getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node
L'API determina se deve chiamare
getTile()
in base alle proprietàMapType
,tileSize
,minZoom
emaxZoom
e all'area visibile e al livello di zoom attuali della mappa. Il gestore per questo metodo deve restituire un elemento HTML dato un elemento DOM, un livello di zoom e una coordinata a cui aggiungere l'immagine del riquadro. -
releaseTile()
(facoltativo) viene chiamato ogni volta che l'API determina che la mappa deve rimuovere un riquadro perché non è più visibile. Questo metodo deve avere la seguente firma:releaseTile(tile:Node)
In genere, devi gestire la rimozione di tutti gli elementi che sono stati allegati alle tessere della mappa al momento dell'aggiunta alla mappa. Ad esempio, se hai collegato listener di eventi a overlay delle tessere della mappa, devi rimuoverli qui.
Il metodo getTile()
funge da controller principale per
determinare quali riquadri caricare all'interno di una determinata area visibile.
Tipi di mappe base
I tipi di mappa che crei in questo modo possono essere utilizzati
singolarmente o combinati con altri tipi di mappa come overlay. I tipi di mappe
autonomi sono noti come tipi di mappe base. Potresti voler fare in modo che l'API
tratti questi MapType
personalizzati come qualsiasi altro tipo di mappa di base esistente (ROADMAP
, TERRAIN
e così via). Per farlo, aggiungi il tuo MapType
personalizzato alla proprietà mapTypes
di Map
. Questa proprietà è di tipo
MapTypeRegistry
.
Il seguente codice crea una base MapType
per visualizzare
le coordinate delle tessere di una mappa e disegna un contorno delle tessere:
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;
Prova campione
Tipi di mappe in overlay
Alcuni tipi di mappe sono progettati per funzionare sopra i tipi di mappe esistenti. Questi tipi di mappe possono avere livelli trasparenti che indicano punti di interesse o mostrano dati aggiuntivi all'utente.
In questi casi, non vuoi che il tipo di mappa venga trattato come un'entità separata, ma come un overlay.
Puoi farlo aggiungendo il tipo di mappa a un MapType
esistente direttamente utilizzando
la proprietà overlayMapTypes
di Map
. Questa proprietà contiene
un MVCArray
di MapType
. Tutti i tipi di mappe
(base e overlay) vengono visualizzati all'interno
del livello mapPane
. I tipi di mappe di overlay vengono visualizzati sopra la mappa di base a cui sono collegati, nell'ordine in cui appaiono nell'array Map.overlayMapTypes
(gli overlay con valori di indice più alti vengono visualizzati davanti a quelli con valori di indice più bassi).
L'esempio seguente è identico a quello precedente
tranne per il fatto che abbiamo creato un overlay di riquadri MapType
sopra il tipo di mappa 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;
Prova campione
Tipi di mappe immagine
L'implementazione di un MapType
che funga da tipo di mappa base può essere un'attività lunga e laboriosa. L'API
fornisce una classe speciale che implementa l'interfaccia MapType
per i tipi di mappe più comuni: tipi di mappe costituiti
da riquadri composti da singoli file immagine.
Questa classe, la classe ImageMapType
,
viene creata utilizzando una specifica dell'oggetto ImageMapTypeOptions
che definisce le seguenti proprietà obbligatorie:
tileSize
(obbligatorio) specifica le dimensioni del riquadro (di tipogoogle.maps.Size
). Le dimensioni devono essere rettangolari anche se non devono essere quadrate.getTileUrl
(obbligatorio) specifica la funzione, di solito fornita come valore letterale della funzione inline, per gestire la selezione del riquadro dell'immagine appropriato in base alle coordinate mondiali e al livello di zoom forniti.
Il seguente codice implementa una ImageMapType
di base
utilizzando le tessere della luna di Google. L'esempio utilizza una funzione di normalizzazione
per garantire che i riquadri si ripetano lungo l'asse x, ma non lungo l'asse
y della mappa.
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;
Prova campione
Proiezioni
La Terra è una sfera tridimensionale (circa), mentre una mappa è una superficie bidimensionale piatta. La mappa che vedi all'interno dell'API Maps JavaScript, come qualsiasi mappa piatta della Terra, è una proiezione di quella sfera su una superficie piatta. Nei termini più semplici, una proiezione può essere definita come una mappatura dei valori di latitudine/longitudine in coordinate sulla mappa della proiezione.
Le proiezioni nell'API Maps JavaScript devono implementare l'interfaccia
Projection
. Un'implementazione di Projection
deve fornire non solo una mappatura da un sistema di coordinate
a un altro, ma una mappatura bidirezionale. ovvero devi
definire come eseguire la conversione dalle coordinate terrestri (oggetti LatLng
) al sistema di
coordinate mondiali della classe Projection
e viceversa.
Google Maps utilizza la proiezione di Mercatore per creare le mappe
a partire dai dati geografici e convertire gli eventi sulla mappa in
coordinate geografiche. Puoi ottenere questa proiezione
chiamando il numero getProjection()
sul Map
(o uno qualsiasi dei tipi di base standard MapType
). Per la maggior parte degli utilizzi,
questo standard Projection
sarà sufficiente, ma puoi anche
definire e utilizzare le tue proiezioni personalizzate.
Implementare una proiezione
Quando implementi una proiezione personalizzata, devi definire alcune cose:
- Le formule per mappare le coordinate di latitudine e longitudine in
un piano cartesiano e le formule corrispondenti per la mappatura da un piano cartesiano alle coordinate di latitudine
e longitudine. (L'interfaccia
Projection
supporta solo le trasformazioni in coordinate rettilinee.) - La dimensione del riquadro di base. Tutti i riquadri devono essere rettangolari.
- Le "dimensioni del mondo" di una mappa che utilizza il set di riquadri di base al livello di zoom 0. Tieni presente che per le mappe costituite da un riquadro con zoom 0, le dimensioni del mondo e le dimensioni del riquadro di base sono identiche.
Trasformazioni delle coordinate nelle proiezioni
Ogni proiezione fornisce due metodi che eseguono la conversione tra questi due sistemi di coordinate, consentendoti di convertire le coordinate geografiche e del mondo:
- Il metodo
Projection.fromLatLngToPoint()
converte un valoreLatLng
in una coordinata del mondo. Questo metodo viene utilizzato per posizionare le sovrapposizioni sulla mappa (e per posizionare la mappa stessa). - Il metodo
Projection.fromPointToLatLng()
converte una coordinata del mondo in un valoreLatLng
. Questo metodo viene utilizzato per convertire eventi come i clic che si verificano sulla mappa in coordinate geografiche.
Google Maps presuppone che le proiezioni siano rettilinee.
In genere, puoi utilizzare una proiezione in due casi: per creare una mappa del mondo o per creare una mappa di un'area locale. Nel primo caso, devi assicurarti che la proiezione sia anche rettilinea e normale a tutte le longitudini. Alcune proiezioni (in particolare le proiezioni coniche) possono essere "normali a livello locale" (ovvero puntare a nord), ma deviare dal nord vero; ad esempio, più la mappa è posizionata rispetto a una longitudine di riferimento. Puoi utilizzare questa proiezione a livello locale, ma tieni presente che la proiezione è necessariamente imprecisa e gli errori di trasformazione diventeranno sempre più evidenti man mano che ti allontani dalla longitudine di riferimento.
Selezione dei riquadri della mappa nelle proiezioni
Le proiezioni non sono utili solo per determinare le posizioni di
località o overlay, ma anche per posizionare le tessere della mappa.
L'API Maps JavaScript esegue il rendering delle mappe di base utilizzando un'interfaccia MapType
, che deve dichiarare sia una proprietà projection
per identificare la proiezione della mappa sia un metodo getTile()
per recuperare i riquadri della mappa in base ai valori delle coordinate del riquadro. Le coordinate dei riquadri si basano
sia sulle dimensioni di base dei riquadri (che devono essere rettangolari) sia sulle "dimensioni
del mondo" della mappa, ovvero le dimensioni in pixel del mondo della mappa
al livello di zoom 0. (Per le mappe costituite da un riquadro con zoom 0, le dimensioni del riquadro e del mondo sono identiche.)
Definisci le dimensioni del riquadro di base all'interno della proprietà tileSize
di MapType
. Definisci implicitamente le dimensioni del mondo
all'interno dei metodi fromLatLngToPoint()
e fromPointToLatLng()
della proiezione.
Poiché la selezione delle immagini dipende da questi valori passati, è utile
denominare le immagini che possono essere selezionate in modo programmatico in base a questi
valori passati, ad esempio
map_zoom_tileX_tileY.png
.
L'esempio seguente definisce un ImageMapType
utilizzando la proiezione
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;