在Smashing Magazine上看到这篇Entering The Wonderful World of Geo Location,介绍了获取并处理用户地理位置的应用和方法,很有意思。结合原文的内容,加上之前的一些应用,整理了几个可以完全在前端实现的地理位置相关小功能。
1.通过IP获取用户位置
很多时候需要通过IP判断用户的位置,通常的办法是通过自己的后台程序查询数据库得到。如果用户位置只是应用在前端,或者有其他的特殊原因(比如,懒:),也有一些其他办法来快速的获取用户位置。
maxmind.com提供了一个服务,通过引入一个js文件(http://j.maxmind.com/app/geoip.js),可以把他判断到的用户的国家、城市、经纬度等信息加入到页面中来。下面是从青岛访问这个js文件返回的内容:
function geoip_country_code() { return 'CN'; } function geoip_country_name() { return 'China'; } function geoip_city() { return 'Qingdao'; } function geoip_region() { return '25'; } function geoip_region_name() { return 'Shandong'; } function geoip_latitude() { return '36.0986'; } function geoip_longitude() { return '120.3719'; } function geoip_postal_code() { return ''; }
我们就可以利用这些信息做很多东西了:DEMO
2.W3C共享位置接口
HTML5加入了的贡献地理位置的浏览器API接口,目前firefox3.5等浏览器已经支持这一功能。
用法:
// if the browser supports the w3c geo api
if(navigator.geolocation){
// get the current position
navigator.geolocation.getCurrentPosition(
// if this was successful, get the latitude and longitude
function(position){
var lat = position.coords.latitude;
var lon = position.coords.longitude;
},
// if there was an error
function(error){
alert('ouch');
});
}
看 DEMO
3.逆经纬度解析
通过浏览器API等方式得到经纬度后,有时需要得到对应的城市名,这就是逆经纬度解析。
google maps api提供了一些经纬度解析方法,如果我们不想引入庞大的api,可以直接使用他的请求地址,通过jsonp方式得到google的经纬度解析数据。jsonp请求地址形式为:
http://ditu.google.cn/maps/geo?
output=json&oe=utf-8&q=纬度%2C经度
&key=你申请到的key
&mapclient=jsapi&hl=zh-CN&callback=myfunction
参数q为经纬度,参数callback为回调函数名。
可以看下这个地址的返回结果,数据非常丰富,并且还是中文的:
myfunction && myfunction( {
"name": "36.06023, 120.3024",
"Status": {
"code": 200,
"request": "geocode"
},
"Placemark": [ {
"id": "p1",
"address": "中国山东省青岛市市南区台西三路6号-10号",
"AddressDetails": {
"Accuracy" : 8,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省",
"Locality" : {
"DependentLocality" : {
"DependentLocalityName" : "市南区",
"Thoroughfare" : {
"ThoroughfareName" : "台西三路6号-10号"
}
},
"LocalityName" : "青岛市"
}
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0633254,
"south": 36.0570301,
"east": 120.3054361,
"west": 120.2991409
}
},
"Point": {
"coordinates": [ 120.3024027, 36.0602271, 0 ]
}
}, {
"id": "p2",
"address": "中国山东省青岛市市南区台西三路8号阿双美容美发厅",
"AddressDetails": {
"Accuracy" : 9,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省",
"Locality" : {
"DependentLocality" : {
"AddressLine" : [ "阿双美容美发厅" ],
"DependentLocalityName" : "市南区",
"Thoroughfare" : {
"ThoroughfareName" : "台西三路8号"
}
},
"LocalityName" : "青岛市"
}
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0632366,
"south": 36.0569414,
"east": 120.3055696,
"west": 120.2992744
}
},
"Point": {
"coordinates": [ 120.3024220, 36.0600890, 0 ]
}
}, {
"id": "p3",
"address": "中国青岛市市南区台西四路站",
"AddressDetails": {
"Accuracy" : 9,
"AddressLine" : [ "台西四路站" ]
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0630636,
"south": 36.0567684,
"east": 120.3063986,
"west": 120.3001034
}
},
"Point": {
"coordinates": [ 120.3032510, 36.0599160, 0 ]
}
}, {
"id": "p4",
"address": "中国青岛市市南区云南路(台西四路口)站",
"AddressDetails": {
"Accuracy" : 9,
"AddressLine" : [ "云南路(台西四路口)站" ]
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0643586,
"south": 36.0580634,
"east": 120.3073456,
"west": 120.3010504
}
},
"Point": {
"coordinates": [ 120.3041980, 36.0612110, 0 ]
}
}, {
"id": "p5",
"address": "中国青岛市市南区贵州路站",
"AddressDetails": {
"Accuracy" : 9,
"AddressLine" : [ "贵州路站" ]
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0614856,
"south": 36.0551904,
"east": 120.3036956,
"west": 120.2974004
}
},
"Point": {
"coordinates": [ 120.3005480, 36.0583380, 0 ]
}
}, {
"id": "p6",
"address": "中国青岛市市南区团岛站",
"AddressDetails": {
"Accuracy" : 9,
"AddressLine" : [ "团岛站" ]
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0629146,
"south": 36.0566194,
"east": 120.3022496,
"west": 120.2959544
}
},
"Point": {
"coordinates": [ 120.2991020, 36.0597670, 0 ]
}
}, {
"id": "p7",
"address": "中国山东省青岛市市南区团岛四路海湾花园",
"AddressDetails": {
"Accuracy" : 9,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省",
"Locality" : {
"DependentLocality" : {
"AddressLine" : [ "海湾花园" ],
"DependentLocalityName" : "市南区",
"Thoroughfare" : {
"ThoroughfareName" : "团岛四路"
}
},
"LocalityName" : "青岛市"
}
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0642706,
"south": 36.0579754,
"east": 120.3006386,
"west": 120.2943434
}
},
"Point": {
"coordinates": [ 120.2974910, 36.0611230, 0 ]
}
}, {
"id": "p8",
"address": "中国山东省青岛市市南区",
"AddressDetails": {
"Accuracy" : 4,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省",
"Locality" : {
"DependentLocality" : {
"DependentLocalityName" : "市南区"
},
"LocalityName" : "青岛市"
}
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 36.0954205,
"south": 36.0413849,
"east": 120.4266629,
"west": 120.2858189
}
},
"Point": {
"coordinates": [ 120.3877350, 36.0667110, 0 ]
}
}, {
"id": "p9",
"address": "中国山东省青岛市",
"AddressDetails": {
"Accuracy" : 4,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省",
"Locality" : {
"LocalityName" : "青岛市"
}
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 36.3313685,
"south": 35.9407727,
"east": 120.6326294,
"west": 120.0970459
}
},
"Point": {
"coordinates": [ 120.3827710, 36.0663480, 0 ]
}
}, {
"id": "p10",
"address": "中国山东省",
"AddressDetails": {
"Accuracy" : 2,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省"
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 38.4055838,
"south": 34.3851760,
"east": 122.7159599,
"west": 114.8033683
}
},
"Point": {
"coordinates": [ 117.0198960, 36.6692270, 0 ]
}
} ]
}
)
Yahoo提供的接口
雅虎提供了一些经纬度查询接口,可以使用YQL查询。
查询语句为:
select * from flickr.places where lat=36.06023 and lon=120.3024
用法:
<script type="text/javascript" charset="utf-8">
function getPlaceFromFlickr(lat,lon,callback){
// the YQL statement
var yql = 'select * from flickr.places where lat='+lat+' and lon='+lon;
// assembling the YQL webservice API
var url = 'http://query.yahooapis.com/v1/public/yql?q='+
encodeURIComponent(yql)+'&format=json&diagnostics='+
'false&callback='+callback;
// create a new script node and add it to the document
var s = document.createElement('script');
s.setAttribute('src',url);
document.getElementsByTagName('head')[0].appendChild(s);
};
// callback in case there is a place found
function output(o){
if(typeof(o.query.results.places.place) != 'undefined'){
alert(o.query.results.places.place.name);
}
}
// call the function with my current lat/lon
getPlaceFromFlickr(36.6692270,117.0198960,'output');
</script>
4.经纬度解析
经纬度解析就是通过地名取得经纬度数据,同样利用google那个请求地址,可以实现这一功能,请求地址格式为:
http://ditu.google.cn/maps/geo?output=json&oe=utf-8
&q=地名的url encode编码
&key=你申请到的key
&mapclient=jsapi&hl=zh-CN&callback=myfunction
参数q为encodeURI(“中国山东省青岛市市北区”),callback是jsonp回调函数名。
举个例子,返回结果:
myfunction && myfunction( {
"name": "中国山东省青岛市市北区",
"Status": {
"code": 200,
"request": "geocode"
},
"Placemark": [ {
"id": "p1",
"address": "中国山东省青岛市市北区",
"AddressDetails": {
"Accuracy" : 4,
"Country" : {
"AdministrativeArea" : {
"AdministrativeAreaName" : "山东省",
"Locality" : {
"DependentLocality" : {
"DependentLocalityName" : "市北区"
},
"LocalityName" : "青岛市"
}
},
"CountryName" : "中国",
"CountryNameCode" : "CN"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 36.1237216,
"south": 36.0515859,
"east": 120.4388307,
"west": 120.3107713
}
},
"Point": {
"coordinates": [ 120.3748010, 36.0876620, 0 ]
}
} ]
}
)
5.google maps 图片接口
有时候我们只想展示简单的地图,不需要交互和拖动,可以通过google maps提供的静态地图API引入动态生成的地图图片,不过需要为你的域名申请一个key。
引入图片的url格式为:
http://maps.google.com/maps/api/staticmap? sensor=false &size=200x200 &maptype=roadmap &key=<em>你申请到的KEY</em> &markers=color:blue|label:1|37.4447,-122.161 &markers=color:red|label:2|37.3385,-121.886 &markers=color:green|label:3|37.3716,-122.038 &markers=color:yellow|label:4|37.7792,-122.42
得到图片:
后记
关于地图的更多操作,可以参见以前的这篇文章:Google Maps Api介绍与基础操作。
随着互联网的发展,越来越多的功能可以在前端实现,出现了越来越多的强大的第三方服务,我们可以很方便的在我们的网站上加入一些实用的功能。这也许就是web2.0的魅力吧。

