はじめての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!!!
…と今日はここまで。さて、次回は何のネタで書こうかな。。。

