動手實操 | 如何用七牛雲 API 實現相片地圖?

實操玩家
實操玩家

在蘋果手機上,咱們只要打開定位服務,拍照後便能在相簿中找到地圖,地圖上顯示着在各地拍攝的相片。網站上這種顯示方式也並很多見,例如 Flickr、即將關閉的 Panoramio 等。html

做爲地圖愛好者,往往看到地圖就激動不已,就想若能在本身博客上也這麼顯示,那該多好!git

攝於汕頭市澄海區蓮下鎮▲ 蘋果手機上的相片地圖
攝於汕頭市澄海區蓮下鎮▲ 蘋果手機上的相片地圖

相片的地理位置信息,是經過手機等設備的 GPS 模塊記錄的,並在其圖片文件的 EXIF 數據,保留了這些位置信息。api

使用七牛作博客圖牀以來,其圖片處理 API 爲各類顯示需求提供了便利,這其中有個能夠獲取圖片 EXIF 信息的 API,能夠很方便的獲取到圖片的 EXIF 信息,而 EXIF 包含的 GPS 位置信息,則能夠實現以上所提到的效果。瀏覽器

###實現流程網站

EXIF 爲位置信息保留了經緯座標、海拔等,將它轉成實際地址信息,或者顯示到地圖上,還須要配合一個地圖 API,在此就以高德地圖爲例。ui

實現流程大體以下編碼

  • 請求數據:利用七牛 API 請求獲取圖片的 GPS 信息
  • 轉換座標:因相片的座標數據是以 WGS84 座標系統爲準的,得轉換座標
  • 顯示地址:經過高德地圖 API 實現

###獲取座標spa

咱們仍是以一張圖片爲例,來分析下如何實現。3d

蓮陽河畔,渡亭堤頂的花
蓮陽河畔,渡亭堤頂的花

上圖是在汕頭市澄海區蓮下鎮渡亭村蓮陽河畔拍的花,其圖片地址以下:rest

source.fooleap.org/show-photo-…

那麼,七牛圖片 EXIF 信息的接口以下:
source.fooleap.org/show-photo-…

直接用瀏覽器打開,能夠很方便地找到全部 GPS 開頭的屬性。其中,海拔等數據能夠忽略掉,位置信息最爲重要的是經緯座標,即如下四個值:

"GPSLatitude": {       
        "val": "23, 29, 10.91",       
        "type": 5   
     },   
     "GPSLatitudeRef": {       
        "val": "N",       
       "type": 2   
     },  
     "GPSLongitude": {       
        "val": "116, 46, 36.49",       
        "type": 5   
     },   
     "GPSLongitudeRef": {       
        "val": "E",       
        "type": 2   
  }
}複製代碼

那麼這個座標爲 23°29’10.91」N, 116°46’36.49」E,也就是北緯 24 度 29 分 10.91 秒,東經 116 度 46 分 36.49 秒。

在各類互聯網地圖上,座標是以度爲單位的,東經北緯爲正值,西經南緯爲負值。這裏須要將度分秒的經緯度轉換以度爲單位的,因度分秒之間爲 60 進制,故轉換公式爲:
度分秒 = 度 + 分 / 60 + 秒 / (60 * 60)

計算後得出上面的座標約爲 116.776803, 23.486364,這是一個 WGS84 座標。

座標轉換此前已經說過很多了,因在網頁上使用,直接採用 coordtransform 模塊便可,以上座標轉換爲 GCJ02 是 116.781381, 23.483788。

可使用高德的座標拾取系統,按座標搜索一下,驗證結果是否正確。

以上過程使用 JS 實現代碼以下,需引入 coordtransform 模塊。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://source.fooleap.org/show-photo-location-on-map-with-qiniu-and-amap-api.jpg?exif', true);
xhr.onreadystatechange = function() {   
if (xhr.readyState == 4 && xhr.status == 200)   
{       
    var data = JSON.parse(xhr.responseText);       
    if ( !!data.GPSLongitude ) {           
       var olat = data.GPSLatitude.val.split(', ');           
       var olng = data.GPSLongitude.val.split(', ');           
       var lat=0, lng=0, coord;           
       for( var i = 0; i < olat.length; i++ ){               
          lat += olat[i] / Math.pow(60, i);               
          lng += olng[i] / Math.pow(60, i);           
      }           
      lat = data.GPSLatitudeRef.val == 'S' ? -lat: lat;           
      lng = data.GPSLongitudeRef.val == 'W' ? -lng: lng;           
      coord = coordtransform.wgs84togcj02(lng, lat).join(',');       
    }   
 }
}
xhr.send();複製代碼

獲取圖片地址信息

有了座標就有了地理位置,有了地理位置就知道是什麼地方。高德地圖逆地理編碼 API 正在招手:「給我一個座標,我將還你一個詳細地址。」

根據文檔,最基本的只需 location 參數傳個座標便可返回地址信息。此 API 還可批量獲取,能夠根據本身需求傳入可選的參數。

以上面獲取的座標爲例:

http://restapi.amap.com/v3/geocode/regeo?location=116.781381,23.48378&key=
  
  <用戶的key>
  

 複製代碼

請求後返回的 JSON 以下,具體返回的參數的詳細說明參考文檔。

{
    "status": "1",
    "info": "OK",
    "infocode": "10000",
    "regeocode": {
        "formatted_address": "廣東省汕頭市澄海區蓮下鎮渡亭村",
        "addressComponent": {
            "country": "中國",
            "province": "廣東省",
            "city": "汕頭市",
            "citycode": "0754",
            "district": "澄海區",
            "adcode": "440515",
            "township": "蓮下鎮",
            "towncode": "440515102000",
            "neighborhood": {
                "name": [],
                "type": []
            },
            "building": {
                "name": [],
                "type": []
            },
            "streetNumber": {
                "street": "文明路",
                "number": "159號",
                "location": "116.78592,23.48872",
                "direction": "東北",
                "distance": "718.365"
            },
            "businessAreas": [
                []
            ]
        }
    }
}複製代碼

準確度通常般,到鄉(鎮、街道)這一級基本沒問題。咱們也不須要太準確的信息,畢竟定位信息有時候仍是挺隱私的。

顯示相片地圖

將相片顯示在地圖上,這彷佛纔是初衷,在這裏,我將它分紅兩部分,一部分是靜態地圖,一部分是動態地圖。

靜態地圖

將圖片顯示到靜態地圖上面,須要用到的高德地圖 API 是靜態地圖 API。

根據高德的文檔,自定義標註(marker)圖片只能支持 PNG 格式,須要多來一張圖片嗎?不須要,這裏能夠直接用七牛圖片處理 API,將原圖調下大小並指定輸出格式。

http://source.fooleap.org/show-photo-location-on-map-with-qiniu-and-amap-api.jpg?imageView2/1/w/100/h/100/format/png複製代碼

上面的連接是輸出等比縮放並居中裁剪的 100x100 PNG 格式圖片,然而應用到高德接口仍是出錯了。我嘗試在最後再加上 .png,結果成功,這意味着高德是之後綴名判斷文件格式的,也是醉了。

http://restapi.amap.com/v3/staticmap?zoom=12&size=640*427&scale=2&markers=-1,http://source.fooleap.org/show-photo-location-on-map-with-qiniu-and-amap-api.jpg?imageView2/1/w/100/h/100/format/png.png,0:116.781381,23.48378&key=
  
  <用戶的key>
  

 複製代碼

以上拼湊出的連接顯示以下。

▲ 高德靜態地圖 API 顯示相片位置
▲ 高德靜態地圖 API 顯示相片位置

高德靜態地圖 API 同樣支持批量,具體可查看文檔。

動態地圖

想要在網頁中實現跟蘋果相冊地圖差很少樣式且可控的地圖,這就得用到高德地圖 JS API,主要是用到點標記,這裏就很少廢話了,直接上圖。


推薦閱讀:

相關文章
相關標籤/搜索