问题
EDIT 3: I was able to get it working. I was making it harder than it actually was!
https://jsfiddle.net/crashvector/xczj76om/13/
EDIT 2: Here is a link to a working fiddle of what I currently have. This has the seperate layers, but doesn't have the clustering function I am trying to implement.
https://jsfiddle.net/xczj76om/12/
EDIT: I have updated my JS with a version that maps a cluster layer, and three individual layers based on the Classification listed in the JSON.
My desire is to implement:
https://ghybs.github.io/Leaflet.FeatureGroup.SubGroup/examples/subGroup-markercluster-controlLayers-realworld.388.html
in order to get rid of the extra cluster layer and cluster the three individual layers together.
I am unsure of how to change this section to accomodate the plugin above.
//define clustering layer
var markerClusters = L.markerClusterGroup({});
for ( var i = 0; i < markers.length; ++i ) {
var popup = '<br/><b>Sample Name:</b> '+ markers[i]["Sample Name"] +
'<br/><b>Location Description:</b> ' + markers[i]["Location Description"] +
'<br/><b>Date Taken:</b> ' + markers[i]["Date"] +
'<br/><b>Classification:</b> ' + markers[i]["Classification"]
//define markers
var m = L.marker( [markers[i].Lattitude, markers[i].Longitude], {icon: icons[markers[i]["Classification"]]})
.bindPopup( popup );
category = markers[i]["Classification"];
// Initialize the category array if not already set.
if (typeof categories[category] === "undefined") {
categories[category] = L.layerGroup().addTo(map);
layersControl.addOverlay(categories[category], category);
}
categories[category].addLayer(m);
markerClusters.addLayer( m );
}
map.addLayer( markerClusters );
I previously asked a question here:
Jquery Leaflet marker layer control for dynamic custom icons with clustering plugin
Which pointed me to this plugin:
Using several Marker Cluster Groups displays overlapping Clusters
And also this thread:
Cluster multiple Layers with markercluster
HTML
<!DOCTYPE html>
<html>
<head>
<title>Sample Locations</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css" />
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css" />
<script charset="utf8" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"
integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
crossorigin=""></script>
<script type='text/javascript' src='https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js'></script>
<!-- Load Esri Leaflet from CDN -->
<script src="https://unpkg.com/esri-leaflet@2.2.4/dist/esri-leaflet.js"
integrity="sha512-tyPum7h2h36X52O2gz+Pe8z/3l+Y9S1yEUscbVs5r5aEY5dFmP1WWRY/WLLElnFHa+k1JBQZSCDGwEAnm2IxAQ=="
crossorigin=""></script>
<!-- Leaflet.FeatureGroup.SubGroup assets -->
<script src="https://unpkg.com/leaflet.featuregroup.subgroup@1.0.2/dist/leaflet.featuregroup.subgroup.js"></script>
<body>
<style>
body{
margin:0;
padding:0;
}
#map{
position: absolute;
top:0;
bottom:0;
right:0;
left:0;
}
#basemaps-wrapper{
position: absolute;
bottom: 10px;
left: 10px;
z-index: 400;
background: white;
padding: 10px;
}
#basemaps{
margin-bottom: 5px;
}
</style>
<div id="map"></div>
<div id="basemaps-wrapper" class="leaflet-bar">
<select name="basemaps" id="basemaps" onChange="changeBasemap(basemaps)">
<option value="Topographic">Topographic</option>
<option value="Streets">Streets</option>
<option value="NationalGeographic">National Geographic</option>
<option value="Oceans">Oceans</option>
<option value="Imagery">Imagery</option>
<option value="ImageryClarity" selected>Imagery (Clarity)</option>
<option value="ImageryFirefly">Imagery (Firefly)</option>
<option value="Gray">Gray</option>
<option value="DarkGray">Dark Gray</option>
<option value="ShadedRelief">Shaded Relief</option>
<option value="Physical">Physical</option>
</select>
</div>
</head>
<script type='text/javascript' src='JS/maptest2.js'></script>
</body>
</html>
Jquery
// Define site URL
var myURL = jQuery( 'script[src$="JS/maptest2.js"]' ).attr( 'src' ).replace( 'JS/maptest2.js', '' );
//define icon image locations
var Sourceiconurl = myURL + 'images/source.png',
Blankiconurl = myURL + 'images/background.png',
Unknowniconurl = myURL + 'images/unknown.png',
Backgroundiconurl = myURL + 'images/background.png';
//initialize variable
var markers;
//pull data from json
jQuery.ajax({
url: myURL + "map_json.php",
type: "JSON",
async: false,
success: function(data){
markers = jQuery.parseJSON(data);
jQuery(markers).each(function( index, element ) {
});
}
});
//initialize map
var map = L.map( 'map', {
center: [39.8333333, -98.585522],
minZoom: 1,
zoom: 4
});
//create esri layers and selector
var layer = L.esri.basemapLayer('Imagery').addTo(map);
var layerLabels = L.esri.basemapLayer('ImageryLabels');
map.addLayer(layerLabels);
function setBasemap(basemap) {
if (layer) {
map.removeLayer(layer);
}
layer = L.esri.basemapLayer(basemap);
map.addLayer(layer);
if (layerLabels) {
map.removeLayer(layerLabels);
}
if (basemap === 'ShadedRelief'
|| basemap === 'Oceans'
|| basemap === 'Gray'
|| basemap === 'DarkGray'
|| basemap === 'Terrain'
) {
layerLabels = L.esri.basemapLayer(basemap + 'Labels');
map.addLayer(layerLabels);
} else if (basemap.includes('Imagery')) {
layerLabels = L.esri.basemapLayer('ImageryLabels');
map.addLayer(layerLabels);
}
}
function changeBasemap(basemaps){
var basemap = basemaps.value;
setBasemap(basemap);
}
//create legend (need to figure out how to format)
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'legend'),
categorynames = ["Source", "Blank/Background", "Unknown"],
imagefiles = [Sourceiconurl,Blankiconurl,myURL + Unknowniconurl];
// assign image for each category
for (var i = 0; i < categorynames.length; i++) {
div.innerHTML +=
categorynames[i] + (" <img src="+ imagefiles[i] +" height='50' width='50'>") +'<br>';
}
return div;
};
legend.addTo(map);
//define base icon features
var MapIcon = L.Icon.extend({
options: {
iconSize: [40, 55],
iconAnchor: [20, 35],
popupAnchor: [2, -10]
}
});
//define custom icons
var Source = new MapIcon({iconUrl: Sourceiconurl}),
Blank = new MapIcon({iconUrl: Blankiconurl}),
Unknown = new MapIcon({iconUrl: Unknowniconurl}),
Background = new MapIcon({iconUrl: Backgroundiconurl});
//allows function to read json field and assign to icon url
var icons = {
"Source": Source,
"Blank": Blank,
"Unknown": Unknown,
"Background": Background};
var categories = {},
category;
var layersControl = L.control.layers(null, null).addTo(map);
//define clustering layer
var markerClusters = L.markerClusterGroup({});
for ( var i = 0; i < markers.length; ++i ) {
var popup = '<br/><b>Sample Name:</b> '+ markers[i]["Sample Name"] +
'<br/><b>Location Description:</b> ' + markers[i]["Location Description"] +
'<br/><b>Date Taken:</b> ' + markers[i]["Date"] +
'<br/><b>Classification:</b> ' + markers[i]["Classification"]
//define markers
var m = L.marker( [markers[i].Lattitude, markers[i].Longitude], {icon: icons[markers[i]["Classification"]]})
.bindPopup( popup );
category = markers[i]["Classification"];
// Initialize the category array if not already set.
if (typeof categories[category] === "undefined") {
categories[category] = L.layerGroup().addTo(map);
layersControl.addOverlay(categories[category], category);
}
categories[category].addLayer(m);
markerClusters.addLayer( m );
}
map.addLayer( markerClusters );
JSON
[
{
"Sample Name": "7411-2",
"Date": "2017-09-05",
"Lattitude": "40.3126",
"Longitude": "-94.0277",
"Location Description": "Lake 1",
"Classification": "Unknown",
"Empty": "1"
},
{
"Sample Name": "7411-1",
"Date": "2017-09-05",
"Lattitude": "40.5999",
"Longitude": "-93.7661",
"Location Description": "Lake 2",
"Classification": "Source",
"Empty": "1"
},
{
"Sample Name": "7406-3",
"Date": "2017-07-31",
"Lattitude": "39.4076",
"Longitude": "-94.5555",
"Location Description": "Lake 3",
"Classification": "Background",
"Empty": "1"
},
{
"Sample Name": "7406-3",
"Date": "2017-07-31",
"Lattitude": "39.4076",
"Longitude": "-94.5555",
"Location Description": "Lake 3",
"Classification": "Background",
"Empty": "1"
}
]
ICONS
You can use any 4 .png icon files in place of the ones I have listed.
回答1:
I was able to make all the magic happen with the following block. This creates dynamic layers based on the JSON field and then allows those layers to be clustered together dynamically based on what layers are currently selected.
var categories = {},
category;
var layersControl = L.control.layers(null, null).addTo(map);
var parentGroup = L.markerClusterGroup().addTo(map);
for ( var i = 0; i < markers.length; ++i ) {
var popup = '<br/><b>Sample Name:</b> '+ markers[i]["Sample Name"] +
'<br/><b>Location Description:</b> ' + markers[i]["Location Description"] +
'<br/><b>Date Taken:</b> ' + markers[i].Date +
'<br/><b>Classification:</b> ' + markers[i].Classification
//define markers
var m = L.marker( [markers[i].Lattitude, markers[i].Longitude], {icon: icons[markers[i].Classification]})
.bindPopup( popup );
category = markers[i].Classification;
// Initialize the category array if not already set.
if (typeof categories[category] === "undefined") {
categories[category] = L.featureGroup.subGroup(parentGroup,m).addTo(map);
layersControl.addOverlay(categories[category], category);
}
categories[category].addLayer(m);
}
来源:https://stackoverflow.com/questions/56856490/jquery-leaflet-marker-layer-cluster-support-with-layers-generated-from-unique-js