モバイル環境でのGoogleマップの表示

お世話になります。

こちらのページを参考に,住所ではなく緯度経度からGoogleマップを表示させたいと思っております。

(実際には緯度経度は別の.jsでgeolocationより取得しています)

そこで2つ問題が起きています。

・PC版だと(各APIにmobileを付けないものを用意しています),詳細画面で問題なくマップ表示されるのですが,モバイルだとマップが表示されません。

・また,PC版でもモバイル版でもイベントハンドラにapp.record.create.changeもしくはmobile.app.record.create.changeを指定していても,レコード新規登録画面で緯度経度が自動取得されているにも関わらず,マップが表示されません。→こちらはコンソールでも良く分かりませんでした。

 

モバイル環境において,Chromeの開発者ツールでコンソールを見ましたが,以下のコメントでした。

download.do?app=7&contentId=1057&jsType=MOBILE&hash=247f3724fa07a3998f634ddb3aef84e0ab463c65:44 Uncaught ReferenceError: google is not defined
at dysplayMap (download.do?app=7&contentId=1057&jsType=MOBILE&hash=247f3724fa07a3998f634ddb3aef84e0ab463c65:44)
at download.do?app=7&contentId=1057&jsType=MOBILE&hash=247f3724fa07a3998f634ddb3aef84e0ab463c65:38
at show.js:247
at Array.forEach (<anonymous>)
at w (show.js:923)
at gw (show.js:247)
at hw (show.js:247)
at cT (show.js:550)
at r8.e.D (show.js:1909)
at show.js:1067

そこで,コンソールのエラーメッセージをクリックしたところ,ここでエラーとなっておりました。
var point = new google.maps.LatLng(fy,fx);

この周辺を確認しましたが,何が悪いのか分からず,どなたかアドバイス頂けませんでしょうか。

以下に.jsを添付します。よろしくお願いいたします。

(function() {

    “use strict”;

    // Google Map の指定

    var script = document.createElement(‘script’);

    script.src = ‘[https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=\*\*\*\*\*](https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key= ***** )’;

    document.body.appendChild(script);

    // 詳細画面処理

    kintone.events.on([‘mobile.app.record.detail.show’,‘mobile.app.record.create.change’],

    function(event) {

        var record = event.record;

            if (!record[‘緯度’][‘value’] && !record[‘経度’][‘value’]) {

                return event;

            }

        var latY = record[‘緯度’][‘value’];

        var lngX = record[‘経度’][‘value’];

        var mapElement = kintone.mobile.app.record.getSpaceElement(‘map_latlng’);

        var mapElementDiv = document.createElement(‘div’);

        mapElementDiv.setAttribute(‘id’,   ‘map’);

        mapElementDiv.setAttribute(‘name’, ‘map’);

        mapElementDiv.setAttribute(‘style’, ‘width: auto; height: 150px;’);

        mapElement.appendChild(mapElementDiv);

        // マップの表示(経度、緯度、倍率)

        displayMap(lngX, latY, 18);

    });

    // Google Map の表示

    function displayMap(fx,fy,zoom){

        var point = new google.maps.LatLng(fy,fx);

        var opts = {

            zoom: zoom,

            center: point,

            mapTypeId: google.maps.MapTypeId.ROADMAP,

            scaleControl: true

        };

        var map = new google.maps.Map(document.getElementById(‘map’), opts);

        var marker = new google.maps.Marker({

            position: point,

            map: map

        });

    }

})();

Nami SATO さん

はじめまして。ひよこです。

①モバイルで地図が表示されない

google というグローバルオブジェクトが存在してないというエラーです。
// Google Map の指定 の3行でDOMに追加したスクリプトタグが実行されたときに、google というオブジェクトをグローバルに追加されます。

cybozu developer network にお手本となる記事 https://developer.cybozu.io/hc/ja/articles/202179174 があり、
これを見てみると、どうやら追加には待ち時間が発生するみたいです。
たまたまモバイルのときは追加される前に displayMap 関数が実行されているので
google というグローバルオブジェクトがないというエラーになっているんだと思います。

なので対処としては、google オブジェクトが存在するか?を確認して存在したら、実行するという処理をしてあげる必要があります。

お手本となる記事 https://developer.cybozu.io/hc/ja/articles/202179174 を参考にしてみてください。
待つ処理の部分は、waitLoaded という関数です。

 

②change イベントが発火しない

change イベントの指定の仕方が違うためと思われます。

https://developer.cybozu.io/hc/ja/articles/201941984#step3 を見ると

app.record.create.change.< フィールドコード>

となっています。このイベントは、あるフィールドに対して変更が起きたら発火するイベントなので、
変更を検知したいフィールドのフィールドコードを指定します。
たとえば、緯度というフィールドの場合、nami さんの設定だと「緯度」というフィールドコードになっているので、
「app.record.create.change.緯度 です。モバイルの場合も同様です。

ひよこ様

初めまして,コメントありがとうございます!

 

①について:

朝から四苦八苦しており,ようやく所望の動作にはなったものの,きちんとGoogle mapのオブジェクト有無を確認してから進んでいるのか,たまたま動作しているのかが分かりません・・・。

宜しければ,(一応)動作したコードを見て頂けませんでしょうか?

以下に記載します。

 

(function() {

    “use strict”;

    // Google Map の指定

    var script = document.createElement(‘script’);

    script.src = ‘https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=***’;

    document.body.appendChild(script);

   

    // レコード新規登録(フィールド書き換え)および詳細表示時

    function drawmap(event) {

        waitLoaded(event, 10000, 100);

    };

    // Google Maps APIがロードされるまで待機してから表示処理へ移行

    function waitLoaded(event, timeout, interval) {

         setTimeout(function() {

            timeout -= interval;

        if (

            typeof google !== ‘undefined’ &&

            typeof google.maps !== ‘undefined’ &&

            typeof google.maps.version !== ‘undefined’

        ) {   

            var record = event.record;

            if (!record[‘緯度’][‘value’] && !record[‘経度’][‘value’]) {

              return event;

            }

            var latY = record[‘緯度’][‘value’];

            var lngX = record[‘経度’][‘value’];

            var mapElement = kintone.mobile.app.record.getSpaceElement(‘map_latlng’);

            var mapElementDiv = document.createElement(‘div’);

            mapElementDiv.setAttribute(‘id’,   ‘map’);

            mapElementDiv.setAttribute(‘name’, ‘map’);

            mapElementDiv.setAttribute(‘style’, ‘width: auto; height: 150px;’);

            mapElement.appendChild(mapElementDiv);

        

            displayMap(lngX, latY, 18);

    }   else if (timeout > 0) {

        // ロードされるまで繰り返す

        waitLoaded(event, timeout, interval);

        }

    }, interval);

}

    // Google Map の表示処理

    function displayMap(fx,fy,zoom){

        var point = new google.maps.LatLng(fy,fx);

        var opts = {

            zoom: zoom,

            center: point,

            mapTypeId: google.maps.MapTypeId.ROADMAP,

            scaleControl: true,

        };

        var map = new google.maps.Map(document.getElementById(‘map’), opts);

        var marker = new google.maps.Marker({

            position: point,

            map: map,

        });

    }

    // 各種イベントハンドラの定義

    kintone.events.on([‘mobile.app.record.detail.show’,‘mobile.app.record.create.change.経度’], drawmap);

})();

 

 

②について

 

アドバイス頂いた内容で発火させることができました。

しかし,正しくは緯度経度の両方が変更になった時点で発火させたいのですが,非同期処理の場合は緯度と経度のどちらが先に変更が掛かるか分からないと思っております。

とりあえず経度の変更で発火させるとうまくいく(緯度から先に読んでるようで,緯度で発火させると経度が入っていないというエラーが出る)のですが,これも環境によって変わるのでしょうか?

その場合,緯度と経度を両方で発火させるようにイベントハンドラを指定するやり方は,強引でしょうか?(かならずどちらかでエラーが起きると思うので・・・)