Google 带有 MarkerClusterer 的地图商店定位器库

Google Maps Store Locator Library with MarkerClusterer

我在旁边使用 Google Maps Store Locator library, but I want to be able to implement MarkerClusterer。但是,我一直无法弄清楚如何让它们协同工作。

代码:

(function($, window, document){

    var map = null,
        cluster = null;

    function storeSource() {
        $.extend(this, new storeLocator.StaticDataFeed);
        var that = this;

        $.getJSON('linktoAJAXThatReturnsJSON', function(data) {
            that.setStores(that.parse_(data));
            map.fitBounds(centerMap(data));
        });
    }

    storeSource.prototype.parse_ = function(data) {
        var stores = [];

        data.forEach(function(row){
            var
            position = new google.maps.LatLng(row.lat, row.long),
            locality = row.postcode + ', ' + row.city,

            store = new storeLocator.Store(row.id, position, null, {
                    title   : row.name,
                    address : [row.address, locality, row.country].join('<br>'),
                    phone   : row.phone
                });

            stores.push(store);
        });

        return stores;
    };

    // Clusters Markers together
    function makeCluster(data) {
        var markers = [];

        data.forEach(function(row){
            markers.push(row.getMarker());
        });

        cluster = new MarkerClusterer(map, markers, {});
    }

    // Finds viewpoint that accomodates all locations
    function centerMap(data) {
        var bounds = new google.maps.LatLngBounds();

        data.forEach(function(row){
            bounds.extend(new google.maps.LatLng(row.lat, row.long));
        });

        return bounds;
    }

    google.maps.event.addDomListener(window, 'load', function() {
        map = new google.maps.Map(document.getElementById('mappanel'), {
            mapTypeId : google.maps.MapTypeId.ROADMAP
        });
        var data = new storeSource();
        var view = new storeLocator.View(map, data, {
            geolocation: false
        });

        new storeLocator.Panel(document.getElementById('searchpanel'), {
            view: view
        });

        // I think this is the place to try and add the Markers
        // from storeSource. However, debugging shows Markers haven't
        // been created yet. This leads me to believe that it's done
        // internally in the storeLocator library. Not sure what to do
        makeCluster(view.data_.stores_);
    });

    $(document).on('click', '.action', function(e){
        e.preventDefault();
    });
})(window.jQuery, window, document);

不幸的是,我没有现场版。

如代码中所述,MarkerClusterer 需要类型为 google.maps.Marker 的对象数组。

我的计划是重用 storeLocator.Store 对象并从中检索标记。我尝试检索它们,但调试显示它们未定义。

不确定如何让这 2 个库一起工作而不必破解其中任何一个。

编辑::取得了一些进展

我能够通过覆盖 storeLocator.View.createMarker 函数将 StoreLocator 使用的标记存储到 MarkerClusterer 中。然而,这会导致另一个问题:标记的可见性由 2 个不同的库控制:MarkerClusterer 想要在缩小时隐藏标记,但 storeLocator 始终显示所有标记。

有没有办法让标记遵循 MarkerClusterer 的默认行为?

我也有一个JFiddle.

编辑#2::解决方案

非常感谢 P1s4 的解决方案!这是修改后的 JFiddle.

我用 opacity 0 和 zindex 10000 解决了 storelocator 标记和 opacity 1 zindex 999 集群标记问题。

view.createMarker = function(store) {
    var SHADOW = new google.maps.MarkerImage('wp-content/plugins/p1s4-storelocator/img/marker-shadow.png', null, null,new google.maps.Point(14, 13));

    var markerOptions = {
      position: store.getLocation(),
      icon: store.getDetails().icon,
      Opacity:0,
      zIndex:10000,
      title: store.getDetails().title
    },

    marker = new google.maps.Marker(markerOptions);
    markercluster = new google.maps.Marker(markerOptions);
    markercluster.setOpacity(1);
    markercluster.setZIndex(999);
    clusters.addMarker(markercluster);
    return marker;
  }
      clusters = new MarkerClusterer(map, []); 

我还有一个问题。我想使用 Feauture 过滤器。但是我无法隐藏群集上的标记...

我正在研究 ClusterMarker + Storelocator。

这是我的panel.js。

现在一切正常:clustermarkers、infowindows、在面板中单击时缩放、使用 cluster 和面板中的功能进行过滤。 希望这有用。

     google.maps.event.addDomListener(window, 'load', function () {
    var map =  new google.maps.Map(document.getElementById('map-canvas'), {
        center :  new google.maps.LatLng(43.779982, 11.242564),
        zoom : 4,
        mapTypeId : google.maps.MapTypeId.ROADMAP
    });
    var panelDiv = document.getElementById('panel');
    var data =  new DataSource;
    var view =  new storeLocator.View(map, data, {
        geolocation : true,
        features : data.getFeatures()
    });

     // create the markers for storelocator and cluster at same time
    // opacity of storelocator marker 0 and cluster 1. This way you see only 
    // the markers of cluster. setClickable false on marker of cluster 
   // and you click markers of storelocator. This way you use your panel click
   // and storelocator inwfowindow. 

    var clusterMarkers = [];
    view.createMarker = function (store) {
        var markerOptions = {
            position : store.getLocation(),
            icon : store.getDetails().icon,
            Opacity : 0,
            title : store.getDetails().title,
            Filter : store.getDetails().filter
        }
        marker =  new google.maps.Marker(markerOptions);
        markercluster =  new google.maps.Marker(markerOptions);
        markercluster.setOpacity(1);
        markercluster.setClickable(false);
        clusters.addMarker(markercluster);
        clusterMarkers.push(markercluster);
        return marker;
    }

//I set maxzoom at 17 and when i open infowindow at 18. This way i have
//infowindow on the marker and not inside cluster
    clusters =  new MarkerClusterer(map, [], {
        maxZoom : 17
    });

// modded infowindow for storelocator
    var infowindow =  new google.maps.InfoWindow;
    view.getInfoWindow = function (store) {
        if (!store) {
            return infowindow;
        }
        var details = store.getDetails();
        var html = ['<div class="store"><div class="title">', details.title, '</div><div class="address">', details.address, '</div>', '<div class="hours misc">', details.phone, '</div></div>'].join('');
         infowindow.setContent($(html)[0]);
        if (map.getZoom() < "18") map.setZoom(18);
        map.panTo(store.getLocation());
        return infowindow;
    };

// i close infowindow on zoom out.
    google.maps.event.addListener(map, 'zoom_changed', function() {
        infowindow.close();
    });

     new storeLocator.Panel(panelDiv, {
        view : view,
        featureFilter : true
    });

// i use features modded with radio button on storelocator. I have a filter based on number (1,2,3,4) and i added features "all" (0) to all stores.
    var features = view.getFeatures().asList();
    $('<div id="filter-radio" />').appendTo('.storelocator-filter');
    $.each(features, function (i, o) {
        list = $('<input type="radio" class="filter" name="filter" value="' + i + '" id="filter' + (o.getDisplayName()) + '"/><label for="filter' + (o.getDisplayName()) + '">' + (o.getDisplayName()) + '</label>').appendTo('#filter-radio').change(function () {
            view.set('featureFilter',  new storeLocator.FeatureSet(features[this.value]));
            view.refreshView();

  // call toggle to change the markers on the cluster too
            toggle(this.value);
        });
    }); 

  //in mobile view i prefer use a select for features filter

    var features_mobile = view.getFeatures().asList();
        $('<div id="filter-select" />').prependTo('#panel');
         list = $('<select class="filter-select"/>')
        .appendTo('#filter-select').
        change(function () {
            view.set('featureFilter',
            new storeLocator.FeatureSet(features[this.selectedIndex]));
            view.refreshView();
            toggle(this.selectedIndex);
        });
    $.each(features, function (i, o) {

        list.append(new Option(o.getDisplayName()));

    });
    // toggle function for markercluster. I filter markers inside the
    // cluster array with the same value as storelocator
    function toggle(filterc) {
        var markers = [];
        for (var i = 0; i < clusterMarkers.length; i++) {
            if (filterc == '0') {
                markers.push(clusterMarkers[i]);
                clusterMarkers[i].setVisible(true);
            }
            else if (clusterMarkers[i].Filter == filterc) {
                markers.push(clusterMarkers[i]);
                clusterMarkers[i].setVisible(true);
            }
        }
        if (markers.length) {
            clusters.removeMarkers(clusterMarkers);
            clusters.addMarkers(markers);
        }
    };


});