[英]Create interactive map with R Leaflet that shows markers upon polygon click
Creating a leaflet map in R
can be tricky if one wants to add reactive, or otherwise customized, features.如果想要添加响应式或其他自定义功能,在
R
创建传单地图可能会很棘手。 My goal was to use my workflow in R
to make a choropleth map that is then augmented by the ability to click a polygon and 'reveal' a set of points.我的目标是使用我在
R
工作流程制作一个等值线图,然后通过单击多边形和“显示”一组点的能力来增强该地图。
A similar question was asked and answered in another post , but it is completely done in leaflet.js
.在另一篇文章中提出并回答了类似的问题,但它完全是在
leaflet.js
完成的。 Converting this solution to something that can be done from within R
but without shiny
is not as straight forward.将此解决方案转换为可以在
R
完成但没有shiny
事情并不是那么简单。 I know it will involve using htmlwidgets::onRender()
and some JavaScript
knowledge.我知道这将涉及使用
htmlwidgets::onRender()
和一些JavaScript
知识。
Here is a reprex of a basic plot to add 'reactive' points to:这是添加“反应”点的基本图的再现:
# Load libraries
library(sf)
library(leaflet)
# Grab data sample from the sf package for mapping
nc <- st_read(system.file("shape/nc.shp", package="sf"))
# Set a basic palette
pal <- colorNumeric("viridis", NULL)
# Create the leaflet widget with R code
nc_map <- leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>% # To get city names
addPolygons(data = nc,
fillColor = ~pal(AREA),
color = 'grey',
opacity = 1,
layerId = ~CNTY_ID,
group = 'Municipality',
fillOpacity = 0.65,
weight = 1.5,
dashArray = '3',
smoothFactor = 1,
highlight = highlightOptions( # Make highlight pop out
weight = 3.5,
color = '#666',
dashArray = "",
fillOpacity = 0.5,
bringToFront = T),
popup = ~NAME,
popupOptions = popupOptions(
style = list('font-weight' = 'normal', padding = '3px 8px'),
textsize = '15px',
maxWidght = 200,
maxHeight = 250,
direction = 'auto')) %>%
addLegend(data = nc, pal = pal, values = ~AREA,
opacity = 0.7,
title = 'Area of county',
position = "bottomleft")
We can start from @nikoshr's solution using leaflet.js
, making a few adjustments to work from R
.我们可以从@nikoshr 的解决方案开始,使用
leaflet.js
,对R
进行一些调整。 Here is the basic idea:这是基本思想:
onRender()
step, and convert to geoJSON
.onRender()
步骤传递包含点信息的数据集,并转换为geoJSON
。layerID
from addPolygons
in your R leaflet widget to track unique polygons, in this case the CNTY_ID
.layerID
的addPolygons
来跟踪唯一的多边形,在本例中为CNTY_ID
。if(layer instanceof L.Polygon)
).if(layer instanceof L.Polygon)
)仅循环遍历多边形图层。 I had issues if it looped through all layers.featureGroup()
to add points to dynamically;featureGroup()
来动态添加点; previous solutions used a layerGroup()
but this doesn't work with the method .bringToFront()
layerGroup()
但是,这并不与法工作.bringToFront()
.on('click')
command that will add the markers to the specific to the CNTY_ID
..on('click')
命令,将标记添加到特定的CNTY_ID
。.on('mouseover')
command to ensure the marker points are always on top, no matter what the highlight option is chosen in the R widget..on('mouseover')
命令以确保标记点始终位于顶部,无论在 R 小部件中选择什么突出显示选项。 Working from the leaflet widget provided in the question above, the following can be added to create the desired map:使用上述问题中提供的传单小部件,可以添加以下内容以创建所需的地图:
library(geojsonsf)
# Custom points to appear in the data (centroids)
nc_centroid <- st_centroid(nc)
nc_map %>% htmlwidgets::onRender("
function(el, x, data){
var mymap= this;
// Create new group
var featureGroup = L.featureGroup();
mymap.addLayer(featureGroup);
// For each polygon layer...
mymap.eachLayer(function(layer){
if(layer instanceof L.Polygon) {
// Zoom to the clicked area
layer.on('click', function(e){
var bbox = e.target.getBounds();
var sw = bbox.getSouthWest();
var ne = bbox.getNorthEast();
mymap.fitBounds([sw, ne]);
// Grab ID from the polygon clicked
var clickedPoly = e.sourceTarget.options.layerId;
// Clear prior layer and fill with markers with matching polygon ID
featureGroup.clearLayers();
featureGroup.addLayer(L.geoJson(data, {
pointToLayer: function(feature, latlng){
var markerlayer = L.circleMarker(latlng, {
color: '#2e2eb8',
radius: 7,
fill: true,
fillOpacity: .5,
opacity: .5
});
return markerlayer;
},
// Add labels to the markers
onEachFeature: function(feature, layer) {
if (feature.properties && feature.properties.NAME) {
return layer.bindTooltip(feature.properties.NAME);
}
},
// Keep only counties within the clicked polygon
filter: function (feature) {
return feature.properties.CNTY_ID === clickedPoly;
}
}));
});
// Ensure that the markers are always on top
layer.on('mouseover', function(e){
featureGroup.bringToFront();
});
};
});
}", data = geojsonsf::sf_geojson(nc_centroid))
This will create a map that shows the popup for the county as well as the point (with tooltip on hover) when the associated polygon is clicked.这将创建一个地图,显示该县的弹出窗口以及单击关联多边形时的点(悬停工具提示)。 The polygon will be highlighted upon mouseover, but will not mask the points.
鼠标悬停时多边形将突出显示,但不会掩盖点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.