Rendere Bing Maps responsive

O meglio, la mappa embeddata tramite l’API AJAX v7.
Questo è il naturale proseguimento dell’altro post.
E ora, bando alle ciance.

Innanzitutto, esiste della documentazione sensasta e comprensibile su come fare praticamente tutto quello che si può fare con le API di Bing Maps, cosa che va molto bene. Ma ovviamente tralascia proprio i punti più importanti e su internet non si trova altro di sensato e comprensibile all’infuori di quella documentazione.

A parte questo, creare una chiave richiede pochissimo, non obbliga a far parte di Google+ e si configura con facilità disarmante se farla funzionare solo dal dominio, da localhost o da entrambi o da ovunque.

La mappa si inserisce con uno script e un div, che andrà modificato via javascript per infilarci la mappa vera e propria:

<script charset="UTF-8" type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<div id="mappa" class="bingmaps"></div>

C’è anche un po’ di CSS:

.bingmaps {
	position: relative;
	margin: 1em auto;
	width: 900px;
	height: 556px;
}

Le cose importanti sono la posizione e le dimensioni, anche se andremo a renderla responsive. Il margine sta lì perché nel sito ci voleva.

E fin qui, rispetto all’inserire le dimensioni in un dannato iframe, la modernità è tangibile con mano. Senza ricorrere ad altro javascript, un po’ di responsività si potrebbe ottenere cambiando semplicemente le dimensioni della mappa con le @media query ma non ho provato. A quanto pare mettere larghezza 100% non funziona, invece.

Alla fine mi sono attenuto a quello che ho trovato su internet, ovvero domande con 0 upvote su Stack Overflow…

Quindi l’ultimo tassello, bello corposo, è un file javascript che va incluso da qualche parte nella pagina e contiene questo:

$(function() {
	Microsoft.Maps.loadModule('Microsoft.Maps.Themes.BingTheme', { callback: function() {
		var map = new Microsoft.Maps.Map(document.getElementById("mappa"), {
			credentials: "CHIAVE DI BING MAPS",
			theme: new Microsoft.Maps.Themes.BingTheme(),
			showMapTypeSelector: false,
			enableClickableLogo: false,
			enableSearchLogo: false,
			mapTypeId: Microsoft.Maps.MapTypeId.road
		});
		map.setView({center: new Microsoft.Maps.Location(42.273360, 11.811354), zoom: 6});

		pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(45.123456, 12.121212), null);
		map.entities.push(pin);
		map.entities.push(new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(45.123456, 12.121212), {title: 'Titolo infobox', description: 'Descrizione', pushpin: pin, offset: new Microsoft.Maps.Point(0, 0)}));

		bingresize(map);

		$(window).resize(function () {
			bingresize(map);
		});
	}});
});

function bingresize(map) {
	var available = $('#main').width();

	if(available > 900) {
		var wid = 900;
	} else {
		var wid = available;
	}

	var hei = wid * 0.618;

	$('#mappa').css({
		width: wid,
		height: hei
	})

	map.setView({width: wid, height: hei});
}

Altro che URL kilometrico, qui si usano javascript e JSON a gogo!

A cosa serve tutto questo codice?

$(function() {

Questo fa parte di JQuery, che stavamo già usando nel sito. Se ne può fare a meno se si include lo script dopo la mappa, o subito prima del tag di chiusura di body, ma queste cose riguardano JQuery.

Microsoft.Maps.loadModule('Microsoft.Maps.Themes.BingTheme', { callback: function() {

Questo carica… quel modulo. E quando l’ha caricato chiama la funzione anonima function() che esegue il codice successivo. Chiarissssssimo, no?

var map = new Microsoft.Maps.Map(document.getElementById("mappa"), {

Va a cercare il div con id=”mappa” e ci crea la mappa dentro. Subito dopo vengono passate alcune opzioni alla nuova mappa, sono tutte degnamente descritte nella documentazione quindi non mi dilungo.

map.setView({center: new Microsoft.Maps.Location(42.273360, 11.811354), zoom: 6});

Centra la mappa sull’Italia e mette un livello di zoom consono.

pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(45.123456, 12.121212), null);
map.entities.push(pin);
map.entities.push(new Microsoft.Maps.Infobox(new Microsoft.Maps.Location(45.123456, 12.121212), {title: 'Titolo infobox', description: 'Descrizione', pushpin: pin, offset: new Microsoft.Maps.Point(0, 0)}));

Crea un pin presso 45.123456, 12.121212, con titolo e descrizione nell’infobox. Piazza l’infobox in modo che si apra sul pin.
Per avere più pin e infobox, si ripetono queste 3 righe per ogni pin, magari usando un for visto che non siamo più nel 1950. L’ovvia implementazione è lasciata al lettore, ma se almeno una persona me lo chiede nei commenti, posto le tre righe di codice per farlo.
Forse si può riciclare l’oggetto Microsoft.Maps.Location, ma gli esempi lo creavano sempre due volte.

bingresize(map);

Chiama quella funzione, definita sotto, che ridimensiona la mappa per farla stare nella pagina, occupando tutta la larghezza senza debordare. La variabile “map” è stata definita prima.

$(window).resize(function () {
	bingresize(map);
});

Chiamo la medesima funzione tutte le volte che la finestra viene ridimensionata. Non ricordo che ragione ci fosse per la funzione anonima invece di $(window).resize(bingresize(map));, ma probabilmente c’era.
$(window).resize() fa parte di JQuery. Da notare che al caricamento iniziale della pagina questo non verrebbe eseguito: la finestra è “nata” con quelle dimensioni, non è stata ridimensionata. Ma magari è molto stretta e la mappa di 900 pixel deborda; per questo è necessario anche il precedente frammento di codice che chiama bingresize(map).

function bingresize(map) {
	var available = $('#main').width();

	if(available > 900) {
		var wid = 900;
	} else {
		var wid = available;
	}

	var hei = wid * 0.618;

	$('#mappa').css({
		width: wid,
		height: hei
	})

	map.setView({width: wid, height: hei});
}

Questa funzione calcola la larghezza interna disponibile nell’elemento #main, che è il contenitore della mappa e del resto della pagina. Probabilmente sarà un div, o un article. Per farlo, tanto per cambiare, usa JQuery.
Se la pagina è più larga di 900 pixel, imposta la larghezza della mappa a 900 pixel, altrimenti a quella disponibile. Poi calcola un’altezza consona secondo quel rapporto.
Poi seleziona il div della mappa e gli assegna quelle dimensioni.
Infine, invoca le API di Bing Maps per comunicare alla mappa che le sue dimensioni devono cambiare, e quella obbedisce di conseguenza.
Forse si può fare il “caching” dei selettori JQuery, forse no, non ho provato.

La cosa fantastica è, per prima cosa, che funziona benissimo ed è velocissima. Funziona così bene ed è così veloce che faccio un’autocitazione della descrizione che ho fatto a 3agle3ye una volta ultimato e provato il javascript qui sopra:

Fulminea, veloce, rapida, veloce, scattante, pr0, HTML5, JS, web 2.0, veloce, si rende responsiva col js, veloce, col codice comprensibile, veloce, funziona, veloce, funziona anche senza mettere la KEY (dice “le credenziali non vanno. Trovati una key, laida bestia” nel mezzo, ma funziona), veloce, non lagga come Google Maps, veloce, non tiene la CPU al 120% costante come Google Maps, non richiede orridi hack per diventare responsive, veloce, moderna.
E veloce.

Oltre ad essere veloce e funzionare benissimo, quando si ridimensiona, lo fa senza spostare il centro in giro, come faceva Google Maps, così è molto più naturale.

Insomma, a ‘sto giro vince Microsoft 20 a 0.

Annunci

2 pensieri su “Rendere Bing Maps responsive

    1. M. Numerio Autore articolo

      È possibile che tu stia dicendo il vero, dopotutto l’API v7 è stata deprecata, da quello che ho capito.

      Eppure a suo tempo funzionava, e tuttora funziona (controllato ora sul sito dove il codice è operativo, deployato in produzione, utilizzato in totale da qualche centinaio di persone) come ha sempre funzionato, che è abbastanza incompatibile con la definizione di “tutto sbagliato” e, a mio modesto parere, l’esperienza empirica è superiore alle affermazioni non dimostrate.

      A parte questo, non ho il tempo e la voglia di riscrivere il codice per la nuova API e magari per non usare jQuery, né il committente del sito mi paga più per aggiornarglielo (in realtà non mi ha pagato nemmeno per farlo, ma ci stava bene dirlo).
      Se vuoi riscriverlo tu, fai pure: poi postalo sul tuo blog e dammi il link che lo aggiungo in cima all’articolo e ti prenderai onore, gloria e traffico; anche se a dire il vero questo post in 1 anno e mezzo ha ricevuto 4 visite in totale…

      Rispondi

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...