上周四下午老大让我加一个map的应用到网站里,需求也没怎么说,大概的样子让我参照大众点评网的来做。
先看看大众点评网关于map应用的这部分:
看起来比较简单的一个东西,因为之前有业余做过地图应用,打开大众的代码扫了一眼,没看太明白……还是得自己写一个。注意下面的4个功能,停车属于他们自己的一个应用,这里只是一个跳转,所以没有实现。其他的3个,查看全图,修改标注,路线查询,我后面均实现鸟。
要想做这货,先说一下我自己的背景,印象里地图应用,都是需要依靠准确的经纬度来定位marker和map的位置的,之前做过的一个chrome扩展,是用的ipcn和qq转换的ip=>经纬度,这里看起来,不能用ip什么的了,html5里的location也不行,毕竟不是定位用户位置,而是具体指定位置。
最一开始,我想到的思路是找位置转换经纬度的api,找到了。搜了一下,是这个地址:
‘http://ditu.google.cn/maps/geo?q=’+encodeURI(_cg.q)+
‘&output=json&callback=GM.widget.map.callback’+this.digit+’&oe=utf8&sensor=false&key=’+_cg.key;
我直接从历史代码里抄来了,大概看的出来,通过传入q关键字,key还有指定的callback,实现经纬度的获取,通过这个借口,可以获得关键字的一个相关jsonp格式的js。
第一个版本的代码,就是按照这个思路来做的,已经完成了90%的时候,老大告诉我,q给不了你那么全……。或者说有,但是为了防止竞争对手网站抄你得数据,不能放在源码里给我。
那么好吧。沟通了一下,写了个爬虫,对这个接口进行一次抓取,把数据库的地址批量导入再储存,获得了一批场馆的经纬度,但是问题还有,依然有一批场馆,google这个接口没有经纬度的返回,那么怎么办。
嗯,我想到的和大众点评网的那个修订标注是一个功能,模糊定位到场馆所在的区,然后让编辑或者场馆主自己修订保存具体的位置,再update到数据库,这样就ok了。
那么又改了一版代码,依旧是依赖这个接口,最后实现了,发布出去以后突然发现……
所有有经纬度的正常显示,但是没有的,这个接口返回610.
http://code.google.com/intl/zh-CN/apis/maps/documentation/geocoding/v2/#StatusCodes
从这里能看到610的意思是key不对,又找了半天,发现v2版本的google map本地是不用key的……但是上线之后我发现我引用绘制地图的api是v3的……到最后问题确定了……所有的 v2通过这个接口得到的东西,必须要用v2的maps.js来绘制,否则就认为你是非法的,那么我的实现是用v3的接口写的……彻底悲剧了。
下午又对代码进行修改,最后放弃了上面这个本地ok的破接口。找了一下v3的服务接口,发现google内置了逆转经纬度的方法:
http://code.google.com/intl/zh-CN/apis/maps/documentation/javascript/services.html#ReverseGeocoding
具体的例子看这个吧。最关键的代码是这一部分:
//不给坐标的情况下,给关键字q,自己搜索绘制
if(!that.center){
//没有坐标的时候,用内置反查询搜索q的位置,如果q还没有搜到,则不显示
if(google){
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': that.q}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var location=results[0].geometry.location;
that.center=[location['Oa'],location['Na']];
drawmap(target,that.center,that.name,that.siteNo);
} else {
error(target);
}
});
}
}else if(that.center){
//给了坐标,直接根据坐标绘制地图,name为场馆名字
drawmap(target,that.center,that.name,that.siteNo);
}
之后内部的drawmap函数就是一个初始化地图的功能了,并且绘制了下面bar部分。
bar部分我这边实现了3个,查看大图,利用自己的ovaerlay浮出一个层,再初始化一个map,就实现了。
然后查询路线,直接一个表单提交到google map,自己查去吧。。
最后是修订,修订功能也不复杂,利用marker的一个dragend时间,进行ajax保存即可:
if(that.drag){
google.maps.event.addListener(marker,'dragend', function () {
var center=marker.getPosition();
if(confirm('指定这里为新的场馆坐标么?')){
GM.tools.overlay.close();
$.ajax({
url:'xxx.jsp',
data:{
siteNo:siteNo,
lat:center['Na'],
lng:center['Oa']
},
success:function(){
alert('本次修改已经提交');
},
error:function(){
alert('服务响应超时,请重试');
},
timeout:5000
});
}
});
}
屎一样的代码我就不多贴了,大概就是这么个意思,全部的代码可以参见下面:
https://github.com/xiaojue/goodmedia/blob/master/src/widget/map/map.js
再然后就没有了,主要是想说,最开始思路的确没问题,恶心的是半年没看过map api了,发现改的太多,还没专下心来读,造成刚才悲剧了。特别记录一下,也分享给需要用到的兄弟们。估计这个功能很多网站都会用到的了,虽然google对map还是有访问限制,但是中小型应用还是不错选择。
最后我实现的截图:
嗯,具体应用地址先不上了= =|| 网站还没对外公测……还很简陋。。
Read More


Comments