mapsplugin / cordova-plugin-googlemaps

Google Maps plugin for Cordova
Apache License 2.0
1.66k stars 914 forks source link

Android (ionic) - cluster and marker icons do not display #2707

Closed alexisAvenel closed 4 years ago

alexisAvenel commented 4 years ago

Hello @wf9a5m75 !

I'm submitting a ... (check one with "x")

OS: (check one with "x")

cli packages: (versions/node/v10.9.0/lib/node_modules)

    @ionic/cli-utils  : 1.19.2
    ionic (Ionic CLI) : 3.20.0

global packages:

    cordova (Cordova CLI) : 9.0.0 (cordova-lib@9.0.1)

local packages:

    @ionic/app-scripts : 3.2.1
    Cordova Platforms  : android 8.1.0
    Ionic Framework    : ionic-angular 3.9.5

System:

    Android SDK Tools : 26.1.1
    ios-deploy        : 1.9.4
    ios-sim           : 8.0.0
    Node              : v10.9.0
    npm               : 6.7.0
    OS                : macOS
    Xcode             : Xcode 11.2.1 Build version 11B500
call-number 0.0.2 "Cordova Call Number Plugin"
com.bma4s.sdk.plugins.cordova 1.5.1 "BMA4S"
com.dwm.it.plugin.deeplink 1.0.0 "dwm plugin deeplink"
cordova-fabric-plugin 1.1.14-dev "cordova-fabric-plugin"
cordova-plugin-app-version 0.1.9 "AppVersion"
cordova-plugin-appavailability 0.4.2 "AppAvailability"
cordova-plugin-device 1.1.7 "Device"
cordova-plugin-facebook4 6.2.0 "Facebook Connect"
cordova-plugin-geolocation 4.0.1 "Geolocation"
cordova-plugin-google-analytics 1.8.3 "Google Universal Analytics Plugin"
cordova-plugin-googlemaps 2.7.0-20191107-1035 "cordova-plugin-googlemaps"
cordova-plugin-headercolor 1.0 "HeaderColor"
cordova-plugin-inappbrowser 3.0.0 "InAppBrowser"
cordova-plugin-ionic-keyboard 2.2.0 "cordova-plugin-ionic-keyboard"
cordova-plugin-ionic-webview 4.1.0 "cordova-plugin-ionic-webview"
cordova-plugin-market 1.2.0 "Market"
cordova-plugin-network-information 2.0.2 "Network Information"
cordova-plugin-request-location-accuracy 2.2.3 "Request Location Accuracy"
cordova-plugin-splashscreen 4.1.0 "Splashscreen"
cordova-plugin-statusbar 2.4.2 "StatusBar"
cordova-plugin-whitelist 1.3.3 "Whitelist"
cordova-plugin-x-socialsharing 5.4.1 "SocialSharing"
cordova.plugins.diagnostic 5.0.1 "Diagnostic"
es6-promise-plugin 4.2.2 "Promise"

The Git branch used is multiple_maps

Current behavior : I am using the cluster system but the cluster and markers icon in the cluster are not displayed. Only the default icon (red icon) is displayed. But I also add a marker to show the location of the geolocated user and this icon is displayed very well.

Screen capture or video record: screen screen2

Related code :

@IonicPage()
@Component({
    selector: 'page-map',
    templateUrl: 'map.html',
})
export class MapPage {
    @ViewChild('map') mapElement: ElementRef;
    @ViewChild('pageContent') pageContent: Content;

    public isVisible: boolean = false;
    public radius: number = 35;
    public offers: Offer[] = [];
    public selectedCards: Offer[] = [];
    public selectedCardInfo: SelectedCardInfo = {} as SelectedCardInfo;
    public map: GoogleMap;
    public userAddress: string = null;
    private _markers: MarkerOptions[] = [];
    private _cards: any;
    private _markerCluster: MarkerCluster;
    private _userMarker: Marker;

    constructor(public locationTracker: LocationTracker,
                private _navCtrl: NavController,
                private _modalCtrl: ModalController,
                private _cdr: ChangeDetectorRef,
                private _privateSalesBridge: PrivateSalesBridge,
                private _loaderService: LoaderService,
                private _keyboard: Keyboard,
                private _nativeKeyboard: NativeKeyboard,
                private _navParams: NavParams,
                private _platform: Platform,
                private _ga: GoogleAnalytics) {
    }

    ionViewWillEnter() {
        this._initMap();
    }

    public addUser() {
        if (this._userMarker) {
            this._userMarker.remove();
        }
        this.map.addMarker({
            icon: {
                url: this._getPathUrl() + 'assets/img/pin-user.png',
                size: {
                    width: 18,
                    height: 21
                }
            },
            position: {
                lat: this.locationTracker.positionInformation.position.lat,
                lng: this.locationTracker.positionInformation.position.lng
            }
        }).then(marker => {
            this._userMarker = marker;
        }).catch(e => {
            console.error('ERROR add marker', e);
        });
    }

    public addCluster(markers?: MarkerOptions[]) {
        if (this._markerCluster) {
            this._markerCluster.remove();
        }
        const finalMarkers = (markers && markers.length) ? markers : this._markers;
        console.log('finalMarkers', finalMarkers);
        this.map.addMarkerCluster({
            markers: finalMarkers,
            icons: [
                {
                    label: {color: "white"},
                    min: 2,
                    max: 100,
                    url: this._getPathUrl() + 'assets/img/circle-orange.png',
                    size: {width: 30, height: 30},
                    anchor: {x: 16, y: 16}
                }
            ]
        }).then((markerCluster) => {
            this._markerCluster = markerCluster;
            markerCluster.on(GoogleMapsEvent.MARKER_CLICK).subscribe((marker) => {
                this.showCard(marker[1].get('cardId'));
                this._ga.trackEvent(
                    'map',
                    'markerInfo',
                    'Afficher les infos sur l’offre'
                );
                this._cdr.detectChanges();
            });
            this._centerMapByMarkers(finalMarkers);
            this._loaderService.hide();
        }).catch(e => {
            this._loaderService.hide();
            console.error('ERROR addMarkerCluster', e);
        });
    }

    public findMe(e: Event) {
        this._loaderService.show();
        this.locationTracker.refreshMyPosition().then((value: PositionInformationInterface) => {
            this._refreshPosition();
            this._loaderService.hide();
        }).catch(e => {
            this._loaderService.hide();
        });
    }

    public searchByAddress() {
        this._keyboard.close();
        this._loaderService.show();
        this.locationTracker.refreshByAddress(this.userAddress).then(() => {
            this._refreshPosition();
            this._loaderService.hide();
        }).catch(e => {
            this._loaderService.hide();
        });
    }

    public centerMap() {
        this.map.animateCamera({
            target: this._userMarker.getPosition(),
            zoom: 12,
            duration: 1500
        });
    }

    public showCard(id) {
        this.isVisible = true;
        const selectedCard: Offer = this._cards.find(card => card.id === id);
        this.selectedCards = this._cards.filter((card: Offer) => card.shop.company.id === selectedCard.shop.company.id);
        this.selectedCardInfo = {
            label: selectedCard.shop.company.label || '',
            city: selectedCard.shop.address.city || '',
            score: selectedCard.shop.company.review.score || 0
        };
    }

    public close() {
        this.isVisible = false;
        this._cdr.detectChanges();
    }

    public goToCard(selectedCard: Offer) {
        this._navCtrl.push('CardDetailOfferPage', {id: selectedCard.id, offer: selectedCard});
    }

    private _centerMapByMarkers(markers: MarkerOptions[]) {
        const bounds: LatLng[] = markers.map(marker => {
            return new LatLng(marker.position.lat, marker.position.lng);
        });
        const latLngBounds = new LatLngBounds(bounds);

        const boundsTimeout = setTimeout(async () => {
            await this.map.animateCamera({
                target: latLngBounds,
                tilt: 0,
                duration: 1500
            });
            clearTimeout(boundsTimeout);
        }, 400);
    }

    private _refreshPosition(moveCamera: boolean = true) {
        this._userCity = this.locationTracker.userCity;
        this.userAddress = this.locationTracker.positionInformation.address;

        this.addUser();
        this._refreshMarkers();
        if (moveCamera) {
            const options = {
                target: this.locationTracker.positionInformation.position,
                zoom: 14
            };
            this.map.moveCamera(options);
        }
    }

    private _refreshMarkers() {
        const offersParams = {
            longitude: this.locationTracker.positionInformation.position.lng,
            latitude: this.locationTracker.positionInformation.position.lat
        };
        this._loaderService.show();
        this._getCards(offersParams).subscribe((cards: any[]) => {
            this._cards = cards;
            if (this._cards.length) {
                this._initMarkers().subscribe(res => {
                    this.addCluster();
                });
            } else {
                this._loaderService.hide();
            }
        });
    }

    private _initMap() {
        this._loaderService.show();
        this.userAddress = this.locationTracker.positionInformation.address;
        this._userCity = this.locationTracker.userCity;
        if (isUndefined(this.map)) {
            let element = this.mapElement.nativeElement;
            this.map = GoogleMaps.create(element, {
                controls: {
                    myLocationButton: false,
                    mapToolbar: false
                }
            });
            Environment.setBackgroundColor('#efebeb');
            this.map.one(GoogleMapsEvent.MAP_READY).then(() => {
                if (this._platform.is('ios')) {
                    document.body.style.transform = 'rotateZ(0deg)';
                }
                const offersParams = {
                    longitude: this.locationTracker.positionInformation.position.lng,
                    latitude: this.locationTracker.positionInformation.position.lat
                };
                this._getCards(offersParams)
                    .subscribe((cards: any[]) => {
                        this._cards = cards;
                        this.offers = cards;
                        if (this._cards.length) {
                            this._initMarkers().subscribe(res => {
                                this.addUser();
                                this.addCluster();
                            });
                        } else {
                            this._loaderService.hide();
                        }
                    });
            }).catch(e => {
                this._loaderService.hide();
                console.error('ERROR map one', e);
            });
        } else {
            this._loaderService.hide();
        }
    }

    private _getCards(offersParams?: {}): Observable<Offer[]> {
        return this._privateSalesBridge.getOffers(offersParams);
    }

    private _initMarkers(): Observable<boolean> {
        return new Observable(observer => {
            this._markers = [];
            if (this._cards && this._cards.length) {
                this._cards.forEach((card: Offer) => {
                    let marker: MarkerOptions = {} as MarkerOptions;
                    marker['cardId'] = card.id;
                    marker.visible = true;
                    if ((<Offer>card).addresses && (<Offer>card).addresses.length) {
                        marker.icon = {
                            url: this._getPathUrl() + 'assets/img/pin-offer.png',
                            size: {
                                width: 25,
                                height: 36
                            }
                        };
                        marker.position = {
                            lat: (<Offer>card).addresses[0].coordinates[0],
                            lng: (<Offer>card).addresses[0].coordinates[1]
                        };
                    }
                    if (marker.position) {
                        this._markers.push(marker);
                    }
                });
            }
            observer.next(true);
            observer.complete();
        });
    }

    private _getPathUrl(): string {
        return this._platform.is('ios') ? 'www/' : './';
    }
}

Best regards.

battika commented 4 years ago

I can see that you try to fetch your icons from the URL ./assets/img/circle-orange.png where ./ is your prefix for Android according to _getPathUrl() With one of the latest commits it no longer works for me this way either. I had to change it to http://localhost Not sure the reasoning behind it but it works for me. My current "prefixes" for each platform

ICONS_ROOT_ANDROID = 'http://localhost/assets/icons/';
ICONS_ROOT_IOS = 'www/assets/icons/';
ICONS_ROOT_BROWSER = 'assets/icons/';
services4smb commented 4 years ago

This is also reported here https://github.com/ionic-team/ionic-native-google-maps/issues/264

EinfachHans commented 4 years ago

Please try my Pull Request (https://github.com/mapsplugin/cordova-plugin-googlemaps/pull/2705) and review if it works for you

alexisAvenel commented 4 years ago

Thanks for reply @services4smb and @HansKrywaa I will test this today

alexisAvenel commented 4 years ago

Hello @HansKrywaa, I just tested your PR and it works perfectly for me ! (For testing his PR you have to add plugin like that : ionic cordova plugin add https://github.com/mapsplugin/cordova-plugin-googlemaps\#15280cb3c6b74eca0c23b85cc44e5562f26c8ca3 --variable PLAY_SERVICES_VERSION="16.0.0" --variable ANDROID_SUPPORT_V4_VERSION="27.+" --variable LOCATION_WHEN_IN_USE_DESCRIPTION="..." --variable LOCATION_ALWAYS_USAGE_DESCRIPTION="..." --save)

EinfachHans commented 4 years ago

My PR was merged. Can you check again and close this Issue when resolved?