1

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/[email protected]/dist/leaflet.css"
    integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
    crossorigin=""/>

    <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/dist/MarkerCluster.css" />
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/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/[email protected]/dist/leaflet.js"
    integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og=="
    crossorigin=""></script>

    <script type='text/javascript' src='https://unpkg.com/[email protected]/dist/leaflet.markercluster.js'></script>

 <!-- Load Esri Leaflet from CDN -->
    <script src="https://unpkg.com/[email protected]/dist/esri-leaflet.js"
    integrity="sha512-tyPum7h2h36X52O2gz+Pe8z/3l+Y9S1yEUscbVs5r5aEY5dFmP1WWRY/WLLElnFHa+k1JBQZSCDGwEAnm2IxAQ=="
    crossorigin=""></script>
    <!-- Leaflet.FeatureGroup.SubGroup assets -->
<script src="https://unpkg.com/[email protected]/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 Answer 1

0

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);




}

Not the answer you're looking for? Browse other questions tagged or ask your own question.