Klaster danych GeoJSON za pomocą PruneCluster

Oct 01 2020

Próbuję utworzyć klaster z kategoriami przy użyciu PruneCluster wokół moich warstw GeoJSON.

Jako przykład w GitHubie tworzą losowo niektóre markery, a następnie dodają je do klastra.

Zrobiłem to samo, uzyskałem współrzędne z warstwy GeoJSON, zapisałem go w zmiennej, a następnie dodałem do Prunecluster w następujący sposób:

leafletView.BuildLeafletClusterIcon = function(cluster) {
        var e = new L.Icon.MarkerCluster();

        e.stats = cluster.stats;
        e.population = cluster.population;
        return e;
    };

    var colors = ['rgb(10, 94, 219)', 'rgb(253, 152, 1)', 'rgb(3, 180, 11)'],
        pi2 = Math.PI * 2;

    L.Icon.MarkerCluster = L.Icon.extend({
        options: {
            iconSize: new L.Point(44, 44),
            className: 'prunecluster leaflet-markercluster-icon'
        },

        createIcon: function() {
            // based on L.Icon.Canvas from shramov/leaflet-plugins (BSD licence)
            var e = document.createElement('canvas');
            this._setIconStyles(e, 'icon');
            var s = this.options.iconSize;
            e.width = s.x;
            e.height = s.y;
            this.draw(e.getContext('2d'), s.x, s.y);
            return e;
        },

        createShadow: function() {
            return null;
        },

        draw: function(canvas, width, height) {

            var lol = 0;

            var start = 0;
            for (var i = 0, l = colors.length; i < l; ++i) {

                var size = this.stats[i] / this.population;


                if (size > 0) {
                    canvas.beginPath();
                    canvas.moveTo(22, 22);
                    canvas.fillStyle = colors[i];
                    var from = start + 0.14,
                        to = start + size * pi2;

                    if (to < from) {
                        from = start;
                    }
                    canvas.arc(22, 22, 22, from, to);

                    start = start + size * pi2;
                    canvas.lineTo(22, 22);
                    canvas.fill();
                    canvas.closePath();
                }

            }

            canvas.beginPath();
            canvas.fillStyle = 'white';
            canvas.arc(22, 22, 18, 0, Math.PI * 2);
            canvas.fill();
            canvas.closePath();

            canvas.fillStyle = '#555';
            canvas.textAlign = 'center';
            canvas.textBaseline = 'middle';
            canvas.font = 'bold 12px sans-serif';

            canvas.fillText(this.population, 22, 22, 40);
        }
    });


let myLayerOptionsArbre = {

        pointToLayer: createCustomIcon,
        onEachFeature: function(feature, layer) {
            layer.bindTooltip(feature.properties.titre);
            layer.on({
                click: onMarkerClick
            });
            coordsArb.push(feature.geometry.coordinates);

        }
    }

var arb = arbres
    var arbre = new L.GeoJSON(arb, myLayerOptionsArbre)

var ap = {}

    for (var i = 0; i < coordsAP.length; i++) {

        ap = new PruneCluster.Marker(coordsAP[i][1], coordsAP[i][0]);
        console.log(typeof ap)
        console.log("hey", coordsAP[i][1])
        ap.category = AIRES_PROTEGEES;
        leafletView.RegisterMarker(ap);
    }

leafletView.ProcessView();
    mymap.addLayer(leafletView)

Teraz na mojej mapie mam klastry wokół nowych znaczników i warstw GeoJSON. Kiedy przeczytałem dokument, stwierdziłem, że Prunecluster nie obsługuje GeoJSON. Teraz, jeśli pracuję tylko ze znacznikami, jak mogę dołączyć je do właściwości funkcji geojson, ponieważ tworzę niestandardowe wyskakujące okienka z funkcją onMarkerClickwywoływaną po kliknięciu funkcji geojson.

Więc jeśli masz pomysł, jak to osiągnąć, byłbym zadowolony.

Odpowiedzi

TomazicM Oct 02 2020 at 01:59

Jeśli chcesz wyświetlać znaczniki za pomocą PruneClusterwtyczki, nie możesz tego łączyć z wyświetlaniem tych samych markerów przez warstwę GeoJSON.

Jeśli twoje znaczniki pochodzą z danych GeoJSON, możesz użyć ulotek L.geoJSONdo iteracji po cechach / punktach, ale znaczniki muszą być tworzone tylko z instancjami PruneCluster.Markerobiektu.

Ponieważ markery utworzone za pomocą PruneClusterwtyczki nie są standardowymi znacznikami Leaflet, nie można przypisać wyskakujących okienek ani programów obsługi zdarzeń do tych znaczników przy użyciu standardowych metod Leaflet. Istnieje rozwiązanie tego problemu w postaci PrepareLeafletMarker(leafletMarker, data)metody nadpisywania (patrz dokhttps://github.com/SINTEF-9012/PruneCluster). Pierwszym parametrem leafletMarkerjest standardowy znacznik Ulotki, do którego można zastosować wszystkie standardowe metody znaczników do tworzenia podpowiedzi, wyskakujących okienek, procedur obsługi zdarzeń itp. Drugi parametr to data, który zawiera dane z datawłaściwości markera, podane w momencie tworzenia znacznika, na przykład:

var marker = new PruneCluster.Marker(latLng.lat, latLng.lng);
marker.data.properties = feature.properties;
leafletView.RegisterMarker(marker);

Znacznik z powyższego przykładu data.propertieszawierałby wszystkie właściwości obiektu.

Poniżej znajduje się prosty przykład tworzenia PruneClustermarkerów ze źródła GeoJSON geojsonData. Wyskakujące okienko jest przypisywane do markera z właściwości obiektu name, a po kliknięciu znacznika wszystkie właściwości elementu są wyświetlane w konsoli.

var map = L.map("map", {
  attributionControl: false,
  zoomControl: false
}).setView(new L.LatLng(41.89, 12.49), 15);

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
  detectRetina: true,
  maxNativeZoom: 17
}).addTo(map);

var leafletView = new PruneClusterForLeaflet();
leafletView.Cluster.Size = 160;

leafletView.PrepareLeafletMarker = function(leafletMarker, data) {
  leafletMarker.bindPopup(data.properties.name);
  leafletMarker.on('click', function(evt){
    console.log(data);
  });
};

L.geoJSON(geojsonData, {
  pointToLayer: function(feature, latLng) {
    var marker = new PruneCluster.Marker(latLng.lat, latLng.lng);
    marker.data.properties = feature.properties;
    leafletView.RegisterMarker(marker);
  }
});

map.addLayer(leafletView);