地図上の吹き出し付きマーカーを自動巡回する

プロトタイプを随分前に作ってて、これはどっかで使えるぜ!いっちょ Web サービスでも作っちまうか!? な〜んて思ってからもう数年経っちまいました。もう Google Maps をキーコンテンツにしたサイトもサービスも流行らん気がしたのでソース晒します。

晒してしまうわりにはコードが汚いままなので、綺麗にして使うか、ここはこうした方が綺麗だよ、というご指摘頂けると幸いです。

ちなみにこの大本となるコードを書いたのは2011年。時代は流れて API キーが必須となったり、自分の中で jQuery への愛情が薄れていったりで、現在(2018年)でも動くように修正しています。

HTML側には #map-canvas というDIVの箱を用意。巡回停止・再開用のボタンも用意。停止ボタンには #btn-autopan-stop と onclick="autoPanStop()" 、再開ボタンには #btn-autopan-restart と onclick="autoPanRestart()"。 あとは下のコードを好きなところにぶっ込んでください。

<div id="map-canvas" class="map-canvas" style="width:640px;height:480px;"></div>
<button type="button" id="btn-autopan-stop" onclick="autoPanStop()">マーカー巡回停止</button>
<button type="button" id="btn-autopan-restart" onclick="autoPanRestart()">マーカー巡回再開</button>
<script type="text/javascript">
  var map;
  var markers = new Array();
  var infoWindows = new Array();
  var currentMarker = null;
  var currentInfoWindow = null;
  var mapAutoPan = false;
  var mapPanInterval = 3;  //Sec
  var mapAutoTimer = mapPanInterval;
  
  function initMap(lat, lng, mapBox, draggable) {
    var myLatlng = {lat: 35.658620, lng: 139.745417};
    var map = new google.maps.Map(document.getElementById("map-canvas"), {
      zoom: 7,
      center: myLatlng,
    });

    //吹き出しの設定
    data = [
      { lat: 35.705833, lng: 139.751944, team: '読売ジャイアンツ' },
      { lat: 35.674556, lng: 139.717083, team: '東京ヤクルトスワローズ' },
      { lat: 35.443383, lng: 139.640028, team: '横浜DeNAベイスターズ' },
      { lat: 35.185972, lng: 136.947467, team: '中日ドラゴンズ' },
      { lat: 34.721231, lng: 135.361642, team: '阪神タイガース' },
      { lat: 34.391878, lng: 132.484731, team: '広島東洋カープ' },
      { lat: 43.015192, lng: 141.409686, team: '北海道日本ハムファイターズ' },
      { lat: 38.256136, lng: 140.902567, team: '東北楽天ゴールデンイーグルス' },
      { lat: 35.768617, lng: 139.420464, team: '埼玉西武ライオンズ' },
      { lat: 35.645117, lng: 140.030847, team: '千葉ロッテマリーンズ' },
      { lat: 34.669403, lng: 135.476214, team: 'オリックス・バファローズ' },
      { lat: 33.595383, lng: 130.362175, team: '福岡ソフトバンクホークス' }
    ];

    for (i in data) {
      //マーカー
      var marker = new google.maps.Marker({
        map: map,
        position: {lat: data[i].lat, lng: data[i].lng},
      });
      markers.push(marker);
      
      //吹き出し
      var infoWindow = attachInfoWindow(
        marker,
        data[i]
      );
    }

    //吹き出しの巡回設定
    autoPanStart();
    autoPan();
    setInterval(autoPan, 1000);
    
    //イベントリスナー(主に巡回停止)の設定
    google.maps.event.addListener(map, 'dragstart', autoPanStop);
    google.maps.event.addListener(map, 'dragend', autoPanStop);
    google.maps.event.addListener(map, 'rightclick', autoPanStop);
  }
  
  function autoPan(){
    mapAutoTimer++;
    if (mapAutoPan == true && mapAutoTimer > mapPanInterval){
      var rnd = parseInt(Math.random() * markers.length);
      if (currentInfoWindow == infoWindows[rnd]) rnd = (rnd + 1) % markers.length;
      var thisMarker = markers[rnd];
      removeInfoWindow();
      infoWindows[rnd].open(map, markers[rnd]);
      currentInfoWindow = infoWindows[rnd];
      mapAutoTimer = 0;
    }
  }
  
  function autoPanStop(){
    document.getElementById("btn-autopan-restart").removeAttribute("disabled"); 
    document.getElementById("btn-autopan-stop").setAttribute("disabled", ""); 
    mapAutoPan = false;
  }
  
  function autoPanStart(){
    autoPanRestart();
  }
  
  function autoPanRestart(){
    removeInfoWindow();

    document.getElementById("btn-autopan-restart").setAttribute("disabled", ""); 
    document.getElementById("btn-autopan-stop").removeAttribute("disabled"); 
    mapAutoTimer = mapPanInterval;
    mapAutoPan = true;
  }
  
  function attachInfoWindow(marker, data){
    var infoWindow = new google.maps.InfoWindow({
      content: '<div onclick="autoPanStop();">'+data.team+'</div>',
    });
    
    infoWindows.push(infoWindow);
    google.maps.event.addListener(marker, "click", function(){
      autoPanStop();
      removeInfoWindow();
      infoWindow.open(marker.getMap(), marker);
      currentInfoWindow = infoWindow;
    });
    return infoWindow;
  }
  
  function openInfoWindow(i){
    autoPanStop();
    removeInfoWindow();
    infoWindows[i].open(map, markers[i]);
    currentInfoWindow = infoWindows[i];
  }
  
  function removeInfoWindow(){
    if (currentInfoWindow){
      currentInfoWindow.close();
    }
    if (currentMarker){
      currentMarker.setMap();
    }
  }
</script>
<script async defer
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>