大家好我是Ian,目前是負責網頁前端,每天工作都在處理各種問題(pm奇形需求),順便分享一些相關的解法。
最近剛好專注在google map工具的使用,需要將大量的資料撒上google map,資料也帶滿多資訊,讓user點擊marker在拉開infowindow,又嫌太慢。於是開始研究marker group概念的工具,也發現關於marker library中文的文件比較少一點,所以就順手寫了marker延伸使用範例,也可以直接點開範例看code。

分為內建google map工具操作,還有運用google map團隊所開發的工具,達到更多的功能。

google map 搭配內建marker infowindow

首先先運用比較常用到的功能,google map下多個marker,再搭配marker的event來互動,以下是打開infowindow的運用。

簡單創建多筆經緯度資料,呈現的是搭計程車到地點的價格。

//我只標出比較重要部分,其他就codepen點開來看唄
var marker = new google.maps.Marker({
position: {lat: item.lat, lng: item.lng},
map: map,
title: item.name,
icon:image,
data:'Go to '+item.name + '<br/> Taxi price: ' +item.price
});
marker.addListener('click', function() {
infowindow.setContent( this.data );
infowindow.open(map, this);
});

比較特別的是這個寫法,在每個marker 加入 data 物件,讓marker延伸操作性。
以下圖片實際呼叫marker 所印出來的資料,可以看到畫線處,出現我們剛剛加入的data,這樣你就可以利用marker來帶一些資料,例如說點擊marker可以call function 然後帶互動,這方法變得方便又輕巧。
ps.可以利用指定某個marker markerArr[i].setOptions({data=”/change/image”})變換marker資料。

google map marker console

實際運作範例 infowindow





## google map 運用library
感謝google大大,其實googlemap官方github有整理滿多library google map library,建議下載使用,因為滿多工具demo頁面都呈現404…。


這邊要用的是markerwithlabel 還有 markercluster這兩個library,markerwithlabel讓我們更簡單設計不同的marker,例如讓他帶自訂的image,再來是重點 markercluster,它讓我們可以解決marker過多,同時重疊的問題。


首先處理單一個marker用的是MarkerWithLabel,原本呼叫 google.maps.Marker 改成 MarkerWithLabel,然後就搞定了,非常快速簡單,他可以用的event滿多的,基本上都可以處理marker的互動,甚至也可以像一般的marker設定物件上去。
//更多變數請點選說明文件,基本上可以用class 搭配 css操作,或是labelStyle 處理icon style
var marker = new MarkerWithLabel({
draggable: false,
raiseOnDrag: false,
map: map,
labelContent: '<span>'+ item.name +'<br/>'+ item.price +'</span>',
labelAnchor: new google.maps.Point(40,32),
labelClass: "labels", // the CSS class for the label
labelStyle: {opacity: 1},
position: {lat: item.lat, lng: item.lng},
data:'Go to '+item.name + '<br/> Taxi price: ' +item.price
});


## 實際範例 markerwithlabel

See the Pen google map marker cluster (markercluster & markerlabel) by ianchu (@chu1228) on CodePen.




最後是使用markercluster工具,這工具目前還有另一版markerclusterplus,這邊就只用來一般版來操作。

markercluster主要是處理marker下完後,call function渲染畫面,快速的判斷每個marker之間是否接近到某個程度,在創造出屬性這區塊的聚合marker,簡單的就是
marker -> markerArr.markercluster({})


建立Cluster的方法,這個版本無法帶入className,需要打開.js檔案,直接在style.push 區塊修改,我這邊有修改background-repeat:no-repeat。
//arr 是剛剛marker的 array 需要建立帶入 其餘是內建option
markerCluster = new MarkerClusterer(map, arr, {
gridSize: 50,
maxZoom: 15,
zoomOnClick: true,
styles: imgArr,
imagePath: 'https://googlemaps.github.io/js-marker-clusterer/images/m'
});


這邊是客製化Cluster icon的方法,這個function會抓到這個建立中的cluster內包含的marker,會用陣列帶進來,這時候我們就跑迴圈,將marker內的資料帶出來,在看你想呈現的方式處理,我這邊是計算裡面的平均價格(這範例下方有click event寫法,不過我直接寫進codepen導致跑不動)。
// 稍微修改 cluster.js的檔案  讓聚合變得更客製化
MarkerClusterer.prototype.calculator_ = function(markers, numStyles) {
//省略
var price = 0;
for (var i = 0; i < markers.length; i++) {
price += Number(markers[i].dataPrice);
}
price = Math.floor(price/count);
//省略
return {
text: count + ' 筆<br/>A. NT' + price,
index: index
};
};


## 實際範例 markercluster

上面簡單講解一下google map marker過多的處理方法,沒想到最麻煩的是寫範例+建立假資料最耗時間,快寫完剛好看到更新版的…最新版更新(os:…,為啥跟github版本差那麼多…),
大家可以直接試用看看,看介紹貌似支援call option直接修改icon 還有增加className,能直接略過我上面硬改cluster.js這段是最好,畢竟改plugin缺乏前端最重要的沿用性。

感謝大家閱讀!!希望能解決google map 麻煩的 marker問題,
一起來讓google map好用一點點點點點點點XD。