コンチはー!kijimaです。

前回の「はじめてのgoogleMapsAPI」に引き続き、今回もgoogle Maps APIネタでまいります。前回は地図を表示して、マウスクリックに対してMapMouseEventを定義してあげて座標を取得し、初期座標を設定するところまでやりました。

今回はcom.google.maps.overlaysのMarkerクラスを使って、ピンのような印を地図上にたくさん表示させたいと思います。

今回は全体のソースコードを見てみましょう。ドキュメントクラスです。

 

package {	
	import flash.display.Sprite;
	import flash.geom.Point;

	import com.google.maps.*;
	import com.google.maps.controls.*;
	import com.google.maps.overlays.*;

	public class MapSample extends Sprite {
		
		private var _map:Map;
		private var _positionControl:PositionControl;
		private var _typeControl:MapTypeControl;
		private var _zoomControl:ZoomControl;
		
		public function MapSample(){
			createMap();
		}
		
		private function createMap():void {
			_map = new Map();
			_map.key = ""//ローカル確認時はAPIキーが必要ありません。
			_map.language = "ja";
			_map.setSize(new Point(stage.stageWidth, stage.stageHeight));

			var positionControl:PositionControl = new PositionControl();
			var typeControl:MapTypeControl = new MapTypeControl();
			var zoomControl:ZoomControl = new ZoomControl();
			
			_map.addControl(positionControl);
			_map.addControl(typeControl);
			_map.addControl(zoomControl);
			
			addChild(_map);
			
			_map.addEventListener(MapEvent.MAP_READY, onMapReady);
		}
		
		private function onMapReady(e:MapEvent):void {
			_map.removeEventListener(MapEvent.MAP_READY, onMapReady);
						
			_map.setCenter( new LatLng( 35.6346365773433, 139.74446296691895 ), 18, MapType.SATELLITE_MAP_TYPE);

			var marker1_pos:LatLng = new LatLng(35.634697616253376, 139.74440395832062);
			var marker1:Marker = new Marker(marker1_pos);

			var marker2_pos:LatLng = new LatLng(35.634697616253376, 139.74452197551727);
			var marker2:Marker = new Marker(marker2_pos);
			
			_map.addOverlay(marker1);
			_map.addOverlay(marker2);

		}
	}
}

 

とりあえず上からコードを見ていってポイントだけ解説。

import com.google.maps.overlays.*;

7行目。今回の主役であるMarkerクラスを使うために、google.maps.overlays.*内のクラスをインポートします。アスタリスクでごそっとインポートしてます。

 

var marker1:Marker = new Marker(marker1_pos)

45行目でMarkerクラスをnewしていますが、コンストラクタの引数で渡しているのは、44行目で定義したLatLng型のパラメータ、すなわちピンを置く位置の座標です。

第二引数でピンのいろんな設定を司る(この言い回しが個人的に好き)MarkerOptionsを渡すと、ピンの見た目にカスタムアイコンを設定できたり(icon)、クリックできるかどうか(clickable)、ドラッグできるかどうか(draggable)とか、いろいろ設定できます。

このMarkerOptions、後ほど使うので頭の隅で覚えておきつつ、とにかくまずは地図上にピンを表示させてみましょう。

_map.addOverlay(marker1);

50行目。45行目でnewしたmarker1を_mapにaddOverlayします。addChildするのと同じ感覚で。

同じようにmarker2をaddOverlayして、 上のサンプルコードを実際にパブリッシュしたものがこちら。(キャプチャ画像です)

 

MapSample01_.jpg

 

まだまだ続きます。次は、さきほどちょろっと触れたMarkerOptionsを使ってピンの見た目を変えてみます。見た目を変えるには、MarkerOptionsのプロパティ、iconにDisplayObjectを設定します。

 

			var opt:MarkerOptions = new MarkerOptions( {
				
				//flaファイルのライブラリ内に「Bubble」リンケージ設定をしたMovieClipがある前提で。
				
				icon:new Bubble(),//カスタムアイコンを設定
				clickable:false,//クリック可能かどうか。初期値はtrue
				draggable:true//ドラッグ可能かどうか。初期値はfalse
			} );
			var marker1:Marker = new Marker(marker1_pos, opt);//第二引数にMarkerOptionsを渡す

続いて、地図上をクリックした位置に、上で表示させたカスタムアイコンのピンを置くようにコードを変えていきましょう。

onMapReadyメソッド内に、マウスイベントを監視するリスナーと、クリックした位置にピンを生成するonMapClickメソッドを追加します。

_map.addEventListener(MapMouseEvent.CLICK, onMapClick);// リスナー追加。

 

 

		private function onMapClick(e:MapMouseEvent):void {
			//e.LatLng = MapMouseEvent が発生した地点の LatLng。
			trace("緯度=", e.latLng.lat(), "経度=", e.latLng.lng() );
			
			var marker:Marker = new Marker(e.latLng, new MarkerOptions( {icon:new Bubble(), draggable:true} ) );
			_map.addOverlay(marker);
			
		}

ここまで追加したものが、下のFlash。地図上をクリックすると、ピンが量産されていくと思います。

 

最新版のAdobe FlashPlayerをインストールしてください。

 

ここで複数のピンを生成していると気づくと思いますが、ピンに対してマウスオーバーしたときに、重なり順が強制的に最前面に来てしまいます。

この挙動を防ぐために、まず疑ったのはMarkerOptionsのプロパティ、clickable(クリック可能かどうか)。しかし、設定してみてもなにも変わらず。。。

ここでかなりの時間はまったんですが、結論としては、Markerクラスまわりで設定するのではなく、MapクラスのoverlayRaisingというプロパティを設定することで解決できました。(涙)

_map.overlayRaising = false;

 

ただ、確実に地図が表示された後で設定しないとエラーになってしまうので、onMapReadyメソッド内に記述します。この設定をしたら、マウスオーバーしてもピンが最前面に来ないようになりました。

 

最新版のAdobe FlashPlayerをインストールしてください。

 

あとは、地図上で表示したピンを経度でソートすれば完璧ですね。なぜソートする必要があるかというと、地図上で北に位置するピンが、南にあるピンより前のレイヤーに表示されてしまい、奥行き感がなんだか変になってしまうからです。

 ピンを置くたびにソートを実行して、重なり順を補正するためにこんな感じにコードを改修しました。

 

		private var sortArr:Array = [];//ソートに使う配列。中にマーカーとlatパラメータを入れて使う
		private function onMapClick(e:MapMouseEvent):void {
			var marker:Marker = new Marker(e.latLng, new MarkerOptions( {icon:new Bubble(), draggable:true} ) );
			_map.addOverlay(marker);
			
			sortArr.push({ marker:marker, lat:e.latLng.lat() });//マーカーと経度を含むオブジェクトを配列に追加する
			
			sortLng();
		}
		
		private function sortLng():void {
			//一旦マーカーを地図上から削除して、ソート。
			for (var i:int = 0; i < sortArr.length; i++) {
				_map.removeOverlay(sortArr[i].marker);
				sortArr.sortOn("lat", Array.DESCENDING | Array.NUMERIC);//ソート方法についてはArrayクラスを調べてください(笑)
			}
			//ソートした順番にaddOverlayする
			for (i = 0; i < sortArr.length; i++) {
				_map.addOverlay(sortArr[i].marker);
			}
		}

(ちなみに、配列のソートに関してはflabakaさんが最近書かれた記事でも解説されています。なるほど!)

そしたらそしたら、下のように表示されました。クリックするたびにソートし直す必要はあまりありませんが、地図の初期表示時に複数のピンを置きたい場合、このソート処理を挟んでおくことで、見た目上の違和感がなくなりますね。

 

最新版のAdobe FlashPlayerをインストールしてください。

 

最後だけフキダシの形を変えてみました。OZ!!!

…と今日はここまで。さて、次回は何のネタで書こうかな。。。

HTML5飯