Search code examples
angulartypescriptionic3baidubaidu-map

Ionic 3: Baidu map working only in browser


In an app I'm developing with Ionic 3, I'm using the npm package angular2-baidu-map for showing maps of China mainland.

I have got an API key for Baidu Maps (for the JS API), and the map is working fine in a browser (i.e. ionic serve -l), but once compiled and installed on a real device, the map isn't showing up.

After doing some debugging, it turns out that the API sends requests to file://api.map.baidu.com, no matter what I set in the protocol map init option.

For instance, the Safari developer tools' console logs some a lot of messages like:

The requested URL was not found on this server. file://api.map.baidu.com/api?v=2.0&ak=...&callback=baidumapinit&s=0 Failed to load resource: The requested URL was not found on this server.

Edit: added code

Basically I just tried this plugin with the demo code. But, for the sake of completeness, here it is.

HTML code

<ion-header>
  <ion-navbar>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Baidu map</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
<baidu-map ak="{{ak}}"
     [options]="opts" [offline]="offlineOpts" 
     (onMapLoaded)="loadMap($event)" 
     (onMarkerClicked)="clickMarker($event)" 
     (onClicked)="clickMap($event)"></baidu-map>
</ion-content>

Typescript

map-baidu.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { MapBaiduPage } from './map-baidu';
import { TranslateModule } from '@ngx-translate/core';
import { BaiduMapModule } from 'angular2-baidu-map';

@NgModule({
  declarations: [
    MapBaiduPage,
  ],
  imports: [
    IonicPageModule.forChild(MapBaiduPage),
    TranslateModule.forChild(),
    BaiduMapModule
  ],
})
export class MapBaiduPageModule {}

map-baidu.ts

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { OfflineOptions, ControlAnchor, NavigationControlType } from 'angular2-baidu-map';

@IonicPage()
@Component({
  selector: 'page-map-baidu',
  templateUrl: 'map-baidu.html',
})
export class MapBaiduPage {

  public ak:string = '<your Baidu JS API key here>';
  opts: any;
  offlineOpts: OfflineOptions;

  constructor(public navCtrl: NavController, public navParams: NavParams) { }

  ionViewDidLoad() {
    console.log('ionViewDidLoad MapBaiduPage');
  }

  loadMap(map:any){
    console.log('> loadMap:', map);
  }
  clickMap(e:any){
    console.log('> clickMap:', e.point.lat, e.point.lng);
  }

  clickMarker(marker:any){
    console.log('> clickMarker:', marker);
  }

  ngOnInit() {
    this.opts = {
      // protocol:'https:', // changes nothing
      center: {
        longitude: 121.506191,
        latitude: 31.245554
      },
      zoom: 12,
      markers: [{
        longitude: 121.506191,
        latitude: 31.245554,
        title: 'Where',
        content: 'Put description here',
        enableDragging: true
      }],
      geolocationCtrl: {
        anchor: ControlAnchor.BMAP_ANCHOR_BOTTOM_RIGHT
      },
      scaleCtrl: {
        anchor: ControlAnchor.BMAP_ANCHOR_BOTTOM_LEFT
      },
      overviewCtrl: {
        isOpen: true
      },
      navCtrl: {
        type: NavigationControlType.BMAP_NAVIGATION_CONTROL_LARGE
      }
    };

    this.offlineOpts = {
      retryInterval: 5000,
      txt: "Network unavailable"
    };
  }
}

Any idea?


Solution

  • Ok I had a look at the sourcecode and this is how the component decides which protocol to use:

    export var loader = function (ak, offlineOpts, callback, protocol) {
      var realProtocol = protocol || location.protocol;
    

    So if no protocol is passed it is using the protocol from where your page is served (in case of ionic this is file:// or in case of WKWebview localhost://).

    Now you said in your question you tried passing a different protocol but looking at your code you passed it as property of the opts object. But if you have a look at the BaiduMap Component it expects the protocol as an separate @Input:

    export class BaiduMap implements OnInit, OnChanges {
      @Input() ak: string;
      @Input() protocol: string;
      @Input() options: MapOptions;
    

    So you need to change your component template as follows:

    <baidu-map ak="{{ak}}"
      [options]="opts" 
      [offline]="offlineOpts" 
      [protocol]="'https'" // not sure about the extra quotation marks
      (onMapLoaded)="loadMap($event)" 
      (onMarkerClicked)="clickMarker($event)" 
      (onClicked)="clickMap($event)">
    </baidu-map>