Google Maps API - 多個地圖標記

前一篇介紹了如何在地圖裡放入地圖標記 ( Marker ),這篇將透過 Google Maps API,做出地圖標記、標籤與動畫,甚至實現在地圖上放入多個標記,並且透過簡單的動畫依序載入這些標記。

放入多個地圖標記

如果有多個地圖標記,可以用個陣列來裝載對應的標籤、經緯度...等資訊,舉例來說,這裡使用一個名為 position 的陣列,將五個地圖標記的資訊用物件的方式放在裡頭,同時建立一個空的 markers 陣列,用這個陣列的內容來宣告一個個新的地圖標記。

在這裡有個比較需要注意的地方,就是addMarker(e)這個 function,如果把這個 function 放在initMap()的外面,會發生地圖還沒載入就執行addMarker(e)而發生錯誤,所以要放在裡頭。

範例:放入多個地圖標記

var map;
var markers = [];
var position = [
  {label:'A',lat:25.0336962,lng:121.5643673},
  {label:'B',lat:25.0333698,lng:121.5641564},
  {label:'C',lat:25.033899,lng:121.564329},
  {label:'D',lat:25.0338407,lng:121.5645269},
  {label:'E',lat:25.0336377,lng:121.5645727}
];

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 19,
    center: {
      lat: 25.0336962,
      lng: 121.5643673
    }
  });

  for (var i = 0; i < position.length; i++) {
    addMarker(i);
  }
}

function addMarker(e) {
  markers[e] = new google.maps.Marker({
    position: {
      lat: position[e].lat,
      lng: position[e].lng
    },
    map: map,
    label: position[e].label
  });
}

點擊按鈕,依序放入地圖標記

已經知道如何放入多個標記後,接著就來試著做個按鈕,搭配地圖標記的 DROP 動畫效果,就能在點擊按鈕的當下,讓地圖標記依序落下並且載入。

首先在 html 裡放入一個 button,撰寫一點 CSS 讓這個按鈕可以置中並且浮在地圖上方,同時用滑鼠按下去的時候,也可以透過active來設定壓下去的感覺,此外在 HTML 的按鈕標籤裡,增加一個onclick的事件,讓點擊按鈕的時候,執行go()這個 function。

HTML

<button id="btn" onclick="go()">放置地圖標記</button>

CSS

#btn{
  position:fixed;
  z-index:99;
  top:20px;
  left:calc(50% - 150px);
  font-size:30px;
  width:80%;
  max-width: 300px;
  box-shadow:rgba(0,0,0,.5) 0 5px 10px;
  border-radius: 5px;
  padding:10px;
  outline: none;
  border:1px solid #999;
}
#btn:active{
  box-shadow:rgba(0,0,0,.5) 0 3px 5px;
}

再來看到初始化地圖的程式,其實跟剛剛的程式一模一樣,差別只在於不要在一開始的時候不要先把地圖標記放進去。

var map;
var markers = [];
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 19,
    center: {
      lat: 25.0336962,
      lng: 121.5643673
    }
  });
}

var position = [
  {label:'A', lat:25.0336962, lng:121.5643673},
  {label:'B', lat:25.0333698, lng:121.5641564},
  {label:'C', lat:25.033899, lng:121.564329},
  {label:'D', lat:25.0338407, lng:121.5645269},
  {label:'E', lat:25.0336377, lng:121.5645727}
];

接著撰寫go()這個 function,裡面可以看到有另外兩個 function 分別是clearMarkers()addMarker(i),因為我們會把每個標記,宣告到 markers 的陣列元素裡,所以在一開始執行go()的時候,透過clearMarkers()來清除標記,這裡清除標記的方法為markers[i].setMap(null);。然而有清除就有新增,新增的方法額外使用了setTimeoutanimation: google.maps.Animation.DROP來產生延遲的動畫效果,因此在執行的當下就會看到地圖標記依序落下。

不過很可惜的,經過長時間的查詢,發現 label 並不會有動畫效果,所以只好忍痛把 label 給 marker 起來...

function go() {
  clearMarkers();
  for (var i = 0; i < position.length; i++) {
    addMarker(i);
  }
}

function addMarker(e) {
  setTimeout(function() {
    markers[e] = new google.maps.Marker({
      position: {
        lat: position[e].lat,
        lng: position[e].lng
      },
      map: map,
      //label: position[e].label,
      animation: google.maps.Animation.DROP
    });
  }, e * 150);
}


function clearMarkers() {
  for (var i = 0; i < markers.length; i++) {
    if(markers[i]){
      markers[i].setMap(null);
    }
  }
  markers = [];
}

雖然到這邊好像完成,但是實際上操作起來會有問題!實際上操作起來會有問題!實際上操作起來會有問題!( 很重要所以說三次 ) 因為使用順序宣告的關係,可能會造成點擊按鈕清空標記的時候,還沒有宣告完成標記,結果就造成快速連點按鈕時,會出現地圖標記卡在地圖上的狀況。

範例:連點會有問題的地圖標記

所以如果要解決這個狀況,就變成要把 marker 的部分改成用push的,就可以一勞永逸地解決這問題。

範例:點擊按鈕,依序放入地圖標記

function addMarker(e) {
  setTimeout(function() {
    markers.push(new google.maps.Marker({
        position: {
          lat: position[e].lat,
          lng: position[e].lng
        },
        map: map,
        //label: position[e].label,
        animation: google.maps.Animation.DROP
      }));
  }, e * 150);
}

有興趣瞧瞧其他新文章嗎?