大家好我是 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 資料。

實際運作範例 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。