はじめてのGoogle Maps API のつづき
コンチはー!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して、 上のサンプルコードを実際にパブリッシュしたものがこちら。(キャプチャ画像です)
まだまだ続きます。次は、さきほどちょろっと触れた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!!!
…と今日はここまで。さて、次回は何のネタで書こうかな。。。