Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding many circles to a google map

I'm attempting to draw many circles (around 1000) on a google map, at various locations and sizes, and then binding a click event to them. But this many calls of new google.maps.Circle(parameters); makes the page loading slow, and sometimes it just hangs forever, so I'd like to figure out if there's a better/faster way to accomplish what I'm trying to do.

I see that there's something called a kml layer, but there doesn't appear to be any easy way to draw filled circles with it and I'm not sure if I can still bind click events to each individual circle in the layer or not.

Looking at the circle workaround on the google KML faq page, I'm not sure if generating a KML file that contains thousands of circles similar to this would end up saving any time.

I also have no idea how to go about generating this kml file.

Finally, take into consideration that I'm pulling the circles I'm attempting to draw from a database, so I'd either have to generate the KML file on the fly for use or generate a new file every time a circle is removed or added from the DB so that the file stays up to date.

Of course, if there's another alternative, I'm all ears!

like image 943
EvilAmarant7x Avatar asked Jul 20 '11 20:07

EvilAmarant7x


People also ask

How do I draw multiple circles on Google Maps?

Click anywhere on the map to create a circle. You may continue clicking outside the circles to create more circles. You can reposition (drag) the circles with your mouse by clicking+holding+moving.

How do you get 100 mile radius on Google Maps?

Click on the map and create a popup marker to select the point. From there, opt for the “Draw Radius.” Choose the proximity distance from the given address found within the radius options in the software.

Can you add more than 10 layers on Google Maps?

Maps are created with one layer, but you can have up to 10. On your computer, sign in to My Maps. Open or create a map.

How do you make concentric circles on Google Maps?

To add your concentric circles, create your radius map, and click on the menu item Highlight Regions -> Circles. This should give you a dialog to specify your circles center, and enter multiple radiuses (separated by commas or spaces) for the circle in miles.


2 Answers

With the help of others via the Google Maps API v3 Group, I was able to implement a map overlay that handles 10,000 points suprisingly well. The trick is to use a canvas tile overlay, which minimizes the number of DOM elements in exchange for much simpler/lighter-weight POJsOs (plain old JavaScript objects).

Demo page w/mouse click events (API v2 only): http://notebook.kulchenko.com/maps/datamark
Demo page w/cursor swapping (API v2 and v3): http://notebook.kulchenko.com/maps/gridmark

like image 105
Matt Ball Avatar answered Oct 18 '22 21:10

Matt Ball


Here is yet another example that demonstrates how to render multiple objects on Google Map using Overlay approach. Since the performance could degrade considerably while the amount of objects (e.g. google.maps.Circle) is increasing, it is proposed to render objects using canvas element instead of divone.

Example

The example demonstrates how to render 1k objects (cities)

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>
like image 26
Vadim Gremyachev Avatar answered Oct 18 '22 21:10

Vadim Gremyachev