向谷歌地图添加许多圈子

Posted

技术标签:

【中文标题】向谷歌地图添加许多圈子【英文标题】:Adding many circles to a google map 【发布时间】:2011-10-09 18:07:21 【问题描述】:

我试图在谷歌地图上以不同的位置和大小绘制许多圆圈(大约 1000 个),然后将点击事件绑定到它们。但是new google.maps.Circle(parameters); 的这么多调用使页面加载缓慢,有时它会永远挂起,所以我想知道是否有更好/更快的方法来完成我正在尝试做的事情。

我看到有一个叫做 kml 层的东西,但似乎没有任何简单的方法可以用它绘制实心圆圈,我不确定是否仍然可以将点击事件绑定到层中的每个单独的圆圈与否。

查看 google KML 常见问题页面上的圆圈 workaround,我不确定生成包含数千个类似这样的圆圈的 KML 文件是否最终会节省任何时间。

我也不知道如何生成这个 kml 文件。

最后,考虑到我正在从数据库中提取我试图绘制的圆圈,所以我要么必须即时生成 KML 文件以供使用,要么每次生成一个新文件从数据库中删除或添加,以便文件保持最新。

当然,如果还有其他选择,我会全力以赴!

【问题讨论】:

您是否希望从本质上构建热图?如果是这样,只需谷歌“谷歌地图热图”,那里有几个不同的图书馆...... 虽然这在未来可能会有用;我不是想绘制热图。只是一堆圆圈,指定地图上的各个区域。 【参考方案1】:

在其他人通过Google Maps API v3 Group 的帮助下,我能够实现一个能够处理 10,000 个点的地图叠加层,出奇地好。诀窍是使用画布平铺覆盖,最大限度地减少 DOM 元素的数量,以换取更简单/更轻量级的 POJsO(普通的旧 javascript 对象)。

带有鼠标点击事件的演示页面(仅限 API v2):http://notebook.kulchenko.com/maps/datamark 带光标交换的演示页面(API v2 和 v3):http://notebook.kulchenko.com/maps/gridmark

【讨论】:

这对我也有帮助!现在我有数千个画布标记,而不是数千个 svg 标记。男孩它飞!现在我只需要弄清楚如何对多边形做同样的事情,因为这是另一件会破坏我的地图性能的事情。 :(【参考方案2】:

这是另一个示例,演示如何使用Overlay approach 在 Google 地图上呈现多个对象。由于随着对象数量(例如google.maps.Circle)的增加,性能可能会显着下降,因此建议使用canvas 元素而不是divone 来渲染对象。

示例

该示例演示了如何渲染 1k 个对象(城市)

var overlay;
USCitiesOverlay.prototype = new google.maps.OverlayView();

function USCitiesOverlay(map) 
    this._map = map;
    this._cities = [];
    this._radius = 6;
    this._container = document.createElement("div");
    this._container.id = "citieslayer";
    this.setMap(map);
    this.addCity = function (lat, lng,population) 
        this._cities.push(position: new google.maps.LatLng(lat,lng),population: population);
    ;



USCitiesOverlay.prototype.createCityIcon = function (id,pos,population) 
    
    var cityIcon = document.createElement('canvas');
    cityIcon.id = 'cityicon_' + id;
    //calculate radius based on poulation 
    this._radius = population / 100000;
    cityIcon.width = cityIcon.height =  this._radius * 2;
    cityIcon.style.width = cityIcon.width + 'px';
    cityIcon.style.height = cityIcon.height + 'px';
    cityIcon.style.left = (pos.x - this._radius) + 'px';  
    cityIcon.style.top = (pos.y - this._radius) + 'px'; 
    cityIcon.style.position = "absolute";

    var centerX = cityIcon.width / 2;
    var centerY = cityIcon.height / 2;
    var ctx = cityIcon.getContext('2d');
    ctx.fillStyle = 'rgba(160,16,0,0.6)';
    ctx.beginPath();
    ctx.arc(centerX, centerY, this._radius, 0, Math.PI * 2, true);
    ctx.fill();

    return cityIcon;
;    


USCitiesOverlay.prototype.ensureCityIcon = function (id,pos,population) 
    var cityIcon = document.getElementById("cityicon_" + id);
    if(cityIcon)
        cityIcon.style.left = (pos.x - this._radius) + 'px';
        cityIcon.style.top = (pos.y - this._radius) + 'px';
        return cityIcon;
    
    return this.createCityIcon(id,pos,population);
;    



USCitiesOverlay.prototype.onAdd = function () 
    var panes = this.getPanes();
    panes.overlayLayer.appendChild(this._container);
;



USCitiesOverlay.prototype.draw = function () 
    var zoom = this._map.getZoom();
    var overlayProjection = this.getProjection();

    var container = this._container;
    
    this._cities.forEach(function(city,idx)
        var xy = overlayProjection.fromLatLngToDivPixel(city.position);
        var cityIcon = overlay.ensureCityIcon(idx,xy,city.population);
        container.appendChild(cityIcon);    
    );
   
;

USCitiesOverlay.prototype.onRemove = function () 
    this._container.parentNode.removeChild(this._container);
    this._container = null;
;











function getRandomInterval(min, max) 
    return Math.random() * (max - min) + min;



function generateCityMap(count) 
    var citymap = [];

    var minPos = new google.maps.LatLng(49.25, -123.1);
    var maxPos = new google.maps.LatLng(34.052234, -74.005973);
    

    for(var i = 0; i < count;i++)
    
       var lat = getRandomInterval(minPos.lat(),maxPos.lat());
       var lng = getRandomInterval(minPos.lng(),maxPos.lng());
       var population = getRandomInterval(100000,1000000);


       citymap.push(
          location: new google.maps.LatLng(lat, lng),
          population: population
       );

    

    return citymap;





function initialize() 
    var mapOptions = 
        zoom: 4,
        center: new google.maps.LatLng(37.09024, -95.712891),
        mapTypeId: google.maps.MapTypeId.TERRAIN
    ;

    var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

    overlay = new USCitiesOverlay(map);
    //overlay.addCity(40.714352, -74.005973);   //chicago
    //overlay.addCity(40.714352, -74.005973);   //newyork
    //overlay.addCity(34.052234, -118.243684);   //losangeles
    //overlay.addCity(49.25, -123.1);   //vancouver

    var citymap = generateCityMap(1000);
    citymap.forEach(function(city)
          overlay.addCity(city.location.lat(), city.location.lng(),city.population);   
    );    




google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas 
   height: 100%;
   margin: 0px;
   padding: 0px;
 
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<div id="map-canvas"></div>

【讨论】:

【参考方案3】:

忘记 KML,自定义图块才是正确的选择。

看看这些县地图: http://maps.forum.nu/v3/gm_customTiles.html(选中“密度”框)。 和 http://maps.forum.nu/gm_main.html?lat=31.428663&lon=-110.830078&z=4&mType=10 (点击地图获取县城信息)

这些地图有 3000 多个多边形(不是圆形),而且加载速度很快。第一个链接是 API V3,第二个是 API V2。 第二张地图(V2)有点击事件。 click 事件处理程序附加到地图本身,它使用单击的纬度/经度向服务器发送 AJAX 调用。然后,服务器端脚本在数据库中查找该纬度/经度以确定点击了哪个县。

【讨论】:

我认为这些链接已经失效,很遗憾。 :(

以上是关于向谷歌地图添加许多圈子的主要内容,如果未能解决你的问题,请参考以下文章

如何在谷歌地图中设置缩放级别

如何在不使用 kml 的情况下向 android studio 中的谷歌地图应用程序添加大量多边形

谷歌地图捕捉到不返回所有值的道路

多个谷歌地图圈的信息窗口

在谷歌地图结果中添加“搜索区域”轮廓

谷歌地图视图缩小以跨越一个圆圈