AckerApple / agm-overlays

Custom marker overlay for the @agm/core package
MIT License
25 stars 24 forks source link

fitBounds not supported? #36

Open nicksav opened 5 years ago

nicksav commented 5 years ago

Hey Looks like fitBounds is not supported as I am adding new overlays after the map was loaded and nothing happens?

Am I correct that it is not supported?

Thanks Nick

AckerApple commented 5 years ago

If you are trying to keep an overlay the same size regardless of zoom, see here: https://github.com/AckerApple/agm-overlays#zoom-sizing

We just called it bounds, and the boundaries are typically a small x/y grouping of numbers indicating in all directions of how to size the overlay at all times.

The demo code has one overlay with a fixed size definition as well: https://github.com/AckerApple/agm-overlays/blob/master/example/src/app.template.ts#L44

JulienBourgain commented 4 years ago

He was talking about this : https://github.com/SebastianM/angular-google-maps/blob/master/docs/content/guides/implement-auto-fit-bounds.md

With these feature, you can put juste put markers on the map and it will set the center and the zoom level automaticaly.

It's so awesome !

In agm-marker, in ngOnChange, if latitude or longitude change, they just emit new values on a subject

MaxBatt commented 4 years ago

Hi, I also would like to have the fit-bounds feature, meaning the zoom level is set automatically to see all available overlays. So this feature is not supported natively by agm-overlays? @JulienBourgain I don't quite understand how to use your solution with agm-overlays. Could you please explain in a little more detail?

Thanks!

d-silvas commented 4 years ago

There is a quick workaround in the line of what @JulienBourgain suggested: wrapping the agm-overlay component with a custom component that implements FitBoundsAccessor.

The custom component would look like:

import { FitBoundsAccessor, FitBoundsDetails } from '@agm/core';
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Component({
    selector: 'app-map-bounds',
    template: ` <ng-content></ng-content> `,
    providers: [{ provide: FitBoundsAccessor, useExisting: forwardRef(() => MapBoundsComponent) }],
})
export class MapBoundsComponent implements OnInit, FitBoundsAccessor {
    @Input() latitude: number;
    @Input() longitude: number;

    fitBoundsDetails$ = new BehaviorSubject<FitBoundsDetails>(null);

    getFitBoundsDetails$(): Observable<FitBoundsDetails> {
        return this.fitBoundsDetails$.asObservable();
    }

    ngOnInit() {
        const latLng: google.maps.LatLngLiteral = { lat: this.latitude, lng: this.longitude };
        this.fitBoundsDetails$.next({ latLng });
    }
}

And then you would use it to wrap markers in the template where you define the map:

<agm-map [fitBounds]="true" style="height:400px;">
    <app-map-bounds [agmFitBounds]="true" *ngFor="let marker of markers" [latitude]="marker.latitude" [longitude]="marker.longitude">
        <agm-overlay [latitude]="marker.latitude" [longitude]="marker.longitude">
            <! -- Your content... -->
        </agm-overlay>
    </app-map-bounds>
</agm-map>
egarkavy commented 3 years ago

@d-silvas you have just made my day So easy and so cool! One little thing is that I would change ngOnInit to ngOnChanges, this way you will react on every lat/lon change if marker is dynamic Also you can make component be OnPush

ricavir11 commented 2 years ago

You can just create a marker collection that is not visible.

<agm-map [fitBounds]="true" style="height:400px;">
        <agm-overlay [latitude]="marker.latitude" [longitude]="marker.longitude">
            <! -- Your content... -->
        </agm-overlay>
         <agm-marker[latitude]="marker.latitude" [longitude]="marker.longitude" [visible]="false" [agmFitBounds]="true">
            <! -- Your content... -->
        </agm-marker>
</agm-map>