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