可以在前端实现的几个地理位置小功能
下文转自:http://www.oncoding.cn/2010/geo-location-frontend
在Smashing Magazine上看到这篇Entering The Wonderful World of Geo Location ,介绍了获取并处理用户地理位置的应用和方法, 很有意思。结合原文的内容,加上之前的一些应用,整理了几个可以完全在前端实现的地理位置相关小功能。
1.通过IP获取用户位置
很多时候需要通过IP判断用户的位置,通常的办法是通过自己的后台程序查询数据库得到。如果用户位置只是应用在前端,或者有其他的特殊原因(比如, 懒:),也有一些其他办法来快速的获取用户位置。
maxmind.com 提供了一个 服务,通过引入一个js文件(http://j.maxmind.com/app/geoip.js ), 可以把他判断到的用户的国家、城市、经纬度等信息加入到页面中来。下面是从青岛访问这个js文件返回的内容:
1
|
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等浏览器已经支持这一功能。
用法:
01
|
// if the browser supports the w3c geo api
|
02
|
if
(navigator.geolocation){
|
03
|
// get the current position
|
04
|
navigator.geolocation.getCurrentPosition(
|
05
|
06
|
// if this was
successful, get the latitude and longitude
|
07
|
function
(position){
|
08
|
var
lat =
position.coords.latitude;
|
09
|
var
lon =
position.coords.longitude;
|
10
|
},
|
11
|
// if there was
an error
|
12
|
function
(error){
|
13
|
alert(
'ouch'
);
|
14
|
});
|
15
|
}
|
看 DEMO
3. Google Gears 的 Geolocation API
Google Gears 是主 要提供本地存储功能的浏览器扩展,新版本的Gears中,加入了判断用户地理位置的API,通过IP、WIFI热点等判断位置。不过Gears的使用似乎 并不太广泛(Chrome内置了Gears,其他浏览器需要安装),国内的地理位置信息也不够丰富,所以这个应用目前只可作为参考。
使用Gears的基本方法看这里 ,引 入gears_init.js ,使用Geolocation API的程序为:
1
|
var
geo =
factory.create(
'beta.geolocation'
);
//创建
geolocation对象
|
2
|
var
okCallback =
function
(d){
|
3
|
alert(
'当前位置(纬度,经度): '
+ d.latitude +
','
+ d.longitude);
|
4
|
};
|
5
|
var
errorCallback =
function
(err){
|
6
|
alert(err.message);
|
7
|
};
|
8
|
geo.getCurrentPosition(okCallback
, errorCallback);
|
更多内容参考这篇文章:使用Gears获取当前地理位置 ,以及DEMO 。
4.逆经纬度解析
通过浏览器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为回调函数名。
可以看下这 个地址 的返回结果,数据非常丰富,并且还是中文的:
001
|
myfunction && myfunction( {
|
002
|
"name"
:
"36.06023, 120.3024"
,
|
003
|
"Status"
: {
|
004
|
"code"
: 200,
|
005
|
"request"
:
"geocode"
|
006
|
},
|
007
|
"Placemark"
: [ {
|
008
|
"id"
:
"p1"
,
|
009
|
"address"
:
"中国山东省青岛市市南区台西三路6号-10号"
,
|
010
|
"AddressDetails"
: {
|
011
|
"Accuracy"
: 8,
|
012
|
"Country"
: {
|
013
|
"AdministrativeArea"
: {
|
014
|
"AdministrativeAreaName"
:
"山东省"
,
|
015
|
"Locality"
: {
|
016
|
"DependentLocality"
: {
|
017
|
"DependentLocalityName"
:
"市南区"
,
|
018
|
"Thoroughfare"
:
{
|
019
|
"ThoroughfareName"
:
"台西三路
6号-10号"
|
020
|
}
|
021
|
},
|
022
|
"LocalityName"
:
"青岛市"
|
023
|
}
|
024
|
},
|
025
|
"CountryName"
:
"中国"
,
|
026
|
"CountryNameCode"
:
"CN"
|
027
|
}
|
028
|
},
|
029
|
"ExtendedData"
: {
|
030
|
"LatLonBox"
: {
|
031
|
"north"
:
36.0633254,
|
032
|
"south"
: 36.0570301,
|
033
|
"east"
:
120.3054361,
|
034
|
"west"
: 120.2991409
|
035
|
}
|
036
|
},
|
037
|
"Point"
: {
|
038
|
"coordinates"
: [ 120.3024027,
36.0602271, 0 ]
|
039
|
}
|
040
|
}, {
|
041
|
"id"
:
"p2"
,
|
042
|
"address"
:
"中国山东省青岛市市南区台西三路8号阿双美容美发厅"
,
|
043
|
"AddressDetails"
: {
|
044
|
"Accuracy"
: 9,
|
045
|
"Country"
: {
|
046
|
"AdministrativeArea"
: {
|
047
|
"AdministrativeAreaName"
:
"山东省"
,
|
048
|
"Locality"
: {
|
049
|
"DependentLocality"
: {
|
050
|
"AddressLine"
: [
"阿双
美容美发厅"
],
|
051
|
"DependentLocalityName"
:
"市南区"
,
|
052
|
"Thoroughfare"
:
{
|
053
|
"ThoroughfareName"
:
"台西三路
8号"
|
054
|
}
|
055
|
},
|
056
|
"LocalityName"
:
"青岛市"
|
057
|
}
|
058
|
},
|
059
|
"CountryName"
:
"中国"
,
|
060
|
"CountryNameCode"
:
"CN"
|
061
|
}
|
062
|
},
|
063
|
"ExtendedData"
: {
|
064
|
"LatLonBox"
: {
|
065
|
"north"
:
36.0632366,
|
066
|
"south"
: 36.0569414,
|
067
|
"east"
:
120.3055696,
|
068
|
"west"
: 120.2992744
|
069
|
}
|
070
|
},
|
071
|
"Point"
: {
|
072
|
"coordinates"
: [ 120.3024220,
36.0600890, 0 ]
|
073
|
}
|
074
|
}, {
|
075
|
"id"
:
"p3"
,
|
076
|
"address"
:
"中国青岛市市南区台西四路站"
,
|
077
|
"AddressDetails"
: {
|
078
|
"Accuracy"
: 9,
|
079
|
"AddressLine"
: [
"台西四路站"
]
|
080
|
},
|
081
|
"ExtendedData"
: {
|
082
|
"LatLonBox"
: {
|
083
|
"north"
:
36.0630636,
|
084
|
"south"
: 36.0567684,
|
085
|
"east"
:
120.3063986,
|
086
|
"west"
: 120.3001034
|
087
|
}
|
088
|
},
|
089
|
"Point"
: {
|
090
|
"coordinates"
: [ 120.3032510,
36.0599160, 0 ]
|
091
|
}
|
092
|
}, {
|
093
|
"id"
:
"p4"
,
|
094
|
"address"
:
"中国青岛市市南区云南路(台西四路口)站"
,
|
095
|
"AddressDetails"
: {
|
096
|
"Accuracy"
: 9,
|
097
|
"AddressLine"
: [
"云南路(台西四路口)站"
]
|
098
|
},
|
099
|
"ExtendedData"
: {
|
100
|
"LatLonBox"
: {
|
101
|
"north"
:
36.0643586,
|
102
|
"south"
: 36.0580634,
|
103
|
"east"
:
120.3073456,
|
104
|
"west"
: 120.3010504
|
105
|
}
|
106
|
},
|
107
|
"Point"
: {
|
108
|
"coordinates"
: [ 120.3041980,
36.0612110, 0 ]
|
109
|
}
|
110
|
}, {
|
111
|
"id"
:
"p5"
,
|
112
|
"address"
:
"中国青岛市市南区贵州路站"
,
|
113
|
"AddressDetails"
: {
|
114
|
"Accuracy"
: 9,
|
115
|
"AddressLine"
: [
"贵州路站"
]
|
116
|
},
|
117
|
"ExtendedData"
: {
|
118
|
"LatLonBox"
: {
|
119
|
"north"
:
36.0614856,
|
120
|
"south"
: 36.0551904,
|
121
|
"east"
:
120.3036956,
|
122
|
"west"
: 120.2974004
|
123
|
}
|
124
|
},
|
125
|
"Point"
: {
|
126
|
"coordinates"
: [ 120.3005480,
36.0583380, 0 ]
|
127
|
}
|
128
|
}, {
|
129
|
"id"
:
"p6"
,
|
130
|
"address"
:
"中国青岛市市南区团岛站"
,
|
131
|
"AddressDetails"
: {
|
132
|
"Accuracy"
: 9,
|
133
|
"AddressLine"
: [
"团岛站"
]
|
134
|
},
|
135
|
"ExtendedData"
: {
|
136
|
"LatLonBox"
: {
|
137
|
"north"
:
36.0629146,
|
138
|
"south"
: 36.0566194,
|
139
|
"east"
:
120.3022496,
|
140
|
"west"
: 120.2959544
|
141
|
}
|
142
|
},
|
143
|
"Point"
: {
|
144
|
"coordinates"
: [ 120.2991020,
36.0597670, 0 ]
|
145
|
}
|
146
|
}, {
|
147
|
"id"
:
"p7"
,
|
148
|
"address"
:
"中国山东省青岛市市南区团岛四路海湾花园"
,
|
149
|
"AddressDetails"
: {
|
150
|
"Accuracy"
: 9,
|
151
|
"Country"
: {
|
152
|
"AdministrativeArea"
: {
|
153
|
"AdministrativeAreaName"
:
"山东省"
,
|
154
|
"Locality"
: {
|
155
|
"DependentLocality"
: {
|
156
|
"AddressLine"
: [
"海湾
花园"
],
|
157
|
"DependentLocalityName"
:
"市南区"
,
|
158
|
"Thoroughfare"
:
{
|
159
|
"ThoroughfareName"
:
"团岛四
路"
|
160
|
}
|
161
|
},
|
162
|
"LocalityName"
:
"青岛市"
|
163
|
}
|
164
|
},
|
165
|
"CountryName"
:
"中国"
,
|
166
|
"CountryNameCode"
:
"CN"
|
167
|
}
|
168
|
},
|
169
|
"ExtendedData"
: {
|
170
|
"LatLonBox"
: {
|
171
|
"north"
:
36.0642706,
|
172
|
"south"
: 36.0579754,
|
173
|
"east"
:
120.3006386,
|
174
|
"west"
: 120.2943434
|
175
|
}
|
176
|
},
|
177
|
"Point"
: {
|
178
|
"coordinates"
: [ 120.2974910,
36.0611230, 0 ]
|
179
|
}
|
180
|
}, {
|
181
|
"id"
:
"p8"
,
|
182
|
"address"
:
"中国山东省青岛市市南区"
,
|
183
|
"AddressDetails"
: {
|
184
|
"Accuracy"
: 4,
|
185
|
"Country"
: {
|
186
|
"AdministrativeArea"
: {
|
187
|
"AdministrativeAreaName"
:
"山东省"
,
|
188
|
"Locality"
: {
|
189
|
"DependentLocality"
: {
|
190
|
"DependentLocalityName"
:
"市南区"
|
191
|
},
|
192
|
"LocalityName"
:
"青岛市"
|
193
|
}
|
194
|
},
|
195
|
"CountryName"
:
"中国"
,
|
196
|
"CountryNameCode"
:
"CN"
|
197
|
}
|
198
|
},
|
199
|
"ExtendedData"
: {
|
200
|
"LatLonBox"
: {
|
201
|
"north"
:
36.0954205,
|
202
|
"south"
: 36.0413849,
|
203
|
"east"
:
120.4266629,
|
204
|
"west"
: 120.2858189
|
205
|
}
|
206
|
},
|
207
|
"Point"
: {
|
208
|
"coordinates"
: [ 120.3877350,
36.0667110, 0 ]
|
209
|
}
|
210
|
}, {
|
211
|
"id"
:
"p9"
,
|
212
|
"address"
:
"中国山东省青岛市"
,
|
213
|
"AddressDetails"
: {
|
214
|
"Accuracy"
: 4,
|
215
|
"Country"
: {
|
216
|
"AdministrativeArea"
: {
|
217
|
"AdministrativeAreaName"
:
"山东省"
,
|
218
|
"Locality"
: {
|
219
|
"LocalityName"
:
"青岛市"
|
220
|
}
|
221
|
},
|
222
|
"CountryName"
:
"中国"
,
|
223
|
"CountryNameCode"
:
"CN"
|
224
|
}
|
225
|
},
|
226
|
"ExtendedData"
: {
|
227
|
"LatLonBox"
: {
|
228
|
"north"
:
36.3313685,
|
229
|
"south"
: 35.9407727,
|
230
|
"east"
:
120.6326294,
|
231
|
"west"
: 120.0970459
|
232
|
}
|
233
|
},
|
234
|
"Point"
: {
|
235
|
"coordinates"
: [ 120.3827710,
36.0663480, 0 ]
|
236
|
}
|
237
|
}, {
|
238
|
"id"
:
"p10"
,
|
239
|
"address"
:
"中国山东省"
,
|
240
|
"AddressDetails"
: {
|
241
|
"Accuracy"
: 2,
|
242
|
"Country"
: {
|
243
|
"AdministrativeArea"
: {
|
244
|
"AdministrativeAreaName"
:
"山东省"
|
245
|
},
|
246
|
"CountryName"
:
"中国"
,
|
247
|
"CountryNameCode"
:
"CN"
|
248
|
}
|
249
|
},
|
250
|
"ExtendedData"
: {
|
251
|
"LatLonBox"
: {
|
252
|
"north"
:
38.4055838,
|
253
|
"south"
: 34.3851760,
|
254
|
"east"
:
122.7159599,
|
255
|
"west"
: 114.8033683
|
256
|
}
|
257
|
},
|
258
|
"Point"
: {
|
259
|
"coordinates"
: [ 117.0198960,
36.6692270, 0 ]
|
260
|
}
|
261
|
} ]
|
262
|
}
|
263
|
)
|
Yahoo提供的接口
雅虎提供了一些经纬度查询接口,可以使用YQL 查询。
查询语句为:
1
|
select
*
from
flickr.places
where
lat=36.06023
and
lon=120.3024
|
用法:
01
|
<script type=
"text/javascript"
charset=
"utf-8"
>
|
02
|
function
getPlaceFromFlickr(lat,lon,callback){
|
03
|
// the YQL statement
|
04
|
var
yql =
'select * from flickr.places where lat='
+lat+
' and
lon='
+lon;
|
05
|
06
|
// assembling
the YQL webservice API
|
07
|
var
url =
'http://query.yahooapis.com/v1/public/yql?q=
'
+
|
08
|
encodeURIComponent(yql)+
'&format=json&diagnostics='
+
|
09
|
'false&callback='
+callback;
|
10
|
11
|
// create a new
script node and add it to the document
|
12
|
var
s =
document.createElement(
'script'
);
|
13
|
s.setAttribute(
'src'
,url);
|
14
|
document.getElementsByTagName(
'head'
)[0].appendChild(s);
|
15
|
};
|
16
|
17
|
// callback in case there is a place found
|
18
|
function
output(o){
|
19
|
if
(
typeof
(o.query.results.places.place)
!=
'undefined'
){
|
20
|
alert(o.query.results.places.place.name);
|
21
|
}
|
22
|
}
|
23
|
24
|
// call the
function with my current lat/lon
|
25
|
getPlaceFromFlickr(36.6692270,117.0198960,
'output'
);
|
26
|
</script>
|
5.经纬度解析
经纬度解析就是通过地名取得经纬度数据,同样利用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回调函数名。
举 个例子 ,返回结果:
01
|
myfunction && myfunction( {
|
02
|
"name"
:
"中国山东省青岛市市北区"
,
|
03
|
"Status"
: {
|
04
|
"code"
: 200,
|
05
|
"request"
:
"geocode"
|
06
|
},
|
07
|
"Placemark"
: [ {
|
08
|
"id"
:
"p1"
,
|
09
|
"address"
:
"中国山东省青岛市市北区"
,
|
10
|
"AddressDetails"
: {
|
11
|
"Accuracy"
: 4,
|
12
|
"Country"
: {
|
13
|
"AdministrativeArea"
: {
|
14
|
"AdministrativeAreaName"
:
"山东省"
,
|
15
|
"Locality"
: {
|
16
|
"DependentLocality"
: {
|
17
|
"DependentLocalityName"
:
"市北区"
|
18
|
},
|
19
|
"LocalityName"
:
"青岛市"
|
20
|
}
|
21
|
},
|
22
|
"CountryName"
:
"中国"
,
|
23
|
"CountryNameCode"
:
"CN"
|
24
|
}
|
25
|
},
|
26
|
"ExtendedData"
: {
|
27
|
"LatLonBox"
: {
|
28
|
"north"
:
36.1237216,
|
29
|
"south"
: 36.0515859,
|
30
|
"east"
:
120.4388307,
|
31
|
"west"
: 120.3107713
|
32
|
}
|
33
|
},
|
34
|
"Point"
: {
|
35
|
"coordinates"
: [ 120.3748010,
36.0876620, 0 ]
|
36
|
}
|
37
|
} ]
|
38
|
}
|
39
|
)
|
6.google maps 图片接口
有时候我们只想展示简单的地图,不需要交互和拖动,可以通过google maps提供的静态地图API 引入动态生成的地图图片,不过需要为你的域名申请一个key。
引入图片的url格式为:
01
|
http:
//maps.google.com/maps/api/staticmap?
|
02
|
03
|
sensor=
false
|
04
|
&size=200x200
|
05
|
&maptype=roadmap
|
06
|
&key=<em>你申请到的
KEY</em>
|
07
|
&markers=color:blue|label:1|37.4447,-122.161
|
08
|
&markers=color:red|label:2|37.3385,-121.886
|
09
|
&markers=color:green|label:3|37.3716,-122.038
|
10
|
&markers=color:yellow|label:4|37.7792,-122.42
|
得到图片:
后记
关于地图的更多操作,可以参见以前的这篇文章:Google Maps Api介绍与基础操作 。
随着互联网的发展,越来越多的功能可以在前端实现,出现了越来越多的强大的第三方服务,我们可以很方便的在我们的网站上加入一些实用的功能。这也许 就是web2.0的魅力吧。