Moje własne Street View

Google wprowadzając usługę Street View wywołał rewolucję - masowe pojawienie się interaktywnych panoram zrobiło wrażenie. Ciekawy jest także silnik, który pozwala na podział obrazka na mniejsze z większą rozdzielczością - co przyspiesza ściąganie widocznej strony panoramy. Najlepsze jest jednak to, że możemy użyć tej technologii bezpośrednio u siebie na stronie.


Wraz z wdrożeniem trzeciej wersji Google Maps API usługa dostała możliwość wyświetlania panoram w ramach programu StreetView. Jak wiadomo w Polsce niestety usługa ta nie jest dostępna i nie wiadomo kiedy będzie. Zamiast tego API w jednym z kolejnych mniejszych wydań dostało możliwość dodawania własnych panoram - korzystając z silnika Google.

Przygotowanie

A teraz krok po kroku przejdźmy do wdrożenia Street View na naszą stronę. Na początku dobrze jest przygotować jakąś panoramę. Google na swojej stronie przekierowuje nas do listy programów do tworzenia panoram na Wikipedii. Większość programów jest płatna - natomiast często możemy się spotkać z tym, że producenci aparatów fotograficznych (np. Panasonic do Lumix'ów) dołączają do swojego oprogramowania także programy do panoram. Google Street View rozciąga panoramę na kuli - dlatego jeżeli mamy możliwość wyboru typu panoramy to wybieramy kulę (a nie sześcian, walec czy stożek).


Obie panoramy pochodzą z nowo powstałego serwisu www.snieznik.com.

Podstawowe StreetView

Po przygotowaniu obrazka czas na kodowanie. Wszystko zaczyna się od obiektu google.maps.StreetViewPanorama, do którego przekazujemy obiekt, który będzie zawierał panoramę oraz parametry. Wymagane są trzy parametry - nazwa (pano), flaga, czy panorama ma być od razu widoczna po załadowaniu (visible) oraz funkcja, która będzie dostarczać kolejne dane panoramy. Ważne jest to, że ta funkcja jako parametry dostanie także numer kafelka do ściągnięcia, aktualny zoom oraz nazwę podaną w parametrze pano.
var panoOptions = {
  pano: 'reception',
  visible: true,
  panoProvider: getCustomPanorama
}

panorama = new google.maps.StreetViewPanorama(
    document.getElementById('pano_canvas'),panoOptions);

function getCustomPanorama(pano,zoom,tileX,tileY) {
}

Jaką strukturę danych powinna zwracać funkcja getCustomPanorama? Oto pełna lista parametrów zwracanego obiektu:
  • copyright - prawa autorskie do zdjęć
  • location - parametry dla aktualnej lokalizacji
  • tiles - parametry dla fragmentów panoramy
  • links - tablica połączeń z innymi panoramami
{
  copyright: string,
  location: {
    description: string,
    latLng: google.maps.LatLng,
    pano: string
  },
  tiles: {
    tileSize: google.maps.Size,
    worldSize: google.maps.Size,
    heading: number,
    getTileUrl: Function
  },
  links: [
    description: string,
    heading: number,
    pano: string,
    roadColor: string,
    roadOpacity: number
  ]
}

Położenie posiada trzy parametry: opis (description), miejsce na mapie (latLng) oraz nazwę panoramy (pano).
Opis poszczególnych fragmentów panoramy zawierają się w sekcji tiles. W tym przypadku będziemy chcieli wyświetlić panoramę złożoną z jednego zdjęcia - w tym celu parametry tileSize oraz worldSize ustawiamy na tą samą wartość. Tym rozmiarem będzie wielkość naszej panoramy.
new google.maps.Size(1024, 512)
Parametr getTileUrl musi być funkcją (z takimi samymi parametrami jak panoProvider) i dostarcza URL fragmentu panoramy - w naszym przypadku z jednym fragmentem zawsze zwracamy to samo.
function getCustomPanoramaTileUrl(pano,zoom,tileX,tileY) {
  return 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_cje9XwKKIo1vEd9s3aZZWZLJD694UQytYuVlAwIMK9pkE39iA5qTdJlrQ5JSscPhV4L0Q8ZfpqsrC-_-5y0hZO2_AQiyr0rgg2N2e81wb7Y6URZOM9TaeEevDngjTirQQ-spOXn-MRp/s1600/pano1.jpg';
}

Ostatni parametr heading odnosi się do startowego obrotu kamery - zakres od 0 do 360.

Ostatnia sekcja links odnosi się do połączeń panoramy z innymi tego typu elementami. Jest to tablica obiektów, które zawierają:
  • opis (description) kolejnej panoramy
  • obrót (heading)
  • nazwę (pano)
  • kolor linii (roadColor) prowadzącej do następnej panoramy
  • półprzezroczystość linii (roadOpacity)
Jako, że jest to element opcjonalny na początku także z niego zrezygnujemy.
No więc składamy teraz wszystkie elementy w całość i sprawdzimy co z tego wyszło.

function initialize() {
  var panoOptions = {
      pano: 'schronisko',
      visible: true,
      panoProvider: getCustomPanorama
    }

    panorama = new google.maps.StreetViewPanorama(
        document.getElementById('sv'),panoOptions);
}

function getCustomPanoramaTileUrl(pano,zoom,tileX,tileY) {
  return 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_cje9XwKKIo1vEd9s3aZZWZLJD694UQytYuVlAwIMK9pkE39iA5qTdJlrQ5JSscPhV4L0Q8ZfpqsrC-_-5y0hZO2_AQiyr0rgg2N2e81wb7Y6URZOM9TaeEevDngjTirQQ-spOXn-MRp/s1600/pano1.jpg';
}

function getCustomPanorama(pano,zoom,tileX,tileY) {
    switch(pano) {

     case 'schronisko':
       return {
         location: {
           pano: 'schronisko',
           description: "Schronisko na Śnieżniku"
         },
         copyright: 'Michał Biniek',
         tiles: {
           tileSize: new google.maps.Size(2000,1000),
           worldSize: new google.maps.Size(2000,1000),
           centerHeading: 0,
           getTileUrl: getCustomPanoramaTileUrl
         }
       };
       break;
   }
}
A oto działający przykład:

A na stronie z przykładami znajdziemy ten sam przykład, ale z większą rozdzielczością.

Łączenie kolejnych StreetView

Aby umożliwić przejście z jednej panoramki do drugiej (połączyć je drogą) konieczne jest zdefiniowanie parametru links, dla każdej z panoram. Najważniejszym parametrem jest nazwa (pano) kolejnej panoramy - ponieważ ten parametr jest przekazywany do funkcji podanej w panoProvider. Kierunek strzałki definiujemy parametrem heading, zaś opis na strzałce parametrem description. Po uzupełnieniu tych danych przy każdej z panoram funkcja getCustomPanorama wygląda następująco:
function getCustomPanorama(pano,zoom,tileX,tileY) {
    switch(pano) {
     case 'schronisko':
       return {
         location: {
           pano: 'schronisko',
           latLng: new google.maps.LatLng(50.208377,16.83216),
           description: "Schronisko na Śnieżniku"
         },
         copyright: 'Michał Biniek',
         links: [
           {
            pano: 'szczyt',
            heading: 240,
            description: 'na szczyt'
           }
         ],
         tiles: {
           tileSize: new google.maps.Size(2000,1000),
           worldSize: new google.maps.Size(2000,1000),
           centerHeading: 0,
           getTileUrl: getCustomPanoramaTileUrl
         }
       };
       break;
     case 'szczyt':
         return {
           location: {
             pano: 'szczyt',
             latLng: new google.maps.LatLng(50.207601,16.84703),
             description: "Śnieżnik"
           },
           links: [
             {
              pano: 'schronisko',
              heading: 140,
              description: 'do schroniska'
             }
           ],
           copyright: 'Michał Biniek',
           tiles: {
             tileSize: new google.maps.Size(2000,1000),
             worldSize: new google.maps.Size(2000,1000),
             centerHeading: 0,
             getTileUrl: getCustomPanoramaTileUrl
           }
         };
         break;
   }
}

Na stronie z przykładami znajdziemy ten sam przykład, ale z większą rozdzielczością.

W ten sposób w naszym lokalnym StreetView mamy już dwie panoramy z charakterystycznymi dla produktu Google elementami interfejsu użytkownika (strzałki, wskazywanie kierunku).
Co prawda widać, że mechanizm nie jest identyczny jak w gotowym produkcie (brak efektu rozmazania, prędkość działania itp.) natomiast trzeba przyznać, że jest to idealna metoda do szybkiego wdrożenia takiej funkcjonalności na naszej stronie.

Prześlij dalej:

3 komentarze:

Bigismall pisze...

Kolejne świetne rozwiązanie od Google.
Bardzo przydatny wpis! Szacun!

Kamil pisze...

Kolejny dobry wpis, na którym pokazujesz nietuzinkowe i bardzo rzadko spotykane w Sieci, aczkolwiek niezwykle ciekawe rozwiązania! Taka wiedza na pewno się przyda, dziękuję bardzo ;)

Anonimowy pisze...

Dobra robota. Tego potrzebowałem. Pozdro Przemo

Prześlij komentarz