可以在前端实现的几个地理位置小功能

在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

另外,腾讯也有一个类似的接口,地址为 http://fw.qq.com/ipaddress,可以得到访问者的省、市信息,返回的格式如下:

var IPData = new Array("123.235.153.126","","山东省","青岛市");

具体的应用可以看这里: 断桥残雪WordPress天气插件

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. Google Gears 的 Geolocation API

Google Gears是主要提供本地存储功能的浏览器扩展,新版本的Gears中,加入了判断用户地理位置的API,通过IP、WIFI热点等判断位置。不过Gears的使用似乎并不太广泛(Chrome内置了Gears,其他浏览器需要安装),国内的地理位置信息也不够丰富,所以这个应用目前只可作为参考。

使用Gears的基本方法看这里,引入gears_init.js,使用Geolocation API的程序为:

var geo = factory.create('beta.geolocation'); //创建geolocation对象
var okCallback = function(d){
  alert('当前位置(纬度,经度): ' + d.latitude + ',' + d.longitude);
};
var errorCallback = function(err){
  alert(err.message);
};
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为回调函数名。

可以看下这个地址的返回结果,数据非常丰富,并且还是中文的:

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>

使用YQL进行更多地理信息查询,可以看这个PPT:YQL Geo Library and Introduction to Geo Hacking talk

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回调函数名。

举个例子,返回结果:

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 ]
    }
  } ]
}
 )

6.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

得到图片:

null

后记

关于地图的更多操作,可以参见以前的这篇文章:Google Maps Api介绍与基础操作

随着互联网的发展,越来越多的功能可以在前端实现,出现了越来越多的强大的第三方服务,我们可以很方便的在我们的网站上加入一些实用的功能。这也许就是web2.0的魅力吧。

10 个评论:

  1. Posted 2010年03月11日 at 6:33 下午 | Permalink

    正在学习Google Maps API,不错的文章,参考下

  2. Posted 2010年03月15日 at 9:00 上午 | Permalink

    还有qq有个IP接口,我做的wp天气插件就是用它:”http://fw.qq.com/ipaddress” 不过是GBK格式,要转换下

  3. Posted 2010年03月19日 at 5:32 下午 | Permalink

    我的网站也写了一些关于Google Maps API的文章。欢迎交流~ 我很喜欢你的博客,想和你交换个链接~以后会常常来访问你的博客~

  4. j5726
    Posted 2010年03月20日 at 3:36 下午 | Permalink

    @简明现代魔法 链接已添加,多多交流~

  5. Posted 2010年03月21日 at 11:22 上午 | Permalink

    博主,你那个feed里输出无格式的问题是怎么解决的啊?

  6. Posted 2010年03月22日 at 11:08 上午 | Permalink

    在幸福收藏夹上看到你的连接 就过来了,发现在普加的人还不少哇。

  7. j5726
    Posted 2010年03月23日 at 7:30 下午 | Permalink

    好像是打开了“全文输出”,然后修改了feed-rss2.php文件,具体的你goo一下,我也忘了。。

  8. Posted 2010年03月24日 at 3:41 下午 | Permalink

    很不错!! 转载!

  9. Posted 2010年03月26日 at 8:29 下午 | Permalink

    不错,喜欢

  10. Posted 2010年07月24日 at 5:12 下午 | Permalink

    学习了

发表评论

*
*

文明评论,共同进步