谷歌地图API V3标记群集与可过滤的标记

Google Maps API V3 Marker Cluster with filterable markers

本文关键字:过滤 群集 API 谷歌地图 V3      更新时间:2023-09-26

Stackoverflow上有很多问题,人们已经帮助解决了MarkerClusterer的问题,但是,我在Github上使用Twilliamson90的一个很棒的小项目。基本上,它允许我对标记进行一些很好的过滤,并允许我链接到一些不错的外部数据集。

我现在的问题是我有太多的数据无法轻松显示在页面上,而不会看起来太拥挤。显而易见的解决方案是添加标记聚类 - 不幸的是,我发现它没有那么简单。

我已经完成了几个教程,但我无法使其与过滤一起使用。

我已经粘贴了下面的javascript,任何帮助将不胜感激。巨大。

var TEST_MAP = 'custom_style';
var myMap = function() {
    var featureOpts = [
    {
      stylers: [
        { hue: '#782B8B' },
        { visibility: 'simplified' },
        { gamma: 0.5 },
        { weight: 0.5 }
      ]
    },
    {
      elementType: 'labels',
      stylers: [
        { visibility: 'off' }
      ]
    },
    {
      featureType: 'water',
      stylers: [
        { color: '#782B8B' }
      ]
    }
  ];
    var options = {
        zoom: 7,
        center: new google.maps.LatLng(53.967397, -2.043457),
        streetViewControl: false,
        zoomControlOptions: {
          style: google.maps.ZoomControlStyle.SMALL
        },
        mapTypeControl: false,
        mapTypeControlOptions: {
            mapTypeIds: [TEST_MAP]
        },
        mapTypeId: TEST_MAP
    }
    /*
        Load the map then markers
        @param object settings (configuration options for map)
        @return undefined
    */
    function init(settings) {
        map = new google.maps.Map(document.getElementById( settings.idSelector ), options);
        var styledMapOptions = {
            name: 'Custom Style'
        };
        var customMapType = new google.maps.StyledMapType(featureOpts, styledMapOptions);
        map.mapTypes.set(TEST_MAP, customMapType);
        markerLocation = settings.markerLocation;
        loadMarkers();
    }
    /*
        =======
        MARKERS
        =======
    */
    markers = {};
    markerList = [];
    /*
        Load markers onto the Google Map party a provided array or demo personData (data.js)
        @param array personList [optional] (list of people to load)
        @return undefined
    */
    function loadMarkers(personList) {
        // optional argument of person
        var people = ( typeof personList !== 'undefined' ) ? personList : personData;
        var j = 1; // for lorempixel
        for( i=0; i < people.length; i++ ) {
            var person = people[i];
            // if its already on the map, dont put it there again
            if( markerList.indexOf(person.id) !== -1 ) continue;
            var lat = person.lat,
                lng = person.lng,
                markerId = person.id;
            var infoWindow = new google.maps.InfoWindow({
                maxWidth: 500
            });
            var iconImage = {
                url: person.markerIcon,
                size: new google.maps.Size(30, 40),
                origin: new google.maps.Point(0,0),
                anchor: new google.maps.Point(0,40)
            };
            var marker = new google.maps.Marker({
                position: new google.maps.LatLng( lat, lng ),
                title: person.name,
                markerId: markerId,
                icon: iconImage,
                map: map
            });
            markers[markerId] = marker;
            markerList.push(person.id);

var MarkerCluster = new MarkerClusterer(TEST_MAP, markers);
            var content = ['<div class="iw"><img src="', person.image, '">', '<div class="iw-text"><strong>', person.name, '</strong><br><strong>Applications:</strong> ', person.applications, '<br><strong>SIC Sub Class:</strong> ', person.sicSubClass, '<br><strong>Constituency:</strong> ', person.constituency, '<br><strong>Stream:</strong> ', person.stream, '<br><strong>Town:</strong> ', person.town, '<br><strong>Start date:</strong> ', person.startDate, '<br><strong>Offer grant:</strong> &pound;', person.grant, '<br><strong>Offer cost:</strong> &pound;', person.cost, '<br><strong>Payments to date:</strong> &pound;', person.payments, '<br><a target="blank_" href="', person.url, '">', person.url, '</a></div></div>'].join('');
            google.maps.event.addListener(marker, 'click', (function (marker, content) {
                return function() {
                    infoWindow.setContent(content);
                    infoWindow.open(map, marker);
                }
            })(marker, content));   
        }
    }

    /*
        Remove marker party map and our list of current markers
        @param int id (id of the marker element)
        @return undefined
    */
    function removePersonMarker(id) {
        if( markers[id] ) {
            markers[id].setMap(null);
            loc = markerList.indexOf(id);
            if (loc > -1) markerList.splice(loc, 1);
            delete markers[id];
        }
    }
    /*
        ======
        FILTER
        ======
    */
    // default all filters off
    var filter = {
        applications: 0,
        constituency: 0,
        town: 0,
        stream: 0,
        startDate: 0,
        party: 0
    }
    var filterMap;
    /*
        Helper function
        @param array a (array of arrays)
        @return array (common elements party all arrays)
    */
    function reduceArray(a) {
        r = a.shift().reduce(function(res, v) {
            if (res.indexOf(v) === -1 && a.every(function(a) {
                return a.indexOf(v) !== -1;
            })) res.push(v);
            return res;
        }, []);
        return r;
    }
    /*
        Helper function
        @param string n
        @return bool
    */
    function isInt(n) {
        return n % 1 === 0;
    }

    /*
        Decides which filter function to call and stacks all filters together
        @param string filterType (the property that will be filtered upon)
        @param string value (selected filter value)
        @return undefined
    */
    function filterCtrl(filterType, value) {
        // result array
        var results = [];
        if( isInt(value) ) {
            filter[filterType] = parseInt(value);
        } else {
            filter[filterType] = value;
        }
        for( k in filter ) {
            if( !filter.hasOwnProperty(k) && !( filter[k] !== 0 ) ) {
                // all the filters are off
                loadMarkers();
                return false;
            } else if ( filter[k] !== 0 ) {
                // call filterMap function and append to r array
                results.push( filterMap[k]( filter[k] ) );
            } else {
                // fail silently
            }
        }
        if( filter[filterType] === 0 ) results.push( personData );
        /*
            if there is 1 array (1 filter applied) set it,
            else find markers that are common to every results array (pass every filter)
        */
        if( results.length === 1 ) {
            results = results[0];
        } else {
            results = reduceArray( results );
        }
        loadMarkers( results );
    }
    /* 
        The keys in this need to be mapped 1-to-1 with the keys in the filter variable.
    */
    filterMap = {
        applications: function( value ) {
            return filterIntsLessThan('applications', value);
        },
        town: function( value ) {
            return filterByString('town', value);
        },
        constituency: function( value ) {
            return filterByString('constituency', value);
        },
        stream: function( value ) {
            return filterByString('stream', value);
        },
        party: function( value ) {
            return filterByString('party', value);
        },
        startDate: function( value ) {
            return filterByString('startDate', value);
        }
    }
    /*
        Filters marker data based upon a string match
        @param string dataProperty (the key that will be filtered upon)
        @param string value (selected filter value)
        @return array (applicants that made it through the filter)
    */
    function filterByString( dataProperty, value ) {
        var applicants = [];
        for( var i=0; i < personData.length; i++ ) {
            var person = personData[i];
            if( person[dataProperty] == value ) {
                applicants.push( person );
            } else {
                removePersonMarker( person.id );
            }
        }
        return applicants;
    }
    /*
        Filters out integers that are under the provided value
        @param string dataProperty (the key that will be filtered upon)
        @param int value (selected filter value)
        @return array (applicants that made it through the filter)
    */
    function filterIntsLessThan( dataProperty, value ) {
            var applicants = [];
            for( var i=0; i < personData.length; i++ ) {
                var person = personData[i];
                if( person[dataProperty] > value ) {
                    applicants.push( person )
                } else {
                    removePersonMarker( person.id );
                }
            }
            return applicants;
    }
    // Takes all the filters off
    function resetFilter() {
        filter = {
            applications: 0,
            constituency: 0,
            town: 0,
            stream: 0,
            startDate: 0,
            party: 0
        }
    }
    return {
        init: init,
        loadMarkers: loadMarkers,
        filterCtrl: filterCtrl,
        resetFilter: resetFilter
    };
}();

$(function() {
    var mapConfig = {
        idSelector: 'map-canvas'
    }
    myMap.init( mapConfig );
    $('.load-btn').on('click', function() {
        var $this = $(this);
        // reset everything
        $('select').val(0);
        myMap.resetFilter();
        myMap.loadMarkers();
        if( $this.hasClass('is-success') ) {
            $this.removeClass('is-success').addClass('is-default');
        }
    });
    $('.applications-select').on('change', function() {
        myMap.filterCtrl('applications', this.value);
    });
    $('.town-select').on('change', function() {
        myMap.filterCtrl('town', this.value);
    });
    $('.constituency-select').on('change', function() {
        myMap.filterCtrl('constituency', this.value);
    });
    $('.stream-select').on('change', function() {
        myMap.filterCtrl('stream', this.value);
    });
    $('.party-select').on('change', function() {
        myMap.filterCtrl('party', this.value);
    });
    $('.startDate-select').on('change', function() {
        myMap.filterCtrl('startDate', this.value);
    });
});

已编辑 尝试使用:在地图上绘制所有标记后。在有pushed all markers的位置使用标记数组。

new MarkerClusterer(map,markers);

请参阅此示例 code.it 它可以帮助您:

<script>
$(document).ready(function(){ 
       ShowHelperMap();
}); 
  function ShowHelperMap() {
        var ctr =new google.maps.LatLng(17.3660, 78.4760);
        var Locations=JSON.parse('[{"Lat":"17.5048667","Lng":"78.4143219"},{"Lat":"17.501313","Lng":"78.4286192"},{"Lat":"17.4865184","Lng":"78.449826"},{"Lat":"17.4963517","Lng":"78.4326133"},{"Lat":"17.4939323","Lng":"78.4420625"},{"Lat":"17.4654334","Lng":"78.4554779"},{"Lat":"17.465164","Lng":"78.45617"},{"Lat":"17.4667402","Lng":"78.4576088"},{"Lat":"17.5043837","Lng":"78.4155832"}]');
         var mapOptions = {
                    center: ctr,
                    zoom: parseInt(10),
                    mapTypeId: google.maps.MapTypeId.ROADMAP,
                    mapTypeControl: false,
                    streetViewControl: false
                  };
         var myInfoWindow = new google.maps.InfoWindow;
        var locationMap = new google.maps.Map(document.getElementById("map"), mapOptions);
        var l;
        var markers=[];
            if (Locations && Locations.length > 0) {
                for (l = 0; l < Locations.length; l++) {
                    store = Locations[l];               
                    var centerMarker = new google.maps.Marker({
                        position: new google.maps.LatLng(parseFloat(store.Lat), parseFloat(store.Lng)),
                        map: locationMap
                    });
                    markers.push(centerMarker);
                }
            }
            new MarkerClusterer(locationMap,markers);
        }

<div id="map" style="width:98%;height:100%;margin:0 auto;" ></div>