具有leafletR可变点大小的交互式地图

时间:2015-03-15 20:32:40

标签: r leaflet

我创建了一个交互式地图,如下所示:

library(leafletR)
data(quakes)

# store data in GeoJSON file (just a subset here)
q.dat <- toGeoJSON(data=quakes[1:99,], dest=tempdir(), name="quakes")

# make style based on quake magnitude
q.style <- styleGrad(prop="mag", breaks=seq(4, 6.5, by=0.5), style.val=rev(heat.colors(5)), leg="Richter Magnitude", fill.alpha=0.7, rad=8)

# create map
q.map <- leaflet(data=q.dat, dest=tempdir(), title="Fiji Earthquakes", base.map="osm", style=q.style, popup="mag")

# view map in browser
rstudio::viewer(q.map)

现在,我想让圆的大小依赖于另一个变量。让我们说变量'station'。我怎样才能做到这一点?如果这个包不可能,我打开使用另一个包...只要我可以放一个图例,地图是交互式的,点击时会出现一个弹出窗口,颜色可能取决于连续变量。

1 个答案:

答案 0 :(得分:9)

我通过documentation读取了leafletR包,在我看来(我可能错了)当前版本不支持同一数据集的多个样式。他们给出了一些示例,通过列出它们(例如style=list(sty.1, sty.2))来组合2个样式单元格,但这只与列出2个不同的数据集一起使用(有关详细信息,请参阅文档中的P.8)。我尝试了各种技巧,但没有一个能为我工作。

然而,我想出了一个你可能想尝试的hacky解决方案。使用leaflet()函数创建html页面后,您可以编辑处理样式的Javascript代码,使radius属性动态化(这也适用于其他样式属性,例如{{ 1}},fill等。)

您需要了解的内容:

在传单创建的HTML文档中,搜索alpha函数的定义。您应该找到以下代码段:

style1(feature)

此函数基本上返回数据集中每条记录的样式。如您所见,当前形式的函数返回function style1(feature) { return {"color": getValue(feature.properties.mag), "fillOpacity": 0.7, "radius": 8}; } fillOpacity的静态值。但是,当涉及到颜色时,它会调用另一个名为radius的函数,并将getValue(幅度)属性传递给它。如果我们看一下mag函数的定义,我们会看到它只是定义了每种颜色的幅度范围:

getValue

功能定义非常简单。如果x(在这种情况下的大小)大于或等于6.5,那么该数据点的颜色将是&#34;#808080&#34;。如果它在6到6.5之间,那么颜色将是#FF0000&#34;。等等等等。

你能做什么:

现在我们看到Javascript代码如何处理颜色如何分配给每个数据点,我们可以用很少的努力为所有其他样式属性做类似的事情。例如,以下代码段显示了如何根据区域中的工作站数量使半径动态化:

function getValue(x) {
    return x >= 6.5 ? "#808080" :
           x >= 6 ? "#FF0000" :
           x >= 5.5 ? "#FF5500" :
           x >= 5 ? "#FFAA00" :
           x >= 4.5 ? "#FFFF00" :
           x >= 4 ? "#FFFF80" :
           "#808080";
}  

因此,使用/* The getValue function controls the color of the data points */ function getValue(x) { return x >= 6.5 ? "#808080" : x >= 6 ? "#FF0000" : x >= 5.5 ? "#FF5500" : x >= 5 ? "#FFAA00" : x >= 4.5 ? "#FFFF00" : x >= 4 ? "#FFFF80" : "#808080"; } /* The getRadValue function controls the radius of the data points */ function getRadValue(x) { return x >= 100 ? 24 : x >= 80 ? 20 : x >= 60 ? 16 : x >= 40 ? 12 : 8; } /* The updated definition of the style1 function */ function style1(feature) { return {"color": getValue(feature.properties.mag), "fillOpacity": 0.7, "radius": getRadValue(feature.properties.stations) }; } 的新定义,现在我们可以控制数据点的颜色和半径。代码修改的结果如下所示:

enter image description here

这种方法的好处在于它可以让您对样式属性和它们可以拥有的值范围进行更细粒度的控制。主要的缺点是,如果您想为这些属性添加图例,那么您必须手动执行此操作。添加/编辑图例的逻辑应位于HTML文档的最底部,如果您了解Javascript / HTML / CSS,则编辑该代码段不应该太困难。

<强>更新

要为新动态变量添加图例(在我们的示例中为半径),您需要编辑附加到图例对象的style1(feature)处理程序。正如我之前所说的,这个处理程序的定义通常位于html页面的底部,如果我们运行你在问题中提供的一些代码,那么处理程序应如下所示:

.onAdd

上面的代码只是循环遍历大小的值范围,并创建一个框(具有适当的颜色,引用我们之前查看过的legend.onAdd = function (map) { var div = L.DomUtil.create('div', 'legend'); var labels = []; var grades = [4, 4.5, 5, 5.5, 6, 6.5]; div.innerHTML += 'Richter Magnitude<br>'; for (var i = 0; i < grades.length - 1; i++) { div.innerHTML += '<i style="background:' + getValue(grades[i]) + '"></i> ' + grades[i] + '&ndash;' + grades[i + 1] + '<br>'; } return div; }; 函数)和一个标签。如果你想为getValue变量创建类似的东西,让我们说,我们可以使用上面相同的逻辑。虽然在这种情况下不是改变颜色,但我们会改变圆的大小。以下代码段显示了如何实现:

stations

如您所见,我们控制的样式属性类型将决定我们如何在图例中指定它。例如,如果要为legend.onAdd = function (map) { var div = L.DomUtil.create('div', 'legend'); var labels = []; var grades = [4, 4.5, 5, 5.5, 6, 6.5]; div.innerHTML += 'Richter Magnitude<br>'; for (var i = 0; i < grades.length - 1; i++) { div.innerHTML += '<i style="background:' + getValue(grades[i]) + '"></i> ' + grades[i] + '&ndash;' + grades[i + 1] + '<br>'; } // Adding the range of possible of values that the variable might take // This should be in sync with the range of values you considered in // the getRadValue function. var rad_grades = [40, 60, 80, 100]; // The title for this section of the legend div.innerHTML += 'Number of stations<br>' for (var i = 0; i < rad_grades.length - 1; i++) { div.innerHTML += '<table style="border: none;"><tr><td class="circle" style="width: ' + (getRadValue(rad_grades[rad_grades.length - 2]) * 2 + 6) + 'px;"><svg style="width: ' + (getRadValue(rad_grades[i]) * 2 + 6) + 'px; height: ' + (getRadValue(rad_grades[i]) * 2 + 6) + 'px;" xmlns="http://www.w3.org/2000/svg" version="1.1"><circle cx="' + (getRadValue(rad_grades[i]) + 3) + '" cy="' + (getRadValue(rad_grades[i]) + 3) + '" r="' + getRadValue(rad_grades[i]) + '" /></svg></td><td class="value">' + rad_grades[i] + '&ndash;' + rad_grades[i + 1] + '</td></tr></table>'; } return div; }; 属性添加图例,则可能需要尝试其他方法,而不是使用圆并控制其宽度和高度。上面代码修改的最终结果如下所示:

enter image description here

此外,如果您想在弹出窗口中包含电台数量,那么您必须编辑alpha功能。它将采用与所有其他修改相同的方法,这是一个非常简单的改变。

onEachFeature函数在原始HTML中如下所示:

onEachFeature

如果要在弹出窗口中包含站点数,则需要将其包含在function onEachFeature(feature, layer) { if (feature.properties && feature.properties.mag) { layer.bindPopup("mag: " + feature.properties.mag); } } 方法的参数中,如下所示:

bindPopup

此更改的最终结果如下:

enter image description here

希望这会有所帮助。