Google Maps JavaScript API: StreetView

Nel mio ultimo post abbiamo visto come utilizzare le API Javascript di Google Maps che ci permettono di aggiungere mappe interattive nelle nostre web application. In questa seconda carrellata di esempi ci occuperemo dell’integrazione con un’altra parte delle API: quella che ci permette di integrare Google StreetView.

Posizione e POV

L’oggetto alla base di StreetView è il panorama. Vediamo subito con questo primo esempio, come aggiungere uno ad una pagina web.

var COORDINATES = [
        {lat: 43.88907, lng: 11.09802},
        {lat: 43.8665949, lng: 11.1561196},
        {lat: 43.523302, lng: 13.244851}
    ];

    window.MapExperiments = {
        currentPositionIndex:0,
        panorama:null,
        initMap:function() {
            MapExperiments.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
                disableDefaultUI:true,
                position: COORDINATES[this.currentPositionIndex],
                pov:{
                    heading:0,
                    pitch:0
                }
            });
        },
        turnLeft:function(){
            var pov = MapExperiments.panorama.getPov();
            pov.heading -= 90;
            MapExperiments.panorama.setPov(pov);
        },
        turnRight:function(){
            var pov = MapExperiments.panorama.getPov();
            pov.heading += 90;
            MapExperiments.panorama.setPov(pov);
        },
        nextLocation:function(){
            this.currentPositionIndex++;
            if(this.currentPositionIndex === COORDINATES.length){
                this.currentPositionIndex = 0;
            }
            MapExperiments.panorama.setPosition(COORDINATES[this.currentPositionIndex]);
        },
        previousLocation:function(){
            this.currentPositionIndex--;
            if(this.currentPositionIndex < 0){
                this.currentPositionIndex = COORDINATES.length - 1;
            }
            MapExperiments.panorama.setPosition(COORDINATES[this.currentPositionIndex]);
        }
    };

Per poter utilizzare StreetView dovete quindi inizializzare un oggetto google.maps.StreetViewPanorama ai quali dovete passare oltre alla position anche il Point of View (POV). In pratica dovete impostare la posizione della vostra “testa” all’interno dello spazio. Il primo parametro heading definisce la rotazione verso destra o sinistra. La rotazione è oraria; in pratica con un valore positivo si gira verso destra, con uno negativo verso sinistra. L’altro parametro pitch invece indica l’inclinazione verso l’alto o il basso. In questo caso un valore positivo indica andare verso l’alto mentre il negativo verso il basso. Potete testare il codice che avete appena visto in questa demo.

Ecco a voi il centro di Jesi!

Ecco a voi il centro di Jesi!

Integrazione con Google Maps

Essendo StreetView parte integrante delle Google Maps API, è davvero semplice integrare le due tecnologie. Vediamo subito come.

var JESI = {lat: 43.523302, lng: 13.244851};

window.MapExperiments = {
    showPanorama:false,
    panorama:null,
    map:null,
    initMap:function() {

        MapExperiments.map = new google.maps.Map(document.getElementById('map'), {
            center: JESI,
            zoom: 15
        });

        var marker = new google.maps.Marker({
            position: JESI,
            map: MapExperiments.map
        });

        MapExperiments.panorama = MapExperiments.map.getStreetView();
        MapExperiments.panorama.setPosition(JESI);
    },
    toggle:function(){
        MapExperiments.showPanorama = !MapExperiments.showPanorama;
        MapExperiments.panorama.setVisible(MapExperiments.showPanorama);
    }
};

In questo secondo esempio (navigabile qui) potete vedere come sia semplice switchare tra una mappa e il suo corrispettivo StreetView. Ogni oggetto google.maps.Map mette a disposizione un panorama StreetView tramite il metodo getStreetView che poi possiamo mostrare/nascondere tramite setVisible.

Eventi

Esattamente come le mappe anche per StreetView è possibile rispondere agli input degli utenti tramite un sistema ad eventi. Come potrete vedere nel prossimo esempio il modo in cui possiamo registrarci agli eventi lanciati dal panorama è esattamente identico a quello delle mappe viste nello scorso post.

var START_PANO_ID = 'yR1Jtop3gccwt7BNHcDCyA';

var printPanoramaData = function(panorama){
    document.getElementById('heading').innerHTML = panorama.getPov().heading;
    document.getElementById('pitch').innerHTML = panorama.getPov().pitch;
    document.getElementById('pano').innerHTML = panorama.getPano();
    document.getElementById('position').innerHTML = panorama.getPosition();
};

window.MapExperiments = {
    panorama:null,
    initMap:function() {
        MapExperiments.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
            pano: START_PANO_ID
        });

        MapExperiments.panorama.addListener('pov_changed',function(){
            printPanoramaData(MapExperiments.panorama);
        });

        MapExperiments.panorama.addListener('pano_changed',function(){
            printPanoramaData(MapExperiments.panorama);
        });

        MapExperiments.panorama.addListener('position_changed',function(){
            printPanoramaData(MapExperiments.panorama);
        });

        //Initial data printing
        printPanoramaData(MapExperiments.panorama);
    }
};

Sbirciando nella demo noterete che non stiamo visitando un luogo all’aperto come al solito, ma l’interno di un ufficio. In particolare il mio ufficio in extrategy. Questa cosa è possibile tramite l’utilizzo di un panoId invece che di una position. Ci sono moltissimi luoghi esplorabili tramite StreetView e per estrarre il panoId potete utilizzare questo tool.

Mi casa es tu casa! ;)

Mi casa es tu casa! 😉

Panorami Custom

Vediamo infine come poter utilizzare foto custom per i nostri panorami StreetView. Ovviamente le foto che dovremo andare a utilizzare dovranno essere preparate appositamente per questo utilizzo come potete leggere nella documentazione ufficiale di Google. Nel prossimo esempio utilizzeremo un’immagine fornita da Google, la reception di una delle loro sedi.

var getCustomPanorama = function(pano, zoom, tileX, tileY) {
    return {
      location: {
        pano: 'custom_panorama',
        description: 'Google Sydney - Reception'
      },
      copyright: 'Imagery (c) 2010 Google',
      tiles: {
        tileSize: new google.maps.Size(1024, 512),
        worldSize: new google.maps.Size(1024, 512),
        getTileUrl: function(pano, zoom, tileX, tileY){
            return 'https://developers.google.com/maps/documentation/javascript/examples/full/images/panoReception1024-0.jpg'
        }
      }
    };
}

window.MapExperiments = {
    currentPositionIndex:0,
    panorama:null,
    initMap:function() {
        MapExperiments.panorama = new google.maps.StreetViewPanorama(document.getElementById('panorama'), {
            disableDefaultUI:true,
            pano: 'custom_panorama',
            panoProvider: getCustomPanorama
        });
    }
};

Notate come questa volta abbiamo definito un panoProvider, factory che torna i metadati del panorama corrente sulla base del nome del panorama scelto (in questo fissato costantemente a custom_panorama) e al POV attuale definito da zoom e coordinate. In questo semplice esempio la funzione getTileUrl torna sempre la stessa immagine, ma in un caso reale questa immagine dovrebbe cambiare al cambiare dei parametri e Google stessa consiglia di utilizzare deli url parlanti per le immagini in questa forma.

BASE_URL + zoom + '-' + tileX + '-' + tileY + '.jpg'

Se date uno sguardo alla demo noterete che la qualità dell’immagine non è all’altezza degli altri esempi. Questo proprio perché l’immagine non cambia al cambiare dello zoom e del POV.

Conclusioni

Anche in questo caso sono rimasto molto soddisfatto dalle API di Google, semplici e chiare. Questa API può sembrare poco utile rispetto alle mappe viste in precedenza, ma se usate nel giusto contesto possono portarvi ad un livello di una spanna superiore rispetto alla concorrenza.

Per chi è interessato tutto il codice del progetto è disponibile in questo repository GitHub. Alla prossima.

Francesco Strazzullo

Faccio il Front-end developer per e-xtrategy dove mi occupo di applicazioni AngularJS e mobile. In passato ho lavorato principalmente con applicazioni con stack Spring+Hibernate+JSF 2.X+Primefaces. Sono tra i collaboratori del progetto Primefaces Extensions: suite di componenti aggiuntivi ufficialmente riconosciuta da Primefaces. Sono anche uno dei fondatori del progetto MaterialPrime: una libreria JSF che segue le direttive del Material Design di Google.