Based on a Google group forum post and this GIS post, I came up with a simple yet complete solution along the same lines.
First, define a function to get the radius in meters for a given zoom level: Because there are scaling differences for different latitudes, you need to feed in someLatValue
, for example the center of the map your plan on using. Although an approximation, it will be good enough for accurate results up to the size of a small country. You also need to specify the size of the radius you want in meters.
You could change the function to read these values in as parameters if you prefer (e.g., getting the lat of the center of the current map view and/or a radius based on property of the data), but if they are static, this making them globals is easier.
var someLatValue = 35.726332;
var desiredRadiusInMeters = 1500;
function getHeatmapRadius(){
metersPerPx = 156543.03392 * Math.cos(someLatValue * Math.PI / 180) / Math.pow(2,theMap.getZoom());
return desiredRadiusInMeters / metersPerPx;
};
This returns the (approximate) radius in pixels for a desired number of meters and zoom level around a particular latitude. The value 156543.03392
is based on the approximate radius of the Earth that google actually uses for Google Maps.
So, say you have a heatmap like this:
fixedRadiusHeatmap = new google.maps.visualization.HeatmapLayer({
data: myCoords,
map: theMap
});
In order to set the initial view, just call the function before adding the heatmap to your map.
fixedRadiusHeatmap.setOptions({radius: getHeatmapRadius()});
fixedRadiusHeatmap.setMap(theMap);
Then you need to reset the radius every time the map is zoomed, which can be done like this:
google.maps.event.addListener(theMap, 'zoom_changed', function () {
fixedRadiusHeatmap.setOptions({radius: getHeatmapRadius()});
});
In my case it lags a bit, so it shows the (stupidly aggregated and poorly thought out) default heatmap before the fixed radius one appears. Maybe there is a way to delay the rendering to make the transition smoother, but that's a different problem.