推推99地图找房 的jquery实现,开发中主要参考了推推99的地图找房,推推99使用了prototype.js 库,下面使用的是jquery库,其版本为jquery-1.3.2.js ,还有保存哈希对象的hash.js 类,主要根据自己开发过程中遇到的问题及解决方法去描述
一、Google地图编程基础
简单描述下Google Map编程中用到的术语,如覆盖对象,地图分层等,以便后面现实中用到术语的统一及理解,已了解可跳过,查看下节的实现步骤,更加详细请参考Google地图API文挡 。
1、google地图编程
使用方法 GEvent.addListener或 GEvent.bind” 监听”事件。
2)信息窗口
信息窗口包含内容区域和锥形箭头,锥形箭头指向地图上的指定点。
3)覆盖对象
覆盖在地图上有固定经纬度坐标位置的对象,当拖动地图或改变地图类型时,会跟着移动。
Maps API支持两种类型的覆盖对象:标记(GMarker),图标(GIcon)。折线(GPolyline)是用一系列点形成的折线 。
4)控件
缩放工具条、选择地图类型等空间,使用addControl方法向地图增加控件。
2、google地图分层
二、地图找房实现及步骤
实现思路:
根据物件刊登地址(县市,乡镇,巷、弄、号)抓取Google Map经纬度,在地图G_MAP_MAP_PANE层上添加自定义叠加层,根据条件面板条件显示物件集合及数目,叠加层使用javascript监听鼠标移上、移开、点击等事件,并作出对应的外观改变、弹窗显示物件等响应。
实现步骤:
2.1、根据经纬度定位并显示物件集合
函数GMap2.fromLatLngToDivPixel(latlng:GLatLng),计算指定地理位置在含有可拖动地图的DOM元素中的像素坐标。如,“深圳图书馆”的经纬度P(22.547083441500213,114.05717031860352),初始地图DOM的ID为“map_canvas”,如下可得“深圳图书馆”在“map_canvas”的像素坐标:
map = new GMap2(document.getElementById("map_canvas"));//初始地图
var point = new GLatLng(22.547083441500213,114.05717031860352);//经纬度
var L = map.fromLatLngToDivPixel(point);//集合定位
var div = document.createElement("div");
div.innerHTML = "深圳图书馆
";
div.style.left = Math.min(L.x, L.x) + "px";
div.style.top = Math.min(L.y, L.y) + "px";
map.getPane(G_MAP_MAP_PANE).appendChild(div);//添加到地图
2.2、移动缩放地图重新定位物件集合
查看例子会发现,地图缩放后再移动时,自定义叠加层、地图marker、实际地址就不再三点合一,出现位置偏移。解决这个问题,使用一个小技巧,缩放移动地图后,结束地图视图的更改时会触发moveend()事件。因此,监控事件,当moveend()时,删除前次所有自定义的叠加层,然后重新计算DOM元素中的像素坐标,显示控件,即moveend()后:
1)移除地图前次所有自定义的叠加层。
2)根据经纬度重新计算DOM元素中的像素坐标,显示控件 。
2.3、移动缩放地图保留区域集合,删除视野外集合,加载增加视野区域集合
1)、如何确定地图的显示区域范围?
2)、移动地图后,如何获取前次显示范围对应的物件集合,从而保留原来的保持不变,只增加新区域物件集合?
问题1:确定地图显示区域
函数GMap2.fromDivPixelToLatLng(pixel:GPoint),根据含有可拖动地图的div中的像素坐标计算地理坐标。如下图,地图显示区域定义两点,假设左下角点像素坐标P1(x,y),根据地图容器宽度及高度,可计算到右上角点为P2(x+$("#map_canvas").width(), y+$("#map_canvas").height()),最后,可通过GMap2.fromDivPixelToLatLng(pixel:GPoint)计算出显示区域的地理坐标,即经纬度范围,如,经度从slngFrom到slngTo,维度从slatFrom到slatTo(实际中我们会减去地图类型、地图缩放等控件的区域)。
实际使用代码:
function getBounds()
{
var E = 80;
var G = map.fromContainerPixelToLatLng(new GPoint(E, E / 2));
var D = map.fromContainerPixelToLatLng(new GPoint($("#map_canvas").width() - E / 2,
$("#map_canvas").height() - E / 2));
var B = D.lat().toFixed(3);
var A = G.lat().toFixed(3);
var F = G.lng().toFixed(3);
var C = D.lng().toFixed(3);
this.bounds = {
slatFrom: B,
slatTo: A,
slngFrom: F,
slngTo: C
}
}
结合前面,监听地图的事件,当触发moveend()时,只要执行上面的函数,即可以得到地图当前显示区域的经纬度范围。ajax请求服务器,获取对应范围的物件集合,其中SQL类似“WHERE lat>=slatFrom AND lat<=slatTo AND lng>=slngFrom AND lng<=slngTo”。
问题2:保留前次物件集合数据
每个物件集合对应一组唯一的经纬度,数据库设计可为每组经纬度对应一个唯一的自动增加的编号ID,每次ajax获取到的数据都保存在以ID为键,经纬度、名称等组成的数组为值的哈希序列中,使用网上哈希对象类 保存前次数据,具体用法可以参考里面的说明,下面简单的看下使用到的部分:
/*
* json格式:
* {collectId:["name",'count',"lat","lng","fullname","postId'","casesId"]}
* 实际数据:
* {1001:["梅林一村",'20',"22.5653936421316","114.038043022156","梅林一村","",""],
1002:["彩天名苑",'8',"22.5379670676697","114.068727493286","彩天名苑","","98550"]}
*/
var m = this.mapMarkers; //前次保存的哈希对象
var H = new hash();
$.each(json,function( collectId, data ) {
H.put( collectId, data ); //保存哈希对象
});
...
if ( L==0 ) {
} else {
//前次物件集合
m.forEach( function( data, collectId ) {
//不在当前区域或集合数目不同
if ( !H.contains(collectId) || H.get(collectId)[1]!=data[1] ) {
...
m.remove(collectId); //移除哈希对象
$("#"+collectId).remove(); //移除地图叠加层
} else {
...
$("#"+collectId).remove(); //移除地图叠加层
drawMarker( marker, L.y, L.x, point ); //重显示地图叠加层
}
});
}
//当前JSON处理
var timer = 0;
$.each( json,function( collectId, data ) {
//当前区域新增
if ( !m.contains(collectId) ) {
window.setTimeout( function() {
...
m.put(collectId, data); //移除地图叠加层
drawMarker(marker, L.y, L.x, point); //显示地图叠加层
},timer++*30);
}
});
注意示例中,地图初始显示5个物件集合点,拖动后假设请求的数据为:移除 最左边66间的“东方时代广场”,保留 另外4个物件,其中改变 最右下64间的“美园MAY HOUSE”为164间,新增 最右上两个新的集合(173间和135间的两个物件集合)。
2.4、jquey自定义事件绑定及触发
因工作需要,页面显示和地图显示、API交互等分开两人开发,页面点击调用地图显示部分代码。如用户点击县市,显示乡镇,定位地图中心点,使用jquery自定义事件,监听“map:center”事件,点击县市时触发事件,并传递县市经纬度、缩放级别等参数,如下代码所示:
事件监听:
$(document).bind(“map:center”,function(event, E) {
map.setCenter(new GLatLng(E.lat, E.lng), E.zoom);
});
事件触发:
$("#region").bind(“click”,function(event) {
initSection(rid);//初始乡镇
//触发
$(document).trigger(“map:center”,
{
lat:G,lng:B,zoom:this.zoom
});
});
2.5、sphinx使用setGroupBy函数根据条件筛选物件,统计并排序集合物件数目
地图放大级别很小时,如地图包括整个深圳市,此时若把地图对应区域(整个深圳市)物件集合显示出来,数据是非常大的,因此,我们可能要求,地图放大到某级别时候,覆盖范围大,而只要显示对应物件集合最多的前100个集合。一般做法:
1)、根据选择条件、区域筛选物件集合,然后GROUP BY集合ID。
2)、根据步骤1)统计集合物件数目。
3)、根据步骤2)排序,输出前100个记录。
在sphinx中只要进行以下操作:
//显示的数目
$conf['limit'] = 100;
$sp->SetLimits(0, $conf['limit'], $this->_maxmatches);
//SetGroupBy
$sp->SetGroupBy('collect_id', SPH_GROUPBY_ATTR, '@count desc');
$result = $sp->Query($this->Spx_q, $sp_index);
$_collect_count = $result['matches'][view_id]['attrs']['@count'];//物件数目
以上就返回根据字段collect_id作GROUP BY后,以物件集合总数倒序的100条记录,其中物件数目保存在@count属性。
阅读(1336) | 评论(0) | 转发(0) |