鐵人賽Day 23- 在WebGIS中加入Google街景

web
  1. 1. 前言
  2. 2. 申請token
  3. 3. 加入街景
  4. 4. 加入地圖互動
    1. 4.1. 移動事件
    2. 4.2. 旋轉事件
  5. 5. 後記

前言

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

本文是參加鐵人賽的文章,同步發表於 “2018鐵人賽-30天打造我的WebGIS系列”

申請token

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

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

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

加入街景

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

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

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

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

接著在app.js加入

1
2
3
4
5
6
7
8
9
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在地圖上

1
2
3
4
5
6
7
8
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改成有方向性的圖片:

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

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

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


完整程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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)。