Questo documento illustra i tipi di mappe che puoi visualizzare utilizzando l'API Maps JavaScript. L'API utilizza un oggetto MapType
per contenere le informazioni su queste mappe. Un MapType
è un'interfaccia che definisce la visualizzazione e l'utilizzo dei riquadri della mappa e la traduzione dei sistemi di coordinate dalle coordinate dello schermo alle coordinate del mondo (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 mappa all'interno dell'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 le mappe con stile o definire riquadri di mappa personalizzati utilizzando i tipi di mappe personalizzate. Quando fornisci tipi di mappe personalizzati, devi capire come modificare il registro dei tipi di mappa della mappa.
Tipi di mappa di base
Nell'API Maps JavaScript sono disponibili quattro tipi di mappe. Oltre ai soliti riquadri di mappe stradali "dipinti", 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 una combinazione di viste normali e satellitari.terrain
mostra una mappa fisica basata sulle informazioni dei rilievi.
Puoi modificare il tipo di mappa utilizzato da Map
impostando la relativa proprietà mapTypeId
, all'interno del costruttore tramite l'impostazione del relativo oggetto Map options
oppure chiamando il metodo setMapTypeId()
della mappa. Per impostazione predefinita, la proprietà mapTypeID
è roadmap
.
Impostazione di mapTypeId
al momento della 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 in realtà non imposti direttamente il tipo di mappa della mappa,
ma imposti il relativo mapTypeId
in modo che faccia riferimento a
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 determinati luoghi. Queste immagini ad alta risoluzione offrono viste prospettiche rispetto a ciascuna direzione cardinale (Nord, Sud, Est, Ovest). Queste immagini sono disponibili a livelli di zoom più elevati per i tipi di mappe supportati.
La seguente immagine mostra una vista prospettica a 45° di New York City:
I tipi di mappa satellite
e hybrid
supportano immagini a 45°
ad alti livelli di zoom (12 e superiori), ove disponibili. Se l'utente
ingrandisce un luogo per il quale esistono immagini di questo tipo, questi tipi di mappe
modificano automaticamente le visualizzazioni nel seguente modo:
- Le immagini satellitari o ibride vengono sostituite da immagini che forniscono una prospettiva a 45°, centrata sulla posizione corrente. Per impostazione predefinita, queste viste sono orientate verso nord. Se l'utente diminuisce 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, viene visualizzata per impostazione predefinita la mappa di base per l'alto verso il basso (0°), a meno che
tilt
non sia impostato su 45. - A livelli di zoom pari o superiori a 18° viene visualizzata la mappa base 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 la rotazione della vista con incrementi di 90° in entrambe le direzioni. Per nascondere il controllo di rotazione, imposta
rotateControl
sufalse
.
La riduzione dello zoom rispetto a un tipo di mappa che mostra immagini a 45° annulla ciascuna di queste modifiche, ripristinando 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 setTilt(45)
. Il metodo getTilt()
di Map
rifletterà sempre l'attuale tilt
mostrato sulla
mappa; se imposti un tilt
su una mappa e poi rimuovi quest'ultimo
tilt
(ad esempio diminuendo lo zoom della mappa), il metodo
getTilt()
della mappa restituirà 0
.
Importante: le immagini a 45° sono supportate solo sulle mappe raster; non possono essere utilizzate con le mappe vettoriali.
L'esempio seguente mostra una vista a 45° di New York:
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 Samples
Rotazione delle immagini a 45°
Le immagini a 45° in realtà sono composte da una raccolta di immagini per ciascuna direzione cardinale (Nord, Sud, Est, Ovest). Quando la mappa mostra immagini a 45°, puoi orientarle verso una delle direzioni cardinali chiamando setHeading()
sull'oggetto Map
e passando un valore numerico espresso in gradi dal nord.
L'esempio seguente mostra una mappa aerea e ruota automaticamente la mappa ogni 3 secondi quando si fa 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 Samples
Modifica del registro dei tipi di mappa
mapTypeId
di una mappa è un identificatore di stringa
utilizzato per associare un MapType
a un
valore univoco. Ogni oggetto Map
gestisce un elemento
MapTypeRegistry
che contiene la raccolta di
MapType
disponibili per quella mappa. Ad esempio, questo registro viene utilizzato per selezionare i tipi di mappe disponibili nel controllo MapType di Maps.
Non leggi direttamente dal registro dei tipi di mappa. Puoi invece modificare il registro aggiungendo tipi di mappe personalizzati e associandoli a un identificatore di stringa di tua scelta. Non puoi modificare
o alterare i tipi di mappa di base (ma puoi rimuoverli dalla
mappa cambiando l'aspetto dell'elemento mapTypeControlOptions
associato alla mappa).
Il codice seguente imposta la mappa in modo che mostri solo
due tipi di mappa nel relativo mapTypeControlOptions
e modifica il registro per aggiungere l'associazione con
questo identificatore all'effettiva implementazione 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
StyledMapType
ti consente di personalizzare la presentazione delle
mappe base di Google standard, modificando la visualizzazione di elementi
come strade, parchi e aree edificate per riflettere uno stile diverso da quello
utilizzato nel tipo di mappa predefinito.
Per ulteriori informazioni su StyledMapType
, consulta la guida alle mappe con stili applicati.
Tipi di mappe personalizzate
L'API Maps JavaScript supporta la visualizzazione e la gestione di tipi di mappe personalizzate, consentendoti di implementare le tue immagini mappa o gli overlay dei riquadri.
All'interno dell'API Maps JavaScript esistono diverse implementazioni del tipo di mappa:
- Set di riquadri standard costituiti da immagini che insieme costituiscono mappe cartografiche complete. Questi set di riquadri sono noti anche come tipi di mappe base. Questi tipi di mappe agiscono e si comportano come i tipi di mappe predefinite esistenti:
roadmap
,satellite
,hybrid
eterrain
. Puoi aggiungere il tuo tipo di mappa personalizzato a un arraymapTypes
di Maps per consentire all'interfaccia utente all'interno dell'API Maps JavaScript di trattare il tuo tipo di mappa personalizzata come un tipo di mappa standard (ad esempio includendolo nel controllo MapType). - Sovrapposizioni del riquadro immagine visualizzate sopra i tipi di mappe base esistenti. In genere, questi tipi di mappa vengono utilizzati per arricchire un tipo di mappa esistente al fine di mostrare informazioni aggiuntive e sono spesso limitati a località specifiche e/o a livelli di zoom. Tieni presente che questi riquadri possono essere trasparenti e ti permettono di aggiungere elementi alle mappe esistenti.
- Tipi di mappe non immagine, che consentono di manipolare la visualizzazione delle informazioni sulla mappa al livello più fondamentale.
Ognuna di queste opzioni si basa sulla creazione di una classe che implementi l'interfaccia MapType
. Inoltre, la classe
ImageMapType
fornisce un comportamento integrato
per semplificare la creazione di tipi di mappe immagini.
Interfaccia di MapType
Prima di creare classi che implementano MapType
, è importante capire in che modo Google Maps determina le coordinate e decide quali parti della mappa mostrare. Devi implementare una logica simile per ogni tipo di mappa base o overlay.
Leggi la guida alle coordinate di mappa e riquadri.
I tipi di mappe personalizzate devono implementare l'interfaccia MapType
. Questa interfaccia specifica alcuni metodi e proprietà che consentono all'API di avviare richieste ai tuoi tipi di mappa quando l'API stabilisce che deve mostrare riquadri della mappa all'interno dell'area visibile e del livello di zoom correnti. Sei tu a gestire queste richieste per decidere quale riquadro caricare.
Nota: puoi creare la tua classe per implementare questa interfaccia. In alternativa, se disponi di
immagini compatibili, puoi utilizzare la classe
ImageMapType
che già implementa questa
interfaccia.
Le classi che implementano l'interfaccia MapType
richiedono la definizione e il completamento delle seguenti proprietà:
tileSize
(obbligatorio) specifica le dimensioni del riquadro (di tipogoogle.maps.Size
). Le dimensioni devono essere rettangolari anche se non quadrate.maxZoom
(obbligatorio) specifica il livello massimo di zoom a cui visualizzare i riquadri di questo tipo di mappa.minZoom
(facoltativo) specifica il livello minimo di zoom a cui visualizzare il riquadro di questo tipo di mappa. Per impostazione predefinita, questo valore è0
e indica che non esiste un livello di zoom minimo.name
(facoltativo) specifica il nome per questo tipo di mappa. Questa proprietà è necessaria solo se vuoi che questo tipo di mappa sia selezionabile all'interno di un controllo MapType. (Vedi Aggiunta di controlliMapType
di seguito.)alt
(facoltativo) specifica il testo alternativo per questo tipo di mappa, mostrato 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 AggiungereMapType
controlli di seguito.
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 mostrare nuovi riquadri 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àtileSize
,minZoom
emaxZoom
diMapType
, nonché all'area visibile e al livello di zoom correnti della mappa. Il gestore per questo metodo deve restituire un elemento HTML in base a una coordinata passata, un livello di zoom ed un elemento DOM a cui aggiungere l'immagine 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 allegati ai riquadri della mappa dopo l'aggiunta alla mappa. Ad esempio, se hai associato listener di eventi a overlay di riquadri 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 mappa base
I tipi di mappa che crei in questo modo possono essere autonomi o combinati con altri tipi di mappe sotto forma di overlay. I tipi di mappe indipendenti sono noti come tipi di mappe base. Potresti voler fare in modo che l'API
consideri questi MapType
personalizzati come qualsiasi altro tipo di mappa 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 dei riquadri di una mappa e traccia il contorno dei riquadri:
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 Samples
Tipi di mappa overlay
Alcuni tipi di mappe sono progettati per funzionare su tipi di mappe esistenti. Questi tipi di mappa possono avere livelli trasparenti che indicano punti d'interesse o mostrano dati aggiuntivi all'utente.
In questi casi, non vuoi che il tipo di mappa venga considerato come un'entità separata ma come un overlay.
Per farlo, aggiungi il tipo di mappa a un elemento MapType
esistente direttamente utilizzando la proprietà overlayMapTypes
di Map
. Questa proprietà contiene
un valore MVCArray
di MapType
. Tutti i tipi di mappa (base e overlay) vengono visualizzati all'interno del livello mapPane
. I tipi di mappa overlay vengono visualizzati sopra la mappa base a cui sono associati, nell'ordine in cui appaiono nell'array Map.overlayMapTypes
(gli overlay con valori di indice più alti vengono visualizzati davanti agli overlay 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 Samples
Tipi di mappa immagine
L'implementazione di una MapType
in modo che agisca come 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 con riquadri costituiti 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 quadrate.getTileUrl
(obbligatorio) specifica la funzione, di solito fornita come valore letterale di funzione in linea, per gestire la selezione del riquadro dell'immagine corretto in base alle coordinate globali e al livello di zoom forniti.
Il codice seguente implementa un valore ImageMapType
di base
utilizzando i riquadri lunare di Google. L'esempio utilizza una funzione di normalizzazione per garantire che i riquadri si ripetano sull'asse x, ma non sull'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 Samples
Proiezioni
La Terra è una sfera tridimensionale (circa), mentre una mappa è una superficie bidimensionale piatta. La mappa visualizzata nell'API Maps JavaScript, come qualsiasi mappa piatta della Terra, è una proiezione della sfera su una superficie piana. In parole povere, 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 Projection
deve fornire non solo una mappatura da un sistema di coordinate
all'altro, ma anche una mappatura bidirezionale. In altre parole, devi definire la modalità di traslazione dalle coordinate terrestri (LatLng
oggetti) al sistema di coordinate mondiali della classe Projection
e viceversa. Google Maps utilizza la proiezione di Mercatore per creare le proprie mappe a partire da dati geografici e convertire gli eventi sulla mappa in coordinate geografiche. Puoi ottenere questa proiezione chiamando getProjection()
su Map
(o qualsiasi tipo di base MapType
standard). Per la maggior parte degli utilizzi, questo Projection
standard è sufficiente, ma puoi anche definire e utilizzare proiezioni personalizzate.
Implementazione di una proiezione
Quando implementi una proiezione personalizzata, dovrai definire alcuni aspetti:
- Le formule per mappare le coordinate di latitudine e longitudine su un piano cartesiano e viceversa. 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 utilizzando il riquadro di base impostato a livello di zoom 0. Tieni presente che per le mappe composte da un riquadro con zoom 0, le dimensioni del mondo e le dimensioni del riquadro di base sono identiche.
Coordina le trasformazioni nelle proiezioni
Ogni proiezione fornisce due metodi che consentono la conversione tra questi due sistemi di coordinate e la conversione tra coordinate geografiche e mondiali:
- Il metodo
Projection.fromLatLngToPoint()
converte un valoreLatLng
in una coordinata mondiale. Questo metodo viene utilizzato per posizionare gli overlay sulla mappa e la mappa stessa. - Il metodo
Projection.fromPointToLatLng()
converte una coordinata mondiale in un valoreLatLng
. Questo metodo viene utilizzato per convertire in coordinate geografiche eventi come i clic sulla mappa.
Google Maps presuppone che le proiezioni siano rettilinee.
In genere, puoi utilizzare la proiezione per 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 rettilinea e normale a tutte le longitudini. Alcune proiezioni (soprattutto quelle coniche) possono essere "localmente normali" (ovvero il punto a nord), ma deviare dal vero nord; ad esempio, più lontano è la mappa posizionata rispetto a una certa longitudine di riferimento. Puoi utilizzare una proiezione di questo tipo a livello locale, ma tieni presente che la proiezione è necessariamente imprecisa e che gli errori di trasformazione si esprimono sempre più lontano dalla longitudine di riferimento con cui devii.
Selezione riquadri mappa nelle proiezioni
Le proiezioni non sono utili solo per determinare le posizioni di
luoghi o overlay, ma per posizionare i riquadri della mappa stessi.
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 riquadri della mappa in base ai valori delle coordinate dei riquadri. 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 a livello di zoom 0. Per le mappe composte da un riquadro con zoom 0, le dimensioni del riquadro e del mondo sono identiche.
Devi definire la dimensione del riquadro di base all'interno della
proprietà tileSize
di MapType
. La dimensione del mondo viene definita implicitamente all'interno dei metodi fromLatLngToPoint()
e fromPointToLatLng()
della proiezione.
Poiché la selezione delle immagini dipende da questi valori trasmessi, è utile assegnare un nome alle immagini che possono essere selezionate in modo programmatico dati i valori trasmessi, 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"), 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;