dapriett / nativescript-google-maps-sdk

Cross Platform Google Maps SDK for Nativescript
MIT License
244 stars 164 forks source link

IndoorLevel are not visible the second time i open the page #403

Open RignonNoel opened 4 years ago

RignonNoel commented 4 years ago

My default page is a big Map created with nativescript-google-maps-sdk . When I first open my app I can see the IndoorLevel and IndoorBuilding but if I change my page and come back to the default I can't see anymore the IndoorLevel, however, it's still functional (zoom, translation, click on infoWindow, ..).

My map is used to visit IndoorLevel, so it's a big problem for me.

Any idea?


Example of code if it can help:

This app is used to show a list of artworks on specific level of building since GoogleMaps only use latitude and longitude and not the IndoorLevel

map.component.html

<ActionBar class="action-bar">
    <!--
    Use the NavigationButton as a side-drawer button in Android
    because ActionItems are shown on the right side of the ActionBar
    -->
    <NavigationButton ios:visibility="collapsed" icon="res://menu" (tap)="onDrawerButtonTap()"></NavigationButton>
    <!--
    Use the ActionItem for IOS with position set to left. Using the
    NavigationButton as a side-drawer button in iOS is not possible,
    because its function is to always navigate back in the application.
    -->
    <ActionItem icon="res://navigation/menu" android:visibility="collapsed" (tap)="onDrawerButtonTap()"
        ios.position="left">
    </ActionItem>
    <Label class="action-bar-title" text="Map"></Label>
</ActionBar>

<GridLayout>
    <MapView #mapView [latitude]="latitude" [longitude]="longitude"
             [zoom]="zoom" [minZoom]="minZoom" [maxZoom]="maxZoom" [bearing]="bearing"
             [tilt]="tilt" i-padding="50,50,50,50" [padding]="padding" (mapReady)="onMapReady($event)"
             (indoorBuildingFocused)="onIndoorBuildingFocused($event)"
             (indoorLevelActivated)="onIndoorLevelActivated($event)">
    </MapView>
</GridLayout>

map.component.ts

import { Component } from "@angular/core";
import { registerElement } from "nativescript-angular/element-registry";
import { MapView, Marker, Position, Style } from "nativescript-google-maps-sdk";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import * as app from "tns-core-modules/application";
import { Artwork } from "~/app/models/artwork";
import { ArtworksService } from "~/app/services/artworks.service";

declare const com: any;

// Important - must register MapView plugin in order to use in Angular templates
registerElement("MapView", () => MapView);

@Component({
    moduleId: module.id,
    selector: "map",
    templateUrl: "./map.component.html",
    styleUrls: ["./map.component.scss"]
})
export class MapComponent {

    latitude =  45.497748;
    longitude = -73.571746;
    zoom = 13;
    minZoom = 11;
    maxZoom = 22;
    bearing = 0;
    tilt = 0;
    padding = [20, 20, 20, 20];
    mapView: MapView;

    style = `
        [
          {
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#f5f5f5"
              }
            ]
          },
          {
            "elementType": "labels.icon",
            "stylers": [
              {
                "visibility": "off"
              }
            ]
          },
          {
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#616161"
              }
            ]
          },
          {
            "elementType": "labels.text.stroke",
            "stylers": [
              {
                "color": "#f5f5f5"
              }
            ]
          },
          {
            "featureType": "administrative",
            "elementType": "geometry",
            "stylers": [
              {
                "visibility": "off"
              }
            ]
          },
          {
            "featureType": "administrative.land_parcel",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#bdbdbd"
              }
            ]
          },
          {
            "featureType": "poi",
            "stylers": [
              {
                "visibility": "off"
              }
            ]
          },
          {
            "featureType": "poi",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#eeeeee"
              }
            ]
          },
          {
            "featureType": "poi",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#757575"
              }
            ]
          },
          {
            "featureType": "poi.park",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#e5e5e5"
              }
            ]
          },
          {
            "featureType": "poi.park",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#9e9e9e"
              }
            ]
          },
          {
            "featureType": "road",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#ffffff"
              }
            ]
          },
          {
            "featureType": "road",
            "elementType": "labels.icon",
            "stylers": [
              {
                "visibility": "off"
              }
            ]
          },
          {
            "featureType": "road.arterial",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#757575"
              }
            ]
          },
          {
            "featureType": "road.highway",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#dadada"
              }
            ]
          },
          {
            "featureType": "road.highway",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#616161"
              }
            ]
          },
          {
            "featureType": "road.local",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#9e9e9e"
              }
            ]
          },
          {
            "featureType": "transit",
            "stylers": [
              {
                "visibility": "off"
              }
            ]
          },
          {
            "featureType": "transit.line",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#e5e5e5"
              }
            ]
          },
          {
            "featureType": "transit.station",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#eeeeee"
              }
            ]
          },
          {
            "featureType": "water",
            "elementType": "geometry",
            "stylers": [
              {
                "color": "#c9c9c9"
              }
            ]
          },
          {
            "featureType": "water",
            "elementType": "labels.text.fill",
            "stylers": [
              {
                "color": "#9e9e9e"
              }
            ]
          }
        ]
    `;

    mapIsReady: boolean = false;
    currentLevelName: string;
    artworks: Array<Artwork>;
    displayedArtworks: Array<Artwork>;

    constructor(private artworksService: ArtworksService) {
        this.getArtworks();
    }

    onDrawerButtonTap(): void {
        const sideDrawer = <RadSideDrawer>app.getRootView();
        sideDrawer.showDrawer();
    }

    onMapReady(event) {
        this.mapView = event.object;
        this.mapView.settings.indoorLevelPickerEnabled = true;
        this.mapView.setStyle(<Style>JSON.parse(this.style));

        this.mapIsReady = true;
        if (this.artworks) {
            this.initMarkerOnMap();
        }
    }

    initMarkerOnMap() {
        this.mapView.removeAllMarkers();

        for (const artwork of this.displayedArtworks) {
            const marker = new Marker();
            marker.position = Position.positionFromLatLng(artwork.latitude, artwork.longitude);
            marker.title = artwork.name;
            marker.snippet = artwork.place.name;
            marker.userData = {index: 1};
            this.mapView.addMarker(marker);
        }
        console.log("Marker refreshed");
    }

    onIndoorBuildingFocused(args) {
        console.log("Building changed -> " + args.indoorBuilding);
        if (args.indoorBuilding) {
            this.currentLevelName = args.indoorBuilding.levels[args.indoorBuilding.defaultLevelIndex].name;
        } else {
            this.currentLevelName = null;
        }
        this.refreshDisplayedArtworks();
    }

    onIndoorLevelActivated(args) {
        console.log("Level changed -> " + args.activateLevel);
        if (args.activateLevel) {
            this.currentLevelName = args.activateLevel.name;
        } else {
            this.currentLevelName = null;
        }
        this.refreshDisplayedArtworks();
    }

    refreshDisplayedArtworks() {
        this.displayedArtworks = [];
        console.log("New displayed artwork -> " + this.currentLevelName);
        for (const artwork of this.artworks) {
            if (this.currentLevelName && this.currentLevelName && artwork.level === this.currentLevelName) {
                this.displayedArtworks.push(artwork);
            }
        }
        this.initMarkerOnMap();
    }

    getArtworks() {
        this.artworksService.list().subscribe(
            (artworks) => {
                this.artworks =  artworks.results.map(
                    (item) => new Artwork(item)
                );
                this.displayedArtworks = this.artworks;
                if (this.mapIsReady) {
                    this.refreshDisplayedArtworks();
                }
            }
        );
    }
}
dlcole commented 4 years ago

I saw something similar last year and concluded that mapReady was not firing when returning to the map page. I handled this by adding logic to onLoaded.

RignonNoel commented 4 years ago

@dlcole I tried putting something into onMapReady to see if it was firing the second time i load the page and it seems that this block was working great. But since i have really no more idea at this point i will investigate your onLoaded to check if i can fix it with it

fgutteridge commented 4 years ago

In my instance, I really only wanted the mapReady event to fire once, on initial load/ready, and never again... to do this, I removed the event listener via mapView.off('mapReady') and the end of my mapReady event handler. Not sure if this info is of any use to you, but it's here nonetheless!