StencilJS Google Maps component is not working with iOS

257 views Asked by At

I created my own custom Google Maps component using StencilJS to include in my Ionic project. The component works fine on android devices, however, it does not render on iOS devices. I cannot figure out the issue. I have tested it on both the iPhone emulator in xCode and on an actual iPhone device.

Below is the entire source code of my Stencil component:

import { Component, h, Prop, Host, Element, State, Watch, Event } from '@stencil/core';
import { EventEmitter } from '@stencil/core/internal';
import { Loader } from 'google-maps';

@Component({
  tag: 'ba-google-map',
  styleUrl: './google-map.component.css',
  shadow: true,
})
export class GoogleMap {
  @Element() el: HTMLElement;

  @Event() markerSelected: EventEmitter;

  @Prop({ attribute: 'api-key' }) apiKey: string;
  @Prop({ attribute: 'map-center-lat' }) centerLat: number = 35.9606;
  @Prop({ attribute: 'map-center-lon' }) centerLon: number = -83.9207;
  @Prop({ attribute: 'map-zoom' }) zoom: number = 8;
  @Prop({ attribute: 'map-pins' }) mapPins: Array<{
    lat: number;
    lng: number;
    contentString?: string;
    pinImgUrl?: string;
    id?: number;
  }>;
  @Prop({ attribute: 'map-height' }) height: string = '40px';
  @Prop({ attribute: 'map-disable-controls' }) disableControls: boolean = false;

  @State() google;
  @State() map: google.maps.Map;
  @State() markers: google.maps.Marker[];

  @Watch('mapPins')
  handleMapPinChange() {
    this.clearMarkers.call(this);
    this.addMarkers.call(this);
  }

  componentWillLoad() {
    this.initMap.call(this);
  }

  addMarkers() {
    let markersTmp = [];
    for (let pin of this.mapPins) {
      const markerConfigOpts: {
        position: object;
        map: google.maps.Map;
        icon?: string;
      } = {
        position: { lat: pin.lat, lng: pin.lng },
        map: this.map,
      };
      if (pin.pinImgUrl) {
        markerConfigOpts.icon = pin.pinImgUrl;
      }
      const marker = new this.google.maps.Marker(markerConfigOpts);

      if (pin.contentString) {
        const infoWin = new this.google.maps.InfoWindow({
          content: pin.contentString,
        });

        marker.addListener('click', () => {
          infoWin.open(this.map, marker);
          this.markerSelected.emit(pin);
        });
      }

      markersTmp.push(marker);
    }
    this.markers = markersTmp;
  }

  clearMarkers() {
    for (let i = 0; i < this.markers.length; i++) {
      this.markers[i].setMap(null);
    }

    this.markers = [];
  }

  async initMap() {
    if (!window['googleMapsLoader']) {
      window['googleMapsLoader'] = new Loader(this.apiKey);
    }

    this.google = await window['googleMapsLoader'].load();

    let mapConfigOpts: {
      center: object;
      zoom: number;
      zoomControl?: boolean;
      mapTypeControl?: boolean;
      scaleControl?: boolean;
      streetViewControl?: boolean;
      rotateControl?: boolean;
      fullscreenControl?: boolean;
    } = {
      center: { lat: this.centerLat, lng: this.centerLon },
      zoom: this.zoom,
    };
    if (this.disableControls) {
      mapConfigOpts.zoomControl = false;
      mapConfigOpts.mapTypeControl = false;
      mapConfigOpts.scaleControl = false;
      mapConfigOpts.streetViewControl = false;
      mapConfigOpts.rotateControl = false;
      mapConfigOpts.fullscreenControl = false;
    }
    this.map = new this.google.maps.Map(this.el.shadowRoot.querySelector('#map') as HTMLElement, mapConfigOpts);
    (this.el.shadowRoot.querySelector(`#map`) as HTMLElement).style.height = this.height;
    this.mapPins && this.addMarkers.call(this);
  }

  render() {
    return (
      <Host>
        <div id="map"></div>
      </Host>
    );
  }
}

Below is the CSS file for the component (if needed...there is not much here):

#map {
  width: 100%;
  background: #eee;
}
0

There are 0 answers