OutSystems+Google Maps API(1) 地図を埋め込む

ForgeにはGoogle Maps APIを使って作られたモジュールがあります。

しかし、機能が限られているし、カスタマイズ用ドキュメントもないみたいなので、自分でGoogle Maps APIを使って地図を埋め込む手順です。この手順に従えば、外部モジュールを使わずにGoogle Mapsの地図を埋め込むことができます。

シリーズ一覧

前提条件

Google Maps API用のキーは別途取得済みとします。

(実はキーなくても動くという記述もありますが、ドキュメントではキー利用おすすめとのことだったので使うことにします)

仕様

これから作っていくモジュールの仕様です。

実現する機能:OutSystemsのWeb ScreenにGoogle Mapsを埋め込み、地図上でクリックしたところに標準マーカーを立てる

地図は複数のScreenから利用されることが想定されるのでWeb Blockで実現することにします。

マーカーが多すぎと地図が見にくくなるので直近N点だけ持つことにして、Web Blockの入力パラメータとしてこのNを指定できるようにする。

また、APIキーはサイトプロパティにして一回設定すれば全画面で利用できるようにしましょう。

実装:Web Block

InterfaceレイヤのMainFlowを右クリックして、Add Web Blockしましょう。

ここでは私の屋号ハウスソフトをとって、HouseSoftMapと名付けました。

HouseSoftMapを右クリックしてAdd Input ParameterからMaxMarkerCountをInteger型で設定してあります。後でJavaScriptに引き渡して地図上に表示するマーカーの数を制限するのに使います(つまり地図出すだけならいらない)。

もう一つJavaScriptプロパティが非常に重要ですが、画面デザインのあとで説明します。

WebBlockプロパティ

画面デザインです。

WebBlockデザイン

配置したコンポーネントは以下の2つ。

Container: Google Mapsを表示するDIVタグになります。名前を「Map」とつけます。こうすることで、OutSystems中でMap.Idとすればhtmlのid属性を取得できます。Google Maps APIの地図オブジェクトのインスタンス化に必要です。また高さを指定しておかないとDIVタグに中身がないため地図が出ません。Min.Heightに適当な値を設定しておきます。450pxとしました。

Expression(Containerの下): Google Maps APIの地図オブジェクトをインスタンス化する関数を呼び出すJavaScriptコードとGoogle Maps API呼び出しリンクを埋め込みます。JavaScriptとして実行させるため、Escape ContentをNoにしておきましょう。

以下がコードです。Expression中ではOutSystemsの変数にアクセスできます。Map.Id, MaxMarkerCount, Site.APIKeyに注目。

DataレイヤのResourcesやWeb BlockのJavaScriptプロパティに入力したコードは静的JavaScriptです。OutSystemsの変数にアクセスする部分は静的JavaScriptから切り離す必要があります。そのため、このExpressionからWeb Blockの関数にパラメータを渡す実装にしています。

“<script type=’text/javascript’>
function initMap() {
houseSoftMap.createMap(‘” + Map.Id + “‘, ” + MaxMarkerCount + “);
}
</script>
<script src=’https://maps.googleapis.com/maps/api/js?key=” + Site.APIKey + “&amp;callback=initMap’ async defer></script>

Web BlockのJavaScriptには下記コードを入力します。Google Maps APIはJavaScriptのAPIなのでこれがメインの処理です。

createMap関数で地図をインスタンス化し、11行めでユーザが地図をクリックしたときの処理をインスタンス化した地図に紐づけています。

addMarkerはマーカーを受け取り内部の配列にため込み、MaxMarkerCountを上回ったら古い方から消していきます。最大でもMaxMarkerCountまでしかマーカーは表示されません。

var houseSoftMap = {
  mapObj : null,
  maxMarkerCount : 0,   // 地図に表示するマーカーの数。デフォルトではマーカー追加できないようにしておく
  markers : [],
  createMap : function (divId, maxMarkerCount) {
    this.mapObj = new google.maps.Map(document.getElementById(divId), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });
    this.maxMarkerCount = maxMarkerCount;
    this.mapObj.addListener("click", function(mouseEvent) {
      if (houseSoftMap.maxMarkerCount &amp;lt;= 0) return; // クリックした位置にマーカーを立てる 
        var marker = new google.maps.Marker({
          position: mouseEvent.latLng,
          map: houseSoftMap.mapObj 
        }); 
        houseSoftMap.addMarker(marker); 
      });
  }, 
  addMarker : function(marker) { 
    this.markers.push(marker); 
    // 直近のMaxMarkerCountポイントだけ持つ 
    while (this.markers.length > this.maxMarkerCount) {
      var firstMarker = this.markers.shift();
      firstMarker.setMap(null); // マーカーを地図から削除
    }
  }
}

実装:Web Block

適当にスキャフォールディングした画面に上で作ったHouseSoftMapを配置し、MaxMarkerCountを3にしておきます。

これでこの画面に地図が配置され、クリックするたびにマーカーが最大3つまで追加されます。

WebBlock配置 WebBlock配置先プロパティ

実装:サイトプロパティ

DataレイヤのSite Propertiesを右クリックして、Add Site Propertyを選択。

Data TypeがTextのAPIKeyプロパティを追加します。

Module Management(Service Studio上の歯車アイコン)を選択し、Site Popertiesから取得しておいたGoogle Maps APIキーを設定しておきます。

実装完了

パブリッシュすると動作確認もできました。

Google Maps APIの地図のスクリーンショットとっていいかどうかわからないので、画像は載せないでおきます。

でも、手順に従えばちゃんと出るはず。