简体   繁体   English

带有MarkerClusterer的Google Maps Store Locator库

[英]Google Maps Store Locator Library with MarkerClusterer

I'm using the Google Maps Store Locator library , but I want to be able to implement MarkerClusterer alongside it. 我正在使用Google Maps Store Locator库 ,但是我希望能够与其一起实现MarkerClusterer However, I haven't been able to figure out how to make them work together. 但是,我还无法弄清楚如何使它们协同工作。

Code: 码:

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

Unfortuantely, I don't have a live version. 不幸的是,我没有现场版本。

As explained in the code, the MarkerClusterer requires an array of objects of type google.maps.Marker. 如代码中所述,MarkerClusterer需要一个类型为google.maps.Marker的对象数组。

My plan is to reuse the storeLocator.Store objects and retrieve the Marker from it. 我的计划是重用storeLocator.Store对象并从中检索标记。 I try to retrieve them, but debugging shows that they are undefined. 我尝试检索它们,但调试显示它们未定义。

Not sure how to make these 2 libraries work together without having to hack either of them. 不知道如何使这两个库一起工作而不必破解它们中的任何一个。

EDIT::SOME PROGRESS MADE 编辑::取得了一些进展

I was able to store the Markers the StoreLocator uses into MarkerClusterer by overriding storeLocator.View.createMarker function. 通过覆盖storeLocator.View.createMarker函数,我能够将StoreLocator使用的标记存储到MarkerClusterer中。 However, this leads to another problem: the visibility of the markers are controlled by 2 different libraries: MarkerClusterer wants to hide the Markers when zoomed out, but storeLocator displays all Markers all the time. 但是,这带来了另一个问题:标记的可见性由2个不同的库控制:MarkerClusterer希望在缩小时隐藏标记,但是storeLocator始终显示所有标记。

Is there a way to make the Markers follow MarkerClusterer's default behavior? 有没有办法让Markers遵循MarkerClusterer的默认行为?

I also have a JFiddle . 我也有一个JFiddle

EDIT #2::SOLUTION 编辑#2 ::解决方案

Huge thanks to P1s4 for the solution! 非常感谢P1s4提供的解决方案! Here is the revised JFiddle . 这是修改后的JFiddle

I'm working on ClusterMarker + Storelocator. 我正在研究ClusterMarker + Storelocator。

Here my panel.js. 这是我的panel.js。

Now it's all working: clustermarkers, infowindows, zoom on click in the panel, filter with features both in cluster and panel. 现在一切正常:群集标记,信息窗口,在面板中单击放大,使用群集和面板中的功能进行过滤。 Hope this is useful. 希望这是有用的。

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


});

I solved with opacity 0 and zindex 10000 for markers of storelocator and opacity 1 zindex 999 for markers of cluster. 我用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, []); 

I have another problem. 我还有另一个问题。 I want tu use the Feauture filter. 我想使用Feauture过滤器。 But i can't Hide the markers on the cluster... 但是我无法隐藏集群上的标记...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM