在苹果手机上,咱们只要打开定位服务,拍照后便能在相簿中找到地图,地图上显示着在各地拍摄的相片。网站上这种显示方式也并很多见,例如 Flickr、即将关闭的 Panoramio 等。html
做为地图爱好者,往往看到地图就激动不已,就想若能在本身博客上也这么显示,那该多好!git
相片的地理位置信息,是经过手机等设备的 GPS 模块记录的,并在其图片文件的 EXIF 数据,保留了这些位置信息。api
使用七牛作博客图床以来,其图片处理 API 为各类显示需求提供了便利,这其中有个能够获取图片 EXIF 信息的 API,能够很方便的获取到图片的 EXIF 信息,而 EXIF 包含的 GPS 位置信息,则能够实现以上所提到的效果。浏览器
###实现流程网站
EXIF 为位置信息保留了经纬坐标、海拔等,将它转成实际地址信息,或者显示到地图上,还须要配合一个地图 API,在此就以高德地图为例。ui
实现流程大体以下:编码
###获取坐标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 同样支持批量,具体可查看文档。
动态地图
想要在网页中实现跟苹果相册地图差很少样式且可控的地图,这就得用到高德地图 JS API,主要是用到点标记,这里就很少废话了,直接上图。
推荐阅读: