将多个圈添加到谷歌地图

时间:2011-07-20 20:57:58

标签: google-maps google-maps-api-3 kml geometry

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

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

查看Google KML常见问题解答页面上的圈子workaround,我不确定生成包含数千个类似于此的圈子的KML文件是否会随时节省。

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

最后,考虑到我正在拉动我试图从数据库中绘制的圆圈,因此我必须动态生成KML文件以供使用或每次生成一个新文件从数据库中删除或添加,以使文件保持最新。

当然,如果有另一种选择,我全都是耳朵!

3 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:3)

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

示例

该示例演示了如何渲染 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);
&#13;
html, body, #map-canvas {
   height: 100%;
   margin: 0px;
   padding: 0px;
} 
&#13;
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<div id="map-canvas"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

忘了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事件处理程序附加到地图本身,它通过单击的lat / lon向服务器发送AJAX调用。然后,服务器端脚本在数据库中查找此lat / lon,以确定单击了哪个县。