iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
0
Modern Web

30天打造我的WebGIS系列 第 23

[Day 23] 在WebGIS中加入Google街景

前言

今天要在地圖中加入另一個元素:街景。
到目前為止介紹的WebGIS應用都是2D的,加入街景環景影像雖然不是3D,但還是比較有身歷其境的感覺,今天我們使用的服務為Google街景。

申請token

跟昨天一樣,使用Google API都要申請token,這邊偷懶地簡單說明一下:
街景服務是被放在Google Javascript API之下,
首先打開連結,按右上角取得金鑰。

然後選取一個專案(如果沒有要另外開啟)。

之後就會取得一組金鑰,這就是token。

加入街景

收先要引入Google API,記得YOUR_KEY是放你的token喔

 <script type="text/javascript"
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&libraries=StreetViewPanorama">
</script>

首先我們沿用昨天的版型,在bottom區塊增加一個id 為googleStreet的div

<div id='googleStreet'></div>

接著在app.js加入

var panorama = new google.maps.StreetViewPanorama(
  document.getElementById('googleStreet'), {
    position: {

      lat: 25.0574304,
      lng: 121.5964764
    },
    pov: { heading: 165, pitch: 0 }
  });

其中呢,lat及lng為經緯度資訊,pov為相片的水平角及俯仰角。

  • heading (預設為 0)使用從正北方算起的相對角度來定義相機焦點的旋轉角度。方向是以順時針方向計算(90 度為正東方)。
  • pitch (預設為 0)定義從相機的初始預設傾斜「往上」或「往下」的角度變化,通常是(但不總是)平面水平。(例如,在山丘上拍到的影像可能會展示不是水平視角的預設傾斜。)傾斜角度的測量是往上仰視為正值(與預設傾斜呈垂直向上的 +90 度),往下俯視為負值(與預設傾斜呈垂直向下的 -90 度)。

成功囉:

加入地圖互動

利用Google的方法,初始化街景影像還不夠,別忘記Google環景還有「小人」這個元素。
我們來加入類似小人的marker,讓街景跟地圖能互動。
要完成這件事需要一些事件綁定,在google.maps.StreetViewPanorama有訂定一些事件:

  • pano_changed 個別全景變更時引發。
  • position_changed 會在全景的底層 (LatLng) 位置變更時引發。旋轉全景將不會觸發此事件。
  • pov_changed 會在「街景服務」的 StreetViewPov 變更時引發。
  • links_changed 會在「街景服務」的連結變更時引發。
  • visible_changed 會在「街景服務」的可見度變更時引發。

移動事件

移動事件這邊使用position_changed,並且在事件中利用getPosition()取得相片所在坐標,把坐標標示一個marker在地圖上

var panoramMan = L.geoJson(null);
panorama.addListener('position_changed', function () {
  map.removeLayer(panoramMan);
  console.log("x:" + panorama.getPosition().lng());
  console.log("y:" + panorama.getPosition().lat());
  panoramMan = L.marker([panorama.getPosition().lat(), panorama.getPosition().lng()]).addTo(map);
  map.setView([panorama.getPosition().lat(), panorama.getPosition().lng()], 17)
});

加入這個事件以後,只要我們在全景視窗中移動,會有一個marker在圖上。
成果:

旋轉事件

要有旋轉的效果,首先先把marker的symbol改成有方向性的圖片:

var streetIcon = L.icon({
  iconUrl: './dist/assets/img/streetman.png',
  iconSize: [32, 32],
});

在加入時設定icon的rotationAngle,值我們可以使用panorama.pov.heading取得轉向。

panoramMan = L.marker([panorama.getPosition().lat(), panorama.getPosition().lng()],
    { rotationAngle: panorama.pov.heading, icon: streetIcon }).addTo(map);


完整程式碼:

var panoramMan = L.geoJson(null);
//圖片
var streetIcon = L.icon({
  iconUrl: './dist/assets/img/streetman.png',
  iconSize: [32, 32],
});
google街景
var panorama = new google.maps.StreetViewPanorama(
  document.getElementById('googleStreet'), {
    position: {
      lat: 25.0574304,
      lng: 121.5964764
    },
    pov: { heading: 165, pitch: 0 }
  });
  
//位置變換事件
panorama.addListener('position_changed', function () {
  map.removeLayer(panoramMan);
  console.log("x:" + panorama.getPosition().lng());
  console.log("y:" + panorama.getPosition().lat());
  console.log("rotation:" + panorama.pov.heading);
  panoramMan = L.marker([panorama.getPosition().lat(), panorama.getPosition().lng()],
    { rotationAngle: panorama.pov.heading, icon: streetIcon }).addTo(map);
  map.setView([panorama.getPosition().lat(), panorama.getPosition().lng()], 17)
});

//旋轉事件
panorama.addListener('pov_changed', function () {
  map.removeLayer(panoramMan);
  console.log("x:" + panorama.getPosition().lng());
  console.log("y:" + panorama.getPosition().lat());
  console.log("rotation:" + panorama.pov.heading);
  panoramMan = L.marker([panorama.getPosition().lat(), panorama.getPosition().lng()],
    { rotationAngle: panorama.pov.heading, icon: streetIcon }).addTo(map);
  map.setView([panorama.getPosition().lat(), panorama.getPosition().lng()], 17)
});

動態成果:

後記

把Google街景接進自己的圖台會讓WebGIS功能更完整,使用的方法也很簡單,提供參考囉!
今天的程式碼一樣放在github(day23的commit)。


上一篇
[Day 22] WebGIS中加入Google Directions導航API
下一篇
[Day 24] 在WebGIS加入Mapillary街景
系列文
30天打造我的WebGIS30

尚未有邦友留言

立即登入留言