2008年12月9日星期二

使用地图API实现自定义叠加层

与地图上的控件不同,地图上的叠加层(Overlay)指的是和某个经纬度坐标绑定,能够跟随地图的缩放拖拽而相应移动的DOM原始,地图API文档里定义的GMarker、GPolyline、GInfoWindow都属于叠加层。右边地图上显示的交通信息的图标就是一个叠加层。
先看一段Hello World的代码吧:
var MyOverlay = function(latlng_) {
  this.latlng = latlng_;
};

MyOverlay.prototype.initialize = function(map_) {
  this.map = map_;
  var label_ = document.createElement("div");
  var container_ = map_.getPane(G_MAP_FLOAT_PANE);
  container_.appendChild(label_);
  label_.innerHTML = "<span style='color:#FF0000;background-color:#FFFFFF;'>Hello World!</span>";
  label_.style.position = "absolute";
  this.label = label_;
  this.redraw();
}
MyOverlay.prototype.redraw = function() {
  var position = this.map.fromLatLngToDivPixel(this.latlng);
  this.label.style.left = position.x + "px";
  this.label.style.top = position.y + "px";
}
MyOverlay.prototype.remove = function() {
  this.label.parentNode.removeChild(this.label);
}
上面的代码中,MyOverlay就是一个自定义的叠加层,需要的时候可以创建一个MyOverlay的实例,然后使用map.addOverlay()就可以在地图上加上这个叠加层了。这里的叠加层是在给定的位置(地图加载时的中心点)加上一个Hello World的文本,以后,无论你怎么拖动缩放地图,这个文本在地图上的位置会跟着地图变化。
下面详细解释一下代码:
var MyOverlay = function(latlng_) {
  this.latlng = latlng_;
};
声明MyOverlay类的构造函数,创建该类的实例是需要给一个GLatLng类型的坐标对象作为参数。

MyOverlay.prototype = new GOverlay();
声明这个类继承自GOverlay

接下来的initialize、redraw、remove都是实现了在GOverlay接口中定义的抽象方法,这些方法在MyOverlay类的对象初始化、地图拖拽缩放、从地图上删除的时候都会被自动调用。

Overlay也是一个DOM元素,所以在initialize方法中需要做的就是定义这个DOM元素并且把它添加到合适的地方去。使用GMap2对象(作为参数传递进来)的getPane方法取得Overlay需要依附的图层(这个图层按照z-index的不同现在可以分为七种不同的图层,我就不列举了,需要的可以到文档里查查GMapPane这个类),也就是Overlay所要依附的DOM容器(不同于GMap2对象的DOM容器),定义好Overlay的样式和内容,然后作为子元素添加到刚才取到的图层里就可以了。
在initialize方法中需要注意的是,作为叠加层的DOM元素的position样式属性必须设置为absolute,并且需要显式的调用redraw方法,才能保证在叠加层第一次加载时的位置显示正确。

对于redraw方法,就是在地图的位置发生变动以后能够重新计算叠加层的坐标并重新设定叠加层的显示位置,关键点就是使用GMap2.fromLatLngToDivPixel()方法来取得叠加层的DOM绝对坐标,不是很理解这个坐标的话可以看看我以前总结果的地图坐标系统

对于remove方法,地图在调用removeOverlay的时候会自动调用这个方法,把你的叠加层从地图上删除。

这里展示的只是一个添加简单文本的Overlay的例子,如果你需要添加更丰富的文本、图片,或者需要这个Overlay能够监听一些事件,比如单击、双击等等,只需要在initialize()方法里对Overlaly的DOM元素做更多的声明和控制就可以了,和你在网页中其他地方定义一个DOM元素没什么两样。

2008年12月5日星期五

定制GoogleBar --谷歌地图的本地搜索栏

在提到地图上的默认控件GMap2的设置项的时候,我都提过谷歌地图的本地搜索栏这个控件,要在地图上加上这个控件很简单,不需要调用GMap2.addControl(),只需要一句话:
  map.enableGoogleBar();
这样就可以在地图的左下角加上这个搜索栏了,并且替换掉了原来的谷歌Logo的图片。
目前用这个搜索栏可以搜索两种类型的数据:
  1、地名;
  2、谷歌提供的商业数据,比如“餐馆”,默认是在当前显示的地图范围内搜索;
具体的搜索结果是上面的哪种类型由你输入的关键字决定,没有什么特别的方法。搜索返回结果后会自动在地图上加上所有结果的标记,同时会用DOM形式显示这个搜索结果,至于DOM会是什么样的形式展现,接着看就知道了。

定制这个搜索栏对应的类是GGoogleBarOptions,没有构造函数,对应一个对象变量,使用方式类似于使用GMapOptions定制谷歌地图,不过GGoogleBarOptions是作为GMapOptions里的一项在创建GMap2对象的时候使用。如果你了解过Google AJAX Search API的话,你对下面这些设置项会很熟悉,因为,这个本地搜索栏就是对AJAX Search中的GLocalSearchControl的一个封装。
先看几个基本的设置项:
  1、 showOnLoad
  这个是boolean类型的项,决定加载完成后搜索栏的显示状态,默认是false,意思是搜索栏是闭合的,不显示输入框,如果你想提醒用户这里有个输入框可以搜索,可以把这一项设成true,即{showOnLoad:true};
  2、linkTarget
  简单的说,这个就是搜索结果里每一条记录对应link的target属性值,四个可选值,默认是等价于target="blank_"的G_GOOGLEBAR_LINK_TARGET,其他还有parent, self, top这几项,准确的参数我就不列了,开发文档里有。不过这一项基本用不着,不用设置;
  3、resultList
  用来指定搜索结果的DOM显示样式,默认是用列表的方式显示(G_GOOGLEBAR_RESULT_LIST_INLINE),还有一种是添加一对方向箭头让你逐个翻阅,就像右边的地图里显示的那样。如果你的地图空间比较小的话可以用后一种,设定{resultList:G_GOOGLEBAR_RESULT_LIST_SUPPRESS};
  4、suppressInitialResultSelection
  这个用来指定搜索完成后是否自动选中第一个搜索结果并且打开它的信息窗口,默认是false,就是打开第一条记录的信息窗口,不需要的话就指定{suppressInitialResultSelection:true};
  5、suppressZoomToBounds
  按照文档的说法,这个用来设定搜索完成后是否需要地图自动缩放移到来完整显示所有的标记点,默认是false,不缩放的,不过我在试用时发现不管搜索结果如何,地图都不会缩放。所以,暂时忽略这一项。
  6、searchFormHint
  这个在文档里没有列出来,但是也可以使用,用来设定输入框处于非激活状态时的提示语,默认的是“搜索地图”,你也可以设成你自己的提示语,比如:{searchFormHint:"hi,在这里可以直接搜索地图"}

再来看几个用来设定搜索操作时的回调函数,类似于事件监听,这几个可以做很多文章:
  1、onIdleCallback
  这个在搜索结果被清除的时候调用,也就是在你点击搜索结果上的“清除结果”这个链接后,是不是在本次搜索结果返回并且自动清除上一次搜索结果后调用我还不确定,看开发文档似乎有这个意思。
  2、onSearchCompleteCallback
  在已经得到搜索结果但是还没有添加到地图上的时候调用,会传递一个GlocalSearch对象作为参数,GlocalSearch是Google AJAX Search API里定义的一个类,想了解的先去看文档吧,我就不多说了。
  3、onGenerateMarkerHtmlCallback
  在打开一条搜索记录的信息窗口前会被调用,传入marker, html, result三个参数,分别对应这条记录在地图上的标记(GMarker)、填充信息窗口的html字符串、对应的搜索结果(GlocalResult)。这里定义的回调方法必须返回一个dom对象,用在打开的信息窗口中。所以,通过这一项的设置,你就可以更改搜索结果的信息窗口里的默认内容了。右边的地图里就把默认的信息窗口内容换了,去掉了“从这里来”、“到这里去”的链接,加上了一个静态地图,
  4、onMarkersSetCallback
  这个在所有的结果标记都已经创建但还没有添加到地图之前调用,传入的参数是一个搜索结果的数组results,数组里的每一项对应一条搜索记录,包括latLng, marker, result,对应结果的坐标GLatLng、标记GMarker、结果记录GlocalResult。这个时候结果的显示列表已经创建完成了,所以,如果你想修改这个现实结果不妨试试这个设置项。
  
追加一些说明,上面说到的GlocalResult也是在Google AJAX Search API里定义的一个类,没有构造函数,当作对象变量使用,需要了解可以看看文档,这里列一下这个类的一些主要属性:
.title, .titleNoFormatting, .lat, .lng, .streetAddress, .city, .country, .phoneNumbers[], .staticMapUrl