2013-10-06

Google Maps API: カスタムオーバーレイ

サンプル
応用例

変更履歴:
・慣例に則って、コンストラクタ名の最初の文字を大文字にした。(2015-11-08)
・メインのコードをhtmlファイルに記載した。(2015-11-08)
・デフォルト値の設定の仕方を変更した。(2015-11-08)
・コンストラクタ内では、.setMap()は実行しないようにした。メインのプログラムで実行するようにした。(2015-11-08)

◆html

7行目: Maps API JavaScript を読み込む。APIキーの取得は〔リンク〕を参照。
71行目:地図を表示するdiv要素を定義する。
28行目以降:マーカーをオーバーレイする(Google Maps API提供のオーバーレイ)。
40行目以降:htmlをオーバーレイする(カスタムオーバーレイ)。ここではキャプションと画像。
46行目:GMOverlayHtml を用いてマーカーと同様にオブジェクトを作成しています。
54行目:カスタムオーバーレイを表示。
58行目:カスタムオーバーレイを非表示。

尚、[1]のように.show(), .hide()を用いて表示、非表示することもできるが、この場合、.onAdd()が呼ばれるタイミングとの関係でうまく動作しない場合があったため、このような方法とした。

<!DOCTYPE html>
<html lang="ja">

<head>
<title>GoogleMapOverlay</title>
<link rel="stylesheet" href="GoogleMapOverlay.css">
<script src="http://maps.googleapis.com/maps/api/js?key=********"></script>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="GMOverlayHtml-2.0.js"></script>

<script>

$(function() {

 var map;

// Google Map を描画
 var myLat = 51.507136;
 var myLng = -0.076421;
 var point = new google.maps.LatLng(myLat,myLng); //中央の座標を定義
 var myOptions = {
     zoom: 5, //ズームを定義
        center: point,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
  map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);

// Marker を overlay
 var image = new google.maps.MarkerImage('images/place.png',
     new google.maps.Size(16, 16),
       new google.maps.Point(0,0),
       new google.maps.Point(8, 8)
 );
 var marker = new google.maps.Marker({
     position: point,
        map: map,
  icon: image
    });

// html を overlay(カスタムオーバーレイ)
 var content = '<div style="background-color:darkgray; border: solid 1px;">';
  content += '<p>London</p>';
  content += '<img src="images/001.jpg"></div>';
 var offsetX = 10;
 var offsetY = 10;
 var overlayHtml = new GMOverlayHtml({
  position: marker.getPosition(), 
  content: content, 
  offsetX: offsetX, 
  offsetY: offsetY
 });

   google.maps.event.addListener(marker, 'mouseover', function() {
     overlayHtml.setMap(map);
   });

   google.maps.event.addListener(marker, 'mouseout', function() {
    overlayHtml.setMap(null);
   });

});

</script>

</head>


<body>
 <div id="header">Sample</div>
 <hr>
 <div id="map_canvas"></div> 
</body>
                   
</html>

◆コンストラクタ GMOverlayHtml (GMOverlayHtml-2.0.js)

1行目以降:コンストラクタ GMOverlayHtml を定義。新しいオブジェクトのプロパティとして渡されたパラメータを初期化します。このとき、optsに入力がなければデフォルト値が使われます。
20行目:OverlayView を明示的に GMOverlayHtml のサブクラスとして指定します。これは、新しいクラスの prototype を親クラスのインスタンスに設定することで実現します。
22行目以降:プロトタイプの中に onAdd() メソッドを実装し、オーバーレイを地図に貼り込みます。地図でオーバーレイの貼付が可能になると OverlayView.onAdd() が呼び出されます。
39行目以降:プロトタイプ中に draw() メソッドを実装し、オブジェクトの表示を制御します。オブジェクトが最初に表示されたとき、OverlayView.draw() が呼び出されます。
48行目以降:オーバーレイの中に追加した要素を消去するための onRemove() メソッドも実装する必要があります。このメソッドは、オーバーレイの map プロパティを null に設定すると、API が自動的に呼び出します。
以上は参考文献[1]に従っています。

var GMOverlayHtml = function(opts) {
 var defaults = {
  offsetX: 0,        // デフォルト値
  offsetY: 0,        // デフォルト値
  position: null,    // 入力値
  content: null,     // 入力値
 }
 for ( var key in defaults ) {
  if (defaults[key] == null) {
   this[key] = opts[key];
  } else {
   this[key] = defaults[key];
   if (opts[key]) this[key] = opts[key];
  }
 }
}

//  以下は、https://developers.google.com/maps/documentation/javascript/customoverlays に従って記載。

GMOverlayHtml.prototype = new google.maps.OverlayView();

GMOverlayHtml.prototype.onAdd = function() {
        // 何度も呼ばれる可能性があるので、divが未設定の場合のみ要素生成
        if (!this.div) {
          // 出力したい要素生成
          this.div = document.createElement( "div" );
          this.div.style.position = "absolute";
       this.div.style.border = '0px none';
       this.div.style.overflow = 'hidden';
       this.div.style.visibility = this.visibility_;
          this.div.innerHTML = this.content;
          // 要素を追加する子を取得
          var panes = this.getPanes();
          // 要素追加
          panes.overlayImage.appendChild( this.div ); // overlayImage: marker の foreground を含む pane
        }
}

GMOverlayHtml.prototype.draw = function() {
        // 緯度、軽度の情報を、Pixel(google.maps.Point)に変換
        var point = this.getProjection().fromLatLngToDivPixel(this.position);
        // 取得したPixel情報の座標に、要素の位置を設定
        // 座標の位置を左上の座標とする位置に要素が設定される
        this.div.style.left = point.x + this.offsetX + 'px';
        this.div.style.top = point.y + this.offsetY + 'px';
}

GMOverlayHtml.prototype.onRemove = function() {
  if (this.div) {
    this.div.parentNode.removeChild(this.div);
    this.div = null;
  }
}

◆css

* {
 margin: 0;
 padding: 0;
}

html, body {
  height: 100%;
}

body {
 overflow: hidden;
 background-color: ivory; 
}

#header {
 height: 5%;
 font: bold 32px arial,sans-serif;
 color: blue;
    margin: 5px;
} 

#map_canvas {
 height: 90%;
}


References





以上