phonegap-googlemaps-pluginでマップ上の要素にアクセスする方法
phonegap-googlemaps-pluginを利用してマップを表示した際に、地図上に配置したコントロールが反応しなくて困ったことがあります。
ボタンや検索ボックスを配置するならマップ表示を指定したDiv内にコントロールを配置すればいいというのはすぐに分かりましたが、サイドメニューやモーダルのポップアップ画面を表示した際にはどうすればいいのか分かりませんでした。
最初はマップ表示したDiv内に全画面の背景Divを用意して、サイドメニューが表示されたタイミングで背景Divを一緒に表示してzindexをいじったりとかしていましたが、最終的にはそんな面倒なことはしなくてもいいということに気が付きました。
しかも、その方法はGitのWikiにちゃんと載っていて結果的にずいぶん遠回りしてしまったので、初めてのフレームワークやプラグインを使う場合、まず最初は公式のガイドに目を通すべきですね。
以下、その方法です。
コード
詳しくはこちら(Map · mapsplugin/cordova-plugin-googlemaps Wiki · GitHub)を参照。
上記リンク先の「map.setClickable()」と書かれている項目が今回の対象で、実際のコードは以下の通り。
var map;
// マップ生成
document.addEventListener("deviceready", function() {
var mapDiv = document.getElementById("map_canvas");
map = plugin.google.maps.Map.getMap(mapDiv);
map.on(plugin.google.maps.event.MAP_READY, onMapInit);
});
// マップ初期化
function onMapInit(map) {
}
// サイドメニューを開く
function openMenu(){
map.setClickable(false);
}
// サイドメニュー閉じる
function closeMenu(){
map.setClickable(true);
}
「setClickable」で”false”を設定すると、マップ上に表示されたサイドメニューが反応するようになります。設定しない場合は、後ろに表示されているはずのマップが反応してサイドメニューを表示してもメニューが選択できません。
ionicフレームワークのモーダル画面の表示を切り替える場合
上記の対応で問題は解決したと思っていましたが、ionicフレームワークのmodal機能を使っていて問題が発生。
以下は、ionicフレームワークのサイドメニューテンプレートを利用して自動で作成されたログイン用のモーダル画面コードに「setClickable」を追加したものになります。
// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope
}).then(function (modal) {
$scope.modalLogin = modal;
});
// Triggered in the login modal to close it
$scope.closeLogin = function () {
map.setClickable(true);
$scope.modalLogin.hide();
};
// Open the login modal
$scope.login = function () {
map.setClickable(false);
$scope.modalLogin.show();
};
このコードで問題となるのは、閉じるボタンからの処理ではきちんと処理されますが、スマホの戻るボタンや表示されたモーダル画面の外側をタップして画面が消された場合に、マップが操作できない状態のままになってしまうことです。
解決方法は以下の通り。
// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/modal.html', {
scope: $scope
}).then(function (modal) {
$scope.modalLogin = modal;
});
// Triggered in the login modal to close it
$scope.closeLogin = function () {
$scope.modalLogin.hide();
};
// Open the login modal
$scope.login = function () {
map.setClickable(false);
$scope.modalLogin.show();
};
// Execute action on hide modal
$scope.$on('modal.hidden', function () {
map.setClickable(true);
});
20~22行目の処理で「modal.hidden」イベントが発生した際に「map.setClickable(true)」でマップを操作できる状態に戻しています。これはモーダル画面が閉じられた際に実行されるので、「closeLogin」メソッドでの「map.setClickable(true)」は不要となります。
なお、これについてもionic公式のガイドに方法が載っているので、本当に事前にちゃんと確認しないと余計時間がかかりますね。