Google Map API version 3 Overlay Example

※以前別の場所で書いた文章を備忘的に書き記しておきます。

【投稿年月日】2009-11-13 【ジャンル】JavaScript

 最近、Google Map APIを活用することが多いのですが、最新版のversion 3(v3)に関する日本語の情報が少ないので結構苦労しています。
 v3を使用した実感としては、version 2と比較して、地図の描画速度が速いです。ただし、私の記述方法がダメダメなためか、大量のMarker(マーカー)を使うと遅くなってしまいます。

 と言うことで、Markerと同様に使え、描画速度が速いような気がするOverlay(オーバーレイ)を活用することにしました。以下、簡単なサンプル。

Google Maps API v3 Example: Overlay1
tika.tisoku.net/overlay/?id=1

 地図を読む込むたびに、10個のOverlayを、その地点の緯度経度と共にランダムに表示させるようにしています。
 ポイントは「AddOverlay.prototype = new google.maps.OverlayView()」のように記述することでしょうか。Javascriptに詳しくないので、正直なところ、馴染めない書き方ですが。。
 「AddOverlay.prototype.draw」以下の記述により、地図を読み込んだとき、OverlayをDOMとして表示させることが可能になります。

【ソース】 Google Maps API v3 Example: Overlay1

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Google Maps API version3 Example: Overlay1</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
 var map = null;
 function initialize() {
  var myLatlng = new google.maps.LatLng(35.472324, 133.05052);
  var myOptions = {
   zoom: 10,
   center: myLatlng,
   mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 
  AddOverlayData();
 }
 function AddOverlayData() {
  var northEast = map.getCenter();
  northEast = new google.maps.LatLng(northEast.lat()+0.5, northEast.lng()+1);
  var southWest = new google.maps.LatLng(northEast.lat()-1, northEast.lng()-2);
  map.fitBounds(new google.maps.LatLngBounds(southWest, northEast));
  var lngSpan = northEast.lng() - southWest.lng();
  var latSpan = northEast.lat() - southWest.lat();
  for(var i=0; i<10; i++) {
   new AddOverlay(i, southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random());
  }
 }
 function AddOverlay(id, lat, lng) {
  this.id_ = id;
  this.lat_ = MathRound(lat);
  this.lng_ = MathRound(lng);
  this.setMap(map);
 }
 AddOverlay.prototype = new google.maps.OverlayView();
 AddOverlay.prototype.draw = function() {
  if(!this.div_) {
   this.div_ = document.createElement("div");
  }
  var div = this.div_;
  var panes = this.getPanes();
  panes.overlayLayer.appendChild(div);
  var latlng = new google.maps.LatLng(this.lat_, this.lng_);
  var point = this.getProjection().fromLatLngToDivPixel(latlng);
  div.title = "Point" + this.id_;
  div.style.position = "absolute";
  div.style.left = point.x + "px";
  div.style.top = point.y + "px";
  div.style.fontSize = "10px";
  div.style.width = "60px";
  div.style.lineHeight = "1em";
  div.style.border = "1px solid #666";
  div.style.background = "#fffffe";
  div.innerHTML = "<strong>Point" + this.id_ + "</strong><br />" + this.lat_ + "<br />" + this.lng_;
 };
 function MathRound(id) {
  var s = 10000;
  return Math.round(id*s)/s;
 }
 function addEvent(obj, evType, fn) {
  if(obj.addEventListener) {
   obj.addEventListener(evType, fn, false);
  }else if(obj.attachEvent) {
   obj.attachEvent("on" + evType, fn);
  }
 }
 addEvent(window, "load", initialize);
</script>
</head>
<body>
<h1>Google Maps API v3 Example: Overlay1</h1>
<div id="map_canvas" style="width:600px; height:350px;"></div>
</body>
</html>



 続いては、地図をDrag(ドラッグ)するたびに、10個のOverlayをランダムに変化させるサンプル。

Google Maps API v3 Example: Overlay2
tika.tisoku.net/overlay/?id=2

 最初のサンプルと大きく異なる点は、「AddOverlay.prototype.remove」と「function ClearOverlay()」が加わったことです。
 また、「function initialize()」内の「google.maps.event.addListener(map, "dragstart", function() {}」により、地図をDragするたびにイベントを発生させることが可能になります。
 各Overlayは、地図をDragするたびに、「AddOverlay.prototype.remove」内のmap.setMap(null)等で消します。

【ソース】 Google Maps API v3 Example: Overlay2

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Google Maps API version3 Example: Overlay2</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
 var map = null;
 var overlays = new Array();
 function initialize() {
  var myLatlng = new google.maps.LatLng(35.472324, 133.05052);
  var myOptions = {
   zoom: 10,
   center: myLatlng,
   mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  AddOverlayData();
  google.maps.event.addListener(map, "dragend", function() {
   ClearOverlay();
   AddOverlayData(1);
  });
 }
 function AddOverlayData(ww) {
  var northEast = map.getCenter();
  northEast = new google.maps.LatLng(northEast.lat()+0.5, northEast.lng()+1);
  var southWest = new google.maps.LatLng(northEast.lat()-1, northEast.lng()-2);
  if(ww!=1) {
   map.fitBounds(new google.maps.LatLngBounds(southWest, northEast));
  }
  var lngSpan = northEast.lng() - southWest.lng();
  var latSpan = northEast.lat() - southWest.lat();
  for(var i=0; i<10; i++) {
   overlays[i] = new AddOverlay(i, southWest.lat() + latSpan * Math.random(), southWest.lng() + lngSpan * Math.random());
  }
 }
 function AddOverlay(id, lat, lng) {
  this.id_ = id;
  this.lat_ = MathRound(lat);
  this.lng_ = MathRound(lng);
  this.setMap(map);
 }
 AddOverlay.prototype = new google.maps.OverlayView();
 AddOverlay.prototype.draw = function() {
  if(!this.div_) {
   this.div_ = document.createElement("div");
  }
  var obj = this.div_;
  var panes = this.getPanes();
  panes.overlayLayer.appendChild(obj);
  var latlng = new google.maps.LatLng(this.lat_, this.lng_);
  var point = this.getProjection().fromLatLngToDivPixel(latlng);
  obj.title = "Point" + this.id_;
  obj.style.position = "absolute";
  obj.style.left = point.x + "px";
  obj.style.top = point.y + "px";
  obj.style.padding = "2px";
  obj.style.fontSize = "10px";
  obj.style.lineHeight = "1em";
  obj.style.border = "1px solid #666";
  obj.style.background = "#fffffe";
  obj.innerHTML = "<strong>Point" + this.id_ + "</strong><br />" + this.lat_ + "<br />" + this.lng_;
 };
 AddOverlay.prototype.onRemove = function() {
  this.div_.parentNode.removeChild(this.div_);
  this.div_ = null;
 };
 function ClearOverlay() {
  if(overlays.length>0) {
   for(var i=0; i<overlays.length; i++) {
    overlays[i].remove();
   }
   overlays = new Array();
  }
 }
 function MathRound(id) {
  var s = 10000;
  return Math.round(id*s)/s;
 }
 function addEvent(obj, evType, fn) {
  if(obj.addEventListener) {
   obj.addEventListener(evType, fn, false);
  }else if(obj.attachEvent) {
   obj.attachEvent("on" + evType, fn);
  }
 }
 addEvent(window, "load", initialize);
</script>
</head>
<body>
<h1>Google Maps API v3 Example: Overlay2</h1>
<div id="map_canvas" style="width:600px; height:350px;"></div>
</body>
</html>

 サンプルのOverlayは共に10個ですが、100個にしても(やや遅くなりますが)描画速度は十分速いです。また、Overlayには、DIVではなくIMG(画像)を埋め込むことも可能なので、Marker(マーカー)のような使い方もできます。

 なお、Overlayの使い方については、下記ページを参考にさせていただきました。

Maps API V3 Overlays : Google Maps API Version3 日本語ドキュメント(非公式)
sites.google.com/site/gmapsapi3/overlays#TOC-Cu...
OverlayView クラス : Google Maps API Version3 日本語ドキュメント(非公式)
sites.google.com/site/gmapsapi3/Home/v3_referen...
Google Maps API V3でカスタムOverlayViewを使う
www.mwsoft.jp/programming/googlemap/google_map_...

【追記】

 Overlayをランダムに変化させる際、「too much recursion」エラーが出て動かないことに気付きました。Google Maps Javascript API V3 Overlaysを見ると、従前のremove()は無くなり、新たにonRemove()が加わっていました。と言うことで修正。(2010-09-02)

EDIUNET | PHP/MySQL | 独り言 | 提供サービス | JavaScript