【问题标题】:Google Maps Store Locator Library with MarkerClusterer带有 MarkerClusterer 的 Google 地图商店定位器库
【发布时间】:2015-03-28 12:37:46
【问题描述】:

我正在使用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

【问题讨论】:

    标签: javascript google-maps-api-3 markerclusterer


    【解决方案1】:

    我正在研究 ClusterMarker + Storelocator。

    这是我的 panel.js。

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

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

    【讨论】:

      【解决方案2】:

      我用 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, []); 
      

      我还有一个问题。我希望你使用功能过滤器。但我无法隐藏集群上的标记...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多