我正在使用Google Maps Store Locator library,但是我希望能够同时实现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对象并从中检索标记。我尝试检索它们,但调试显示它们未定义。

不知道如何使这两个库一起工作而不必破解它们中的任何一个。

编辑::取得了一些进展

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

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

我也有一个JFiddle

编辑#2 ::解决方案

非常感谢P1s4提供的解决方案!这是修订的JFiddle

最佳答案

我正在研究ClusterMarker + Storelocator。

这是我的panel.js。

现在一切正常:群集标记,信息窗口,在面板中单击放大,使用群集和面板中的功能进行过滤。
希望这是有用的。

     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);
        }
    };


});

关于javascript - 带有MarkerClusterer的Google Maps Store Locator库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28212129/

10-11 03:26