javascript 谷歌地图热图层点半径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12291459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google Maps heatmap layer point radius
提问by eqzx
I want to be able to specify the radius of points effectively in meters. The API is configured so that the radius
property is held to be constant for pixels, so that zooming in causes the heatmap to erode (I know you can make the heatmap not erode with the dissipating
property, but this raises other issues, i.e., having to manually mess with the radius to get my heatmap to display properly. Here is the heatmaps reference.
我希望能够以米为单位有效地指定点的半径。API 的配置使得radius
属性对于像素保持不变,因此放大会导致热图被侵蚀(我知道您可以使热图不被dissipating
属性侵蚀,但这会引发其他问题,即必须手动弄乱半径以使我的热图正确显示。这是热图参考。
Specifically, I'm trying to display a probability distribution on a map. I have the distribution in image form, and want to map the 0-1 weights to a heatmap layer. (I can, and don't want to, overlay the images).
具体来说,我试图在地图上显示概率分布。我有图像形式的分布,并且想要将 0-1 权重映射到热图层。(我可以也不想叠加图像)。
Any suggestions?
有什么建议?
回答by lccarrasco
Ok, I tried some things:
好的,我尝试了一些事情:
Using the Mercator Projection example (check the source)to extract the x,y pixel coordinates of any point from a latLng, to later use the geometry library, specifically the computeOffset functionget another latLng a distance "DM" (in meters) to the right of the previous one, get the difference (in pixels) as an absolute value "DP" and from there you get your "pixelsPerMeter" ratio DP/DM.
使用墨卡托投影示例(检查源)从 latLng 中提取任何点的 x、y 像素坐标,以便稍后使用几何库,具体而言,computeOffset 函数将另一个 latLng 与距离“DM”(以米为单位)到在前一个的右侧,将差异(以像素为单位)作为绝对值“DP”,然后从那里得到“pixelsPerMeter”比率 DP/DM。
So then, if you want your radius to be 100 meters you just set the properties to {radius:Math.floor(desiredRadiusPerPointInMeters*pixelsPerMeter)}
那么,如果您希望半径为 100 米,您只需将属性设置为 {radius:Math.floor(desiredRadiusPerPointInMeters*pixelsPerMeter)}
And to handle the change in zoom just use a listener
并处理缩放的变化只需使用侦听器
google.maps.event.addListener(map, 'zoom_changed', function () {
heatmap.setOptions({radius:getNewRadius()});
});
I uploaded a small example(try zooming), you can check if the distance looks right with the button on the bottom.
我上传了一个小例子(尝试缩放),您可以使用底部的按钮检查距离是否正确。
回答by schenkman
For anyone who'd like to have a nicely packaged coffeescript version of @lccarrasco's jsbin example, you can view the gist of the MercatorProjection coffeescript classI created using his code.
对于想要拥有@lccarrasco jsbin 示例的精美打包的咖啡脚本版本的任何人,您可以查看我使用他的代码创建的MercatorProjection 咖啡脚本类的要点。
Once you have the class loaded, you can use it with the following:
加载类后,您可以将其与以下内容一起使用:
map = new google.maps.Map(...)
heatmap = new google.maps.visualization.HeatmapLayer({map: map})
google.maps.event.addListener(map, 'zoom_changed', () ->
projection = new MercatorProjection()
heatmap.setOptions(radius: projection.getNewRadius(map, 15))
)
Where '15' is the radius in meters which you can play with or set programmatically by other means to get your heatmap to look like you want it.
其中“15”是以米为单位的半径,您可以使用它或通过其他方式以编程方式设置以使您的热图看起来像您想要的那样。
回答by junlop
I solved this by using the listener that @lccarrasco used but in my getNewRadius() function i made the radius change relative to the zoom.
我通过使用@lccarrasco 使用的侦听器解决了这个问题,但是在我的 getNewRadius() 函数中,我使半径相对于缩放发生了变化。
ie. var radius = (somemultiplicationfactor)/(Math.pow(2,(20-zoom)));
IE。var radius = (somemultiplicationfactor)/(Math.pow(2,(20-zoom)));
This works as the zoom ratio is 2:1 for each zoom
这是因为每次缩放的缩放比例为 2:1
回答by Aaron Bramson
Based on a Google group forum post and this GIS post, I came up with a simple yet complete solution along the same lines.
基于 Google group forum post 和this GIS post,我想出了一个简单而完整的解决方案。
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.
首先,定义一个函数来获取给定缩放级别的半径(以米为单位):因为不同纬度存在缩放差异,所以您需要输入someLatValue
,例如您计划使用的地图的中心。虽然是近似值,但对于小国大小的准确结果来说已经足够了。您还需要以米为单位指定所需的半径大小。
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(zoomLevel){
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.
这将返回特定纬度周围所需米数和缩放级别的(近似)半径(以像素为单位)。该值156543.03392
基于 google 实际用于 Google 地图的地球的近似半径。
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(theMap.getZoom())});
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(theMap.getZoom())});
});
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.
在我的情况下,它有点滞后,所以它在固定半径出现之前显示了(愚蠢的聚合和深思熟虑的)默认热图。也许有一种方法可以延迟渲染以使过渡更平滑,但这是一个不同的问题。