Google Map API version 3 Overlay Example2

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

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

 「Google Map API version 3 Overlay Example」の続きです。

 前回は、地図をDrag(ドラッグ)するたびに、10個のOverlayをランダムに変化させたのですが、今回は、それにInfoWindow(吹き出し)を付けることにします。各Overlayをクリックすると、吹き出しが表示されます。

Google Maps API v3 Example: Overlay3
tika.tisoku.net/overlay/?id=3

 ポイントの一つ目は「AddOverlay.prototype.draw」内の
  popups[id] = new google.maps.InfoWindow({
   content: "<strong>Point" + id + "</strong><br />(" + this.lat_ + " ," + this.lng_ + ")",
   pixelOffset: new google.maps.Size(30, 0),
   position: latlng
  });
  google.maps.event.addDomListener(div, "click", function() {
   PopInfowidow(id);
  });
です。
 苦労したのは、「google.maps.InfoWindow()」でInfoWindowを作成する際に「position: latlng」のように緯度経度を設定することと、OverlayをクリックしてInfoWindowを呼び出す際に「google.maps.event.addListener()」ではなく「google.maps.event.addDomListener()」を使用することが、なかなか分からなかったことです。
 後者の「google.maps.event.addDomListener()」については、「this.div_ = document.createElement("div")」と「var div = this.div_」で定義したOverlayのdivオブジェクトと、「var id = this.id_」で定義したOverlayのidを、「PopInfowidow()」に渡しています。
 この「PopInfowidow()」では
 function PopInfowidow(id) {
  popups[id].open(map);
  if(popup) {
   popup.close();
  }
  popup = popups[id];
 }
にある通り、「map」上において指定された「id」のInfoWidowをopenし、以前に開かれていたInfoWidowについては閉じるという処理を行っています。

 取り合えず、これでMarkerを使うことなく、InfoWindowを開くことができるのですが、注意点が2つあります。
  1. IE6などでメモリリークが発生する。
  2. InfoWidowを開いた際に、地図画面が動いた場合、新たにOverlayをクリックしてもInfoWidowが開かない場合がある。
 前者については、回避方法が思い浮びません。公式サンプルの「Google Maps JavaScript API v3 Example: Info Window Simple」code.google.com/intl/en/apis/maps/documentation... でも、IE6でInfoWidowを開くとメモリリークが発生するので仕方ないのかも。
 後者は、「google.maps.event.addListener(map, "dragend", function())」と「PopInfowidow()」にglobalなフラグを設定することで簡単に回避することできます。ちなみに、先ほど公開した「全国地価探索」では、この注意点の回避処理を行っています。

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

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Google Maps API version3 Example: Overlay3</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
 var map = popup = null;
 var overlays = new Array(), popups = 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 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.style.cursor = "pointer";
  var id = this.id_;
  div.innerHTML = "<strong>Point" + id + "</strong>";
  popups[id] = new google.maps.InfoWindow({
   content: "<strong>Point" + id + "</strong><br />(" + this.lat_ + " ," + this.lng_ + ")",
   pixelOffset: new google.maps.Size(30, 0),
   position: latlng
  });
  google.maps.event.addDomListener(div, "click", function() {
   PopInfowidow(id);
  });
 };
 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].onRemove();
   }
   overlays = new Array();
  }
  if(popup) {
   popup.close();
  }
 }
 function PopInfowidow(id) {
  popups[id].open(map);
  if(popup) {
   popup.close();
  }
  popup = popups[id];
 }
 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: Overlay3</h1>
<div id="map_canvas" style="width:600px; height:350px;"></div>
</body>
</html>

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