0

I am using angular 6 and ngx-leaflet. I am loading data backend, and I trying to zoom to area (in this case India) once data loaded on the map.

My html looks:

<div leaflet style="height: 800px; width: 100%"
    [leafletOptions]="options"
    (leafletMapReady)="onMapReady($event)"
    [leafletBaseLayers]="baseLayers"
    [leafletLayersControlOptions]="layersControlOptions"
    [leafletMarkerCluster]="markerClusterData"
    [leafletMarkerClusterOptions]="markerClusterOptions"
    (leafletMarkerClusterReady)="markerClusterReady($event)">
</div>

In .ts

@Component({
    templateUrl: 'details.component.html'
})

export class DetailsComponent implements OnInit {

LAYER_OSM = {
    enabled: false,
    layer: L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
        maxZoom: 17,
        minZoom: 2,
        subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
        detectRetina: true,
    })
};

layersControlOptions = { position: 'bottomright' };
baseLayers = {
    'Google': this.LAYER_OSM.layer
};
options = {
    zoom: 3,
    center: L.latLng([0.0, 0.0])
};
markerClusterGroup: L.MarkerClusterGroup;
markerClusterData: any[] = [];
markerClusterOptions: L.MarkerClusterGroupOptions = {};
fitBounds: any = null; // = [[46.67, -122.25], [47.01, -121.302]];
fGroup = L.featureGroup();
constructor(private mapDataService: MapDataService) { }

ngOnInit() {
    this.mapDataService.getMapData(this.nav)
        .subscribe(res => { this.generateData(res) });
}

onMapReady(map: L.Map) {
    map.fitBounds(map.getBounds(),{
        maxZoom: 12,
        animate: true
      });
 }

markerClusterReady(group: L.MarkerClusterGroup) {
    this.markerClusterGroup = L.markerClusterGroup();
}

generateData(res: any[]) {
    const data: any[] = [];
    res.forEach(function (item) {
        const icon = L.icon({
            iconSize: [25, 41],
            iconAnchor: [13, 41],
            iconRetinaUrl: 'leaflet/marker-icon-2x.png',
            iconUrl: 'leaflet/marker-icon.png',
            shadowUrl: 'leaflet/marker-shadow.png'
        });

        data.push(L.marker([item.latitude, item.longitude], { icon }));
    })

    this.markerClusterData = data;
}
}

onMapReady(map: L.Map), map.getBounds() is returning always one coordination, but not the one I need.

I Have also tried to use [leafletFitBounds], but I am not able to get correct bounce. The first is how it is now. The second that I am trying to achieve.

Thanks in advance.

What I have

What I would like to have

this.markerClusterData looks like this

markerClusterData

Bahodir
  • 539
  • 1
  • 9
  • 29

2 Answers2

4

map.getBounds() is returning the current boundry of the map, not the boundry of the data loaded into your markerClusterData.

In your html, add a line to bind the "leafletFitBounds" Input property to a property in your .ts file, e.g:

[leafletFitBounds]="mapFitToBounds"

In your ts file, add the new property

mapFitToBounds: L.LatLngBounds;

To control the max zoom and padding etc, you can also add the "[leafletFitBoundsOptions]" property to your html and ts e.g:

[leafletFitBoundsOptions]="mapFitToBoundsOptions"

In your ts file, add the new property

mapFitToBoundsOptions: L.FitBoundsOptions;

To make use of these input properties in your ts, you will need to configure your "mapFitToBoundsOptions" in ngOnInit(), e.g:

this.mapFitToBoundsOptions = {maxZoom: 12, animate: true};

For more settings that are configurable check: https://leafletjs.com/reference-1.3.2.html#fitbounds-options

Now to get the correct bounds you will need to call .getBounds() on this.markerClusterData once you have loaded the data, you can do this inside your subscription or your generateData function, if you change your subscription, here's an example of what it would look like:

this.mapDataService.getMapData(this.nav).subscribe(res => { 
  this.generateData(res);

  // Focus the map view to the boundaries of the marker group
  this.mapFitToBounds = this.markerClusterData.getBounds();
});

Remove the onMapReady event from your code and after making the above changes, your map should focus on your data.

Chris
  • 131
  • 2
  • 4
  • Chris thank you very much for your reply. `this.markerClusterData.getBounds()` is undefined. Getting `_this.markerClusterData.getBounds is not a function`. `this.markerClusterData` has a data. Any ideas? Thanks – Bahodir Jul 31 '18 at 15:30
  • That seems odd as MarkerClusterGroup extends a leaflet FeatureGroup to get the getBounds() method. I suspect it's because data is declared as an array and not a MarkerClusterGroup. Try and use the MarkerClusterGroup when building up your markers, inside your generateData function, change the "data" property declaration to "const data: L.MarkerClusterGroup = new L.MarkerClusterGroup();" then change where your adding the markers to "data.addLayer(L.marker([item.latitude, item.longitude], { icon }));". – Chris Aug 01 '18 at 05:54
-1

You can zoom the map with the function .fitBounds() and .getBounds(). In my code, this works for me:

this.map.fitBounds(this.layer.getBounds());

blackgreen
  • 34,072
  • 23
  • 111
  • 129