首页 > 解决方案 > 具有多个 HTML 选择过滤器和数组值的 Google Maps JS API

问题描述

我正在开发基于 Google Maps JS API 的自定义商店定位器,并且正在从 JSON 文件中检索所有位置数据。每个商店都可以通过选择过滤器的组合进行过滤。

我的目标是按“商店类型”(字符串)、“品牌”(品牌数组)和“裁缝”(字符串)进行过滤。按字符串(单个值)过滤效果很好,但我被困在“品牌”过滤器上。脚本无法匹配数组中的值。所以我的问题是:我需要修改什么来实现字符串+数组过滤器的组合?

我正在使用以下代码:https ://codepen.io/xtiggerk/pen/GBNPdO

var json = [
      {
        "title" : "Store A",
        "type" : "boutique",
        "brands" : ["Brand A", "Brand B", "Brand C"],
        "tailor" : "tailora",
        "geometry": {
          "type": "Point",
          "coordinates": [
            0.48339843749999994,
            46.89023157359399
          ]
        }
      },
      {
        "title" : "Store B",
        "type" : "boutique",
        "brands" : ["Brand D", "Brand E", "Brand F"],
        "tailor" : "tailorb",
        "geometry": {
          "type": "Point",
          "coordinates": [
            2.7685546874999996,
            47.76148371616669
          ]
        }
      },
      {
        "title" : "Store C",
        "type" : "mall",
        "brands" : ["Brand A", "Brand B", "Brand C"],
        "tailor" : "tailora",
        "geometry": {
          "type": "Point",
          "coordinates": [
            2.57080078125,
            45.882360730184025
          ]
        }
      },
      {
        "title" : "Store D",
        "type" : "mall",
        "brands" : ["Brand D", "Brand E", "Brand F"],
        "tailor" : "tailorb",
        "geometry": {
          "type": "Point",
          "coordinates": [
            -0.098876953125,
            44.52001001133986
          ]
        }
      },
      {
        "title" : "Store E",
        "type" : "popupstore",
        "brands" : ["Brand A", "Brand B", "Brand C"],
        "tailor" : "tailora",
        "geometry": {
          "type": "Point",
          "coordinates": [
            4.54833984375,
            45.874712248904764
          ]
        }
      },
      {
        "title" : "Store F",
        "type" : "popupstore",
        "brands" : ["Brand D", "Brand E", "Brand F"],
        "tailor" : "tailorb",
        "geometry": {
          "type": "Point",
          "coordinates": [
            4.822998046875,
            45.920587344733654
          ]
        }
      }
    ]
var jsonStringify = JSON.stringify(json)
var jsonParse = JSON.parse(jsonStringify); 

var markers = [];
var markerCluster;
var searchInput = jQuery('#searchMap input');
var filterSelect = jQuery('.filter');
var resetButton = jQuery('#resetFilter');



var filterResults = [];
for (var i = 0; i < json.length; i++) {
    var filters = json[i];
    var filtertype = filters.type;
    var filterbrands = filters.brands;
    var filtertailor = filters.tailor;
    filterResults.push(filtertype, filterbrands, filtertailor);       
}

var filterStringify = JSON.stringify(filterResults)
var filterParse = JSON.parse(filterStringify);   


function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 6,
      center: new google.maps.LatLng(45.882360730184025, 2.57080078125)
    });

    for (var i = 0; i < json.length; i++){
        setMarkers(json[i], map);
    }

    markerCluster = new MarkerClusterer(map, markers, {ignoreHiddenMarkers: true, imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'});
}

function setMarkers(marker, map) {
    var markerMap = marker.geometry.coordinates;
    var title = marker.title;
    var type = marker.type;
    var brands = marker.brands;
    var tailor = marker.tailor;
    var pos = new google.maps.LatLng(markerMap[1], markerMap[0]);
    var content = marker;

    markerMap = new google.maps.Marker({
        position: pos,
        title: title,
        type: type,
        brands: brands,
        tailor: tailor,
        map: map
    });

    markers.push(markerMap);

    var infowindow = new google.maps.InfoWindow({
        content: title + '<br/>' + type + '<br/>' + brands + '<br/>' + tailor 
    });    

    // Marker click listener
    google.maps.event.addListener(markerMap, 'click', (function (marker1, content) {
        return function () {
            infowindow.setContent(content);
            infowindow.open(map, markerMap);
            map.panTo(this.getPosition());
            // map.setZoom(15);
        }
    })(markerMap, content));
}

function clusterManager(array) {
    markerCluster.clearMarkers();
    if (!array.length) {
        jQuery('.alert').addClass('is-visible');
    } else {
        jQuery('.alert').removeClass('is-visible');
        for (i=0; i < array.length; i++) {
            markerCluster.addMarker(array[i]);
        }
    }
}

//@todo add inputsearch
function newFilter(filterType1 = 'all', filterType2 = 'all', filterType3 = 'all') {
    var criteria = [
        { Field: "type", Values: [filterType1] },
        { Field: "brands", Values: [filterType2] },
        { Field: "tailor", Values: [filterType3] },
        // { Field: ["type", "tailor", "brands"], Values: [filterTyped] }
      ];

    var filtered = markers.flexFilter(criteria);
    clusterManager(filtered);
}

Array.prototype.flexFilter = function(info) {
    // Set our variables
    var matchesFilter, matches = [], count;

    // Helper function to loop through the filter criteria to find matching values
    // Each filter criteria is treated as "AND". So each item must match all the filter criteria to be considered a match.
    // Multiple filter values in a filter field are treated as "OR" i.e. ["Blue", "Green"] will yield items matching a value of Blue OR Green.
    matchesFilter = function(item) {
      count = 0
      for (var n = 0; n < info.length; n++) {
        if (info[n]["Values"].indexOf(item[info[n]["Field"]]) > -1) {
            count++;
        }
        //if value = all, return all item
        else if (info[n]["Values"] == "all") {
            count++;
        }
      }
      // If TRUE, then the current item in the array meets all the filter criteria
      return count == info.length;
    }

    // Loop through each item in the array
    for (var i = 0; i < this.length; i++) {
      // Determine if the current item matches the filter criteria
      if (matchesFilter(this[i])) {
        matches.push(this[i]);
      }
    }

    // Give us a new array containing the objects matching the filter criteria
    return matches;
  }



jQuery(document).ready(function() {
  jQuery('.filter-type').on('change', function(){       
    var filter2 = jQuery('.filter-brands').val();
    var filter3 = jQuery('.filter-tailor').val();
    newFilter(jQuery(this).val(), filter2, filter3);
  });

  jQuery('.filter-brands').on('change', function(){
    var filter1 = jQuery('.filter-type').val();
    var filter3 = jQuery('.filter-tailor').val();
    newFilter(filter1, jQuery(this).val(), filter3);
  });

  jQuery('.filter-tailor').on('change', function(){
    var filter1 = jQuery('.filter-type').val();
    var filter2 = jQuery('.filter-brands').val();
    newFilter(filter1, filter2, jQuery(this).val());
  });

    searchInput.on('keyup', function () {
          var searchTyped = $(this).val();
          var arr = [];
          if (searchTyped.length > 0) {
              jsonParse.filter(function() {
                  for (i = 0; i < json.length; i++) {
                      marker = markers[i];
                      var markerFilter = [];
                      var filtertype = marker.type;
                      var filterbrands = marker.brands;
                      var filtertailor = marker.tailor;

                      markerFilter.push(filtertype, filterbrands, filtertailor); 
                      var markerFilterStringify = JSON.stringify(markerFilter);
                      if( markerFilterStringify.indexOf(searchTyped) >= 0) {
                          arr.push(marker);
                      } else {
                          console.log('dont fit requirement')
                      }
                  }
              });
              clusterManager(arr);
          } else {
              newFilter();
          }
      });

    resetButton.on('click', function() {
        searchInput.val('');
        filterSelect.val('all');
        newFilter();
    });

    //delete all duplicated value from the previous array
    var uniqueValue = [];
    jQuery.each(filterResults, function(i, el){
        if(jQuery.inArray(el, uniqueValue) === -1) {
            uniqueValue.push(el);
        } 
    });

    var substringMatcher = function(strs) {
        return function findMatches(q, cb) {
        var matches, substringRegex;
        matches = [];

        substrRegex = new RegExp(q, 'i');

        jQuery.each(strs, function(i, str) {
            if (substrRegex.test(str)) {
            matches.push(str);
            }
        });
        cb(matches);
        };    
    };
    searchInput.typeahead({
        hint: true,
        highlight: true,
        minLength: 1
    },
    {
        tailor: 'customFilter',
        source: substringMatcher(uniqueValue)
    });

});


jQuery(window).on('load', function(){
    initMap();
});

标签: jsongoogle-mapsselectfiltermaps

解决方案


您可以尝试matchesFilter按如下方式更改您的功能:

matchesFilter = function(item) {
    count = 0
    for (var n = 0; n < info.length; n++) {

        var values = info[n]["Values"];
        var fieldArr = item[info[n]["Field"]];

        if (values.indexOf(fieldArr) > -1) {
            count++;
        }
        //if value = all, return all item
        else if (values == "all") {
            count++;
        } else {
            //if value is an array, loop through it to find a match using includes() method
            if (values instanceof Array) {
                for (var j = 0; j < values.length; j++) {
                    if (fieldArr.includes(values[j])) {
                        count++;
                    }
                }
            }
        }
    }
    // If TRUE, then the current item in the array meets all the filter criteria
    return count == info.length;
}

希望这可以帮助!


推荐阅读