0

I am starting with Leaflet and I am trying to use the Regular-grid-cluster plugin with no success. The following code works until the definition of the 'const grid' element. So, I can see the markers on the map but I can not implement the functionality of the plugin. Could you point me the errors in the code?

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    <!-- Leaflet -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
    <!-- Grid Cluster -->
    <link rel="stylesheet" href="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/node_modules/leaflet/dist/leaflet.css" />
    <link rel="stylesheet" href="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/zoomdisplay/zoomdisplay.css" />
    <link rel="stylesheet" href="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/demo.css" />
    <script src="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/node_modules/leaflet/dist/leaflet.js"></script>
    <script src="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/zoomdisplay/zoomdisplay.js"></script>
    <script src="https://adammertel.github.io/Leaflet.RegularGridCluster/dist/leaflet-regulargridcluster.src.js"></script>
    <script src="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/random_data/main.js"></script>
    <!-- GeoJSON file -->
    <script src="https://drive.google.com/uc?export=view&id=1Wiju0Kfbpj2YKTKog1u2ZceEXBdbb12r"></script>
</head>

<body>
    <div id="map" style="height: 98vh; width: 100hw"></div>
    <script>
    var map = L.map('map');
    var CartoDB_PositronNoLabels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
        subdomains: 'abcd',
        minZoom: 4,
        maxZoom: 18,
    }).addTo(map);
    var CartoDB_PositronOnlyLabels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}{r}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
        subdomains: 'abcd',
        minZoom: 4,
        maxZoom: 18,
    }).addTo(map);
    var southWest = L.latLng(-60, -80),
        northEast = L.latLng(-10, -60);
    var bounds = L.latLngBounds(southWest, northEast);
    map.setMaxBounds(bounds);
    map.on('drag', function() {
        map.panInsideBounds(bounds, {
            animate: false
        });
    });
    var layer = L.geoJSON(points, {
        onEachFeature: function(feature, layer) {
            var popupContent = "<p> <b>" + "FIC_ID: " + "</br>" + feature.properties.fic_id + "</b></br>" + "Región: " + "</br>" + feature.properties.reg_ejec + "</br>" + feature.properties.pro_ejec + ",</br> " + feature.properties.com_ejec + ",</br> " + feature.properties.num_informe + "</p>";
            layer.bindPopup(popupContent);
        }
    }).addTo(map);
    map.fitBounds(layer.getBounds());
    const rules = {
        cells: {
            "fillColor": {
                "method": "mean",
                "attribute": "fic_id",
                "scale": "size",
                "range": ["#d7191c", "#fdae61", "#ffffbf", "#a6d96a", "#1a9641"]
            },
            "color": "black",
            "fillOpacity": 0.2,
            "weight": 0
        },
        markers: {
            "color": "white",
            "weight": 2,
            "fillOpacity": 0.9,
            "fillColor": {
                "method": "mean",
                "attribute": "fic_id",
                "scale": "continuous",
                "range": ["#ffffb2", "#fecc5c", "#fd8d3c", "#e31a1c"]
            },
            "radius": {
                "method": "count",
                "attribute": "fic_id",
                "scale": "continuous",
                "range": [7, 17]
            }
        },
        texts: {}
    }
    const grid = L.regularGridCluster({
        rules: rules,
        gridMode: 'hexagon,
        showCells: true,
        showMarkers: true,
        showTexts: false
    });
    grid.addLayers(layer);
    grid.addTo(map);
    </script>
</body>

</html>

EDIT: I made some amendments to the code, now I can see the markers when testing but I still got an error, this time the console says:

leaflet-regulargridcluster.src.js:282 Uncaught TypeError: layersArray.map is not a function at i.addLayers (leaflet-regulargridcluster.src.js:282) at test05.html:94

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <!-- Leaflet -->
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
    
    <!-- Grid Cluster -->
    <link rel="stylesheet" href="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/zoomdisplay/zoomdisplay.css" />
    <link rel="stylesheet" href="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/demo.css" />

    <script src="https://adammertel.github.io/Leaflet.RegularGridCluster/demo/zoomdisplay/zoomdisplay.js"></script>
    <script src="https://adammertel.github.io/Leaflet.RegularGridCluster/dist/leaflet-regulargridcluster.src.js"></script>
    
    <!-- GeoJSON file -->
    <script src="https://drive.google.com/uc?export=view&id=1Wiju0Kfbpj2YKTKog1u2ZceEXBdbb12r"></script>
</head>

<body>
    <div id="map" style="height: 98vh; width: 100hw"></div>
    <script>
    var map = L.map('map');
    var CartoDB_PositronNoLabels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
        subdomains: 'abcd',
        minZoom: 4,
        maxZoom: 18,
    }).addTo(map);
    var CartoDB_PositronOnlyLabels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}{r}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
        subdomains: 'abcd',
        minZoom: 4,
        maxZoom: 18,
    }).addTo(map);
    var southWest = L.latLng(-60, -80),
        northEast = L.latLng(-10, -60);
    var bounds = L.latLngBounds(southWest, northEast);
    map.setMaxBounds(bounds);
    map.on('drag', function() {
        map.panInsideBounds(bounds, {
            animate: false
        });
    });
    var layer = L.geoJSON(points, {
        onEachFeature: function(feature, layer) {
            var popupContent = "<p> <b>" + "FIC_ID: " + "</br>" + feature.properties.fic_id + "</b></br>" + "Región: " + "</br>" + feature.properties.region_ejecucion + "</br>" + feature.properties.provincia_ejecucion + ",</br> " + feature.properties.comuna_ejecucion + ",</br> " + feature.properties.numero + "</p>";
            layer.bindPopup(popupContent);
        }
    }).addTo(map);
    map.fitBounds(layer.getBounds());
    const rules = {
        cells: {
            "fillColor": {
                "method": "mean",
                "attribute": "fic_id",
                "scale": "size",
                "range": ["#d7191c", "#fdae61", "#ffffbf", "#a6d96a", "#1a9641"]
            },
            "color": "black",
            "fillOpacity": 0.2,
            "weight": 0
        },
        markers: {
            "color": "white",
            "weight": 2,
            "fillOpacity": 0.9,
            "fillColor": {
                "method": "mean",
                "attribute": "fic_id",
                "scale": "continuous",
                "range": ["#ffffb2", "#fecc5c", "#fd8d3c", "#e31a1c"]
            },
            "radius": {
                "method": "count",
                "attribute": "fic_id",
                "scale": "continuous",
                "range": [7, 17]
            }
        },
        texts: {}
    }
    const grid = L.regularGridCluster({
        rules: rules,
        gridMode: 'square',
        showCells: true,
        showMarkers: true,
        showTexts: false
    });
    grid.addLayers(layer);
    grid.addTo(map);
    </script>
</body>

</html>
  • Do you get any errors in the browser debugger console? – TomazicM Jul 22 at 8:11
  • I got two: 'Uncaught SyntaxError: Identifier 'grid' has already been declared' and 'leaflet.js:5 Uncaught Error: Map container not found.' – gtapko Jul 22 at 14:03
1

Documentation on Regular-grid-cluster Leaflet plugin is not very extensive, but with the help of demo code at https://adammertel.github.io/Leaflet.RegularGridCluster/demo/random_data/ I was able to make your code work.

First thing you notice in demo code is that input to .addLayers of L.regularGridCluster is not Leaflet layer, but an array of objects. Description of structure of these objects in the docs is not very helping, but in the demo code such object has the following form:

{marker: markerLayer,
 properties: {
   a: maxValue,
   b: minValue
 }
}

Next thing is that markers to be used in L.regularGridCluster must support styling, like for example L.circleMarker.

And the last thing, when creating markers from GeoJSON, this layer should not be added to the map, since marker display is regulated by L.regularGridCluster.

Taken all this into account, your code could then look something like this (min and max properties are created random, as in demo code):

var data = [];

var layer = L.geoJSON(points, {
    pointToLayer: function (point, latLng) {
      var marker = L.circleMarker(latLng, {radius: 10});
      return(marker);
    },
    onEachFeature: function(feature, layer) {
      const properties = {
          a: 5 + Math.floor(Math.random() * 5),
          b: Math.floor(Math.random() * 5)
      };          
      data.push({marker: layer, properties: properties});
      var popupContent = "<p> <b>" + "FIC_ID: " + "</br>" + feature.properties.fic_id + "</b></br>" + "Región: " + "</br>" + feature.properties.reg_ejec + "</br>" + feature.properties.pro_ejec + ",</br> " + feature.properties.com_ejec + ",</br> " + feature.properties.num_informe + "</p>";
      layer.bindPopup(popupContent);
    }
});
map.fitBounds(layer.getBounds());

const grid = L.regularGridCluster({
    rules: rules,
    gridMode: 'hexagon',
    showCells: true,
    showMarkers: true,
    showTexts: false
});
grid.addLayers(data);
grid.addTo(map);
| improve this answer | |
  • Thank you, with your code, I was able to run the script properly. – gtapko Jul 27 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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