在Google Maps API的使用中,经常用到Clusterer来避免过密的Marker显示。但仔细看一下Clusterer的设置参数中并没有直接将某些Marker除外的方法,那遇到这样的需求,怎么做呢?以下是我从StackoverFlow上获得的解答,也是实践下来最佳的方法:

// Create marker clusterer
// map: google.maps.Map Object
// markerArray: [google.maps.Marker Object1, google.maps.Marker Object2 ...]
var clusterer = new MarkerClusterer(map, markerArray, {
maxZoom: 15,
gridSize: 40
});
// Separate the map pin from the cluster
// specialMarker: google.maps.Marker Object
clusterer.removeMarker(specialMarker);
specialMarker.setMap(map);

思路很简单,就是用Clusterer对象提供的方法将Marker从中移除,然后用Marker对象的setMap方法使其回到map上。

然后你就会发现另外有一个问题出现了。这个被分离出来的Marker总是在Clusterer的下面一层。客户很不爽。看到有人说要靠建立自定义的OverlayView来把Marker画在Clusterer的上面一层,不过也没看到有具体的解决办法,于是我硬着头皮上了。对谷歌文档半熟的人来说,看到他们列出来的一堆东西很头疼,往往不知道怎么下手。

首先要知道Google Map上总共分了7个层,具体可以参考API文档OverlayView及Panes的部分,说明还是很详细的。

我们可以知道直接用Marker对象画出来的Map pin是在OverlayLayer这一层内,好像是第3层,而Cluster位于其上的OverlayImage这一层内。各层HTML按序从上到下排列,CSS是用position:absolute定位,zIndex定先后层级。

那么从这可以看出,其实如果只要显示Marker在Clusterer上方通过改变zIndex是很容易做到的。问题是,这么做因为原来的层级被搞乱导致一些事件,比如Clusterer的点击事件不能触发。

然后我用了个假的Marker画在比较高层的Pane上以假乱真。如下:

var maxZoom = 15;
var markerClusterer = new MarkerClusterer(map, markerArray, {
maxZoom: maxZoom,
gridSize: 40
});
// separate the map pin from the cluster
if (specialMarker) {
markerClusterer.removeMarker(this.centerMarker);
//specialMarker.setMap(this.map);
// Make the map pins over the clusters
if ($(map.getDiv()).find('.special-marker').length < 1) {
// Create the OverlayView structor
var overlay = function (marker) {
this.pos = marker ? marker.getPosition() : new google.maps.LatLng();
this.marker = marker;
};
var markerOverlay;
// Extend google.maps.OverlayView Class
// You must add onAdd, onRemove, Draw function to its prototype
overlay.prototype = new google.maps.OverlayView();
overlay.prototype.onAdd = function () {
var pane = this.getPanes().floatPane;
var marker = this.marker;
// Add fake marker and attach click event to it
$('<div class="special-marker"></div>').appendTo($(pane)).on('click', function () {
google.maps.event.trigger(marker, 'click');
});
};
overlay.prototype.onRemove = function () {
// You can leave this function empty
// It's only triggered when you call markerOverlay.setMap(null)
};
overlay.prototype.draw = function () {
// Calculate the position of the marker and put it on the map
// Hide the fake one when the true marker shows
var projection = this.getProjection();
var position = projection.fromLatLngToDivPixel(this.pos);
var $pane = $(this.getPanes().floatPane);
$('.special-marker', $pane).css({
left: position.x - 11,
top: position.y - 41,
position: "absolute"
}).toggle(map.getZoom() <= maxZoom);
};
markerOverlay = new overlay(specialMarker);
markerOverlay.setMap(map);
}
}

这里我先创建了一个自定义层,插入到第7层Pane的floatPane内最后。然后我用了个跟真Marker一模一样的图标作为这个层的背景,尺寸22px*41px,根据真Marker的位置计算出来在Map上的位置,用CSS绝对定位到指定位置。并且,很重要的是,把真Marker上的click事件绑定到这个假Marker上,因为点击Marker会显示InfoWindow。最后,为了避免真假Marker同时显示在Map上,加了一层判断。

实际上,以假乱真可以说是多余的,你可以直接画自己的Marker,作为真Marker来用,当然这也有一定的风险。

[Google Maps API 3]Marker从Clusterer中分离及Marker置于Cluster上一层的解决办法的更多相关文章

  1. Google Maps API V3 之绘图库 信息窗口

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  2. Google Maps API V3 之 图层

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  3. Google Maps API V3 之 路线服务

    Google官方教程: Google 地图 API V3 使用入门 Google 地图 API V3 针对移动设备进行开发 Google 地图 API V3 之事件 Google 地图 API V3 ...

  4. Google maps API开发(一)(转)

    一.加载Google maps API <script type="text/javascript" src="http://ditu.google.com/map ...

  5. Google maps API开发(二)(转)

    这一篇主要实现怎么调用Google maps API中的地址解析核心类GClientGeocoder: 主要功能包括地址解析.反向解析.本地搜索.周边搜索等, 我这里主要有两个实例: 实例一.当你搜索 ...

  6. Google maps API开发

    原文:Google maps API开发 Google maps API开发(一) 最近做一个小东西用到google map,突击了一下,收获不小,把自己学习的一些小例子记录下来吧 一.加载Googl ...

  7. google maps api申请的问题

    现在已经改由统一的GOOGLE API控制台进行所有GOOGLE API的管理了. 方法是使用Google帐号登入 https://code.google.com/apis/console. 然后在所 ...

  8. Google Maps API Web Services

    原文:Google Maps API Web Services 摘自:https://developers.google.com/maps/documentation/webservices/ Goo ...

  9. Google Maps API Key申请办法(最新)

    之前的Google Maps Api的API Key很容易申请,只需要按照一个简单的表单提交部署的网站地址即可,自动生成API Key并给出引用的路径. 但是最近在处理另外一个项目的时候发现之前的这种 ...

随机推荐

  1. 在线电路编程 (ICP)

    通过在线电路编程(ICP)编程Flash.如果产品在开发中,或在终端客户的产品需要固件升级,采用硬件编程模式非常困难且不方便.采用ICP方式将很简单,且不需要将微控制器从板上拆下来.ICP方式同样允许 ...

  2. 在javaweb的项目当中实现随机数字的生成

    首先,需要在javaweb的项目当中新建一个Servlet文件,然后再web.xml中配置一下: 这样运行的时候就可以通过“http://localhost:8080/Response/Respons ...

  3. php安装xdebug后var_dump输出没有格式化的问题

    开发环境,装了一个xdebug扩展方便调试代码. 但是环境配置好了之后却发现xdebug加载成功了但是var_dump输出的内容却没有使用html格式化 这时想到估计是php.ini里面的某个输出的配 ...

  4. 【.netcore学习】.netcore添加到 supervisor 守护进程自启动报错

    配置 supervisor [program:HelloWebApp] command=dotnet run directory=/home/python/dotnet/myweb/mywebapi ...

  5. 【读书笔记-数据挖掘概念与技术】数据仓库与联机分析处理(OLAP)

    之前看了认识数据以及数据的预处理,那么,处理之后的数据放在哪儿呢?就放在一个叫“数据仓库”的地方. 数据仓库的基本概念: 数据仓库的定义——面向主题的.集成的.时变的.非易失的 操作数据库系统VS数据 ...

  6. c++ 纯虚析构函数

    ; 这就是一个纯虚析构函数,这种定义是允许的. 一般纯虚函数都不允许有实体,但是因为析构一个类的过程中会把所有的父类全析构了,所以每个类必有一个析构函数. 所以.纯虚析构函数需要提供函数的实现,而一般 ...

  7. 如何使用Countifs函数动态统计

    我们以前就是一个函数一个功能,一个函数一个区域,这次我们使用动态函数.我们先写好条件范围,因为我们要引用.   同样的我们写下函数出来,我们先把Countifs写出来.选择完区域之后如下图.   条件 ...

  8. ELK系列二:Elasticsearch的架构原理和配置优化

    1.Elasticsearch的数据组织架构 1.1.Elasticsearch结构概念 集群(cluster):拥有相同cluster-name的elasticsearch结点的集合(每个结点其实就 ...

  9. 查看UUID的方法

    # blkid /dev/sdc1: UUID="6dfada2a-3a79-46b9-8e5d-7e8b39eba0da" TYPE="ext4" /dev/ ...

  10. linux下模拟CPU占用100%小程序

    在做一个测试时,需要模拟服务器CPU占用满的情况,在查阅相关资料后,发现网上程序不太好用, 原文在这:http://www.2cto.com/os/201304/202068.html 优化后如下: ...