Фильтровать маркеры Google Map с несколькими [и пересекающимися] флажками

Я не могу заставить свою систему фильтрации с несколькими флажками работать. Я объясню проблему, исследование, которое я провел здесь по stackoverflow, и почему мне все еще нужна помощь после этого.

Моя проблема в том, что мои флажки не могут вернуть маркеры, когда я постепенно снимаю их. Эти упомянутые фильтры хорошо работают, когда я нажимаю на них, потому что они постепенно исчезают связанные с ними маркеры. Однако после снятия нескольких флажков все маркеры снова появляются на экране, а последние флажки ничего не делают, когда их окончательно не щелкают.

Это временный URL-адрес проекта: http://www.lcc.gatech.edu/~amartell6/php/main12.php

Это код, в котором я застрял:

//this getJson function exists within an init funciton where a map 
//has already been called
$.getJSON(theUrl,function(result){



    $.each(result, function(i, item){

        //get Longitude
        var latCoord = item.coordinate;
        var parenthCoord = latCoord.indexOf(",");
        var partiaLat = latCoord.substr(1,parenthCoord-1);
        var lat = parseFloat(partiaLat);
        //alert(lat);

        //get Latitude
        var lngCoord = item.coordinate;
        var commaCoord = lngCoord.indexOf(",");
        var partiaLng = lngCoord.substr(commaCoord+1);
        var lng = parseFloat(partiaLng);
        //alert(lng);


        // display ALL the story markers
        var storyMarker;
        storyMarker = new google.maps.Marker({
            position: new google.maps.LatLng(lat, lng),// ----- > whithin the mutidimentional array, 
            map: map
        });


        //display the stories by clicking on the markers
        google.maps.event.addListener(storyMarker, 'click', function() {
            var from = "From ";
            if(item.end_date != ""){
                item.end_date = " to " + item.end_date;
            }
            else{
                from = "";
            }

            $('#output').html(
                '<p><span class="selected">Type of Entry: </span>' + 
                item.entry_type + ' <br/><br/>'+
                '<span class="selected">Title: </span>'+ item.entry_title + '<br/><br/>' +
                '<span class="selected">Date(s):</span><br/>'+ from +item.start_date+
                //' to '+item.end_date+'<br/><br/>'+
                item.end_date+'<br/><br/>'+
                '<span class="selected">Content:</span><br/><br/> '+ item.entry 
                +'</p>'
            );
        });// end of story displays


        //call filters from filter funciton
        filter('#evacuation-filter',item.evacuation,"Yes");
        filter('#evacuation-order-filter',item.evacuation_order,"Yes");
        filter('#w-nearby-filter',item.w_nearby,"Yes");
        filter('#hurricane-reached-filter',item.hurricane_reached,"Yes");
        filter('#outdoors-filter',item.in_out_doors,"Outdoors Most of the Time");
        filter('#indoors-filter',item.in_out_doors,"Indoors Most of the Time");
        filter('#food-filter',item.food,"Yes");
        filter('#windows-filter',item.windows,"Yes");
        filter('#power-filter',item.power,"Yes");
        filter('#wounded-filter',item.wounded,"Yes");
        filter('#looting-filter',item.looting,"Yes");
        filter('#blackouts-filter',item.blackouts,"Yes");
        filter('#trees-filter',item.trees,"Yes");
        filter('#powerlines-filter',item.powerlines,"Yes");
        filter('#light-filter',item.light,"Yes");
        filter('#sidewalks-filter',item.sidewalks,"Yes");
        filter('#buildings-filter',item.buildings,"Yes");
        filter('#flooding-filter',item.flooding,"Yes");


        //FILTER FUNCTION
        //first parameter is the checkbox id, the second is the filter criteria
        //(the filter function has to be called within the $.each loop to be within scope)

        var otherFilter = false;

        function filter(id, criterion1, value){

            var activeFilters = [];

            $(id).change(function() {
                //evalute if the checkbox has been "checked" or "unchecked"
                var checkBoxVal = $(id).attr("checked");

                //if it's been checked:
                if(checkBoxVal=="checked"){
                    //1 - Get markers that don't talk about the filter
                    if(criterion1!=value && storyMarker.getVisible()==true){
                        //2 - fade them away, and leave only those meet the criteria
                        storyMarker.setVisible(false); 
                        otherFilter = true;
                        activeFilters.push(criterion1);
                        //document.getElementById("text3").innerHTML=activeFilters+"<br/>";
                        //alert(activeFilters.push(criterion1) +","+criterion1.length);
                    }
                }
                //if it's been unchecked:
                else if(checkBoxVal==undefined){
                    //1 - Get markers that don't talk about the filter
                    if(criterion1!=value && storyMarker.getVisible()==false){
                        //2 - Show them again
                        storyMarker.setVisible(true);
                        otherFilter = false;
                        activeFilters.pop(criterion1);
                        //alert(activeFilters.pop(criterion1) +","+criterion1.length);
                    } //end of if to cancel filter and bring markers and stories back
                }

            }); // end of change event

        } // end of filter function


        //var otherDropDown = false;
        filter2("#media-filter",item.media);
        filter2("#authorities-filter",item.authorities);

        //---------------

        function filter2(id2,criterion2){

            $(id2).change(function() {
                //get the value of the drowpdown menu based on its id
                var dropDownVal = $(id2).attr("value");
                var all="All";
                //if the value isn't "All", other filters have not been applied, and marker is on screen
                if(dropDownVal!=all && otherFilter==false){
                    //1 - check if the marker doesn't comply with filter
                    if(criterion2!=dropDownVal){
                        //2 - fade them away if not, and leave only those meet the criteria
                        storyMarker.setVisible(false);
                    //3 - If the marker does comply with it
                    }else if(criterion2==dropDownVal){
                        //4 - keep it there
                        storyMarker.setVisible(true);
                    }//end of filter applier
                //else if if the value IS "All", filters have not been applied, and marker is faded
                }else if(dropDownVal==all && otherFilter==false){
                    //select all the possible values for the cirterion
                    if(criterion2!=undefined){
                        //and show all those markers
                        storyMarker.setVisible(true);
                    }
                }
            }); 
        }   //end of function filter2



    }); // end of $.each
}); // end of $.getJSON

Я нашел один связанный пост в блоге. Этот предлагает добавить категорию к маркерам. Однако, когда я это делаю, фильтры продолжают работать так же. Я думаю, это происходит потому, что каждый фильтр запрограммирован на скрытие каждого отдельного маркера, соответствующего их критериям выбора, но каждый маркер имеет более одного свойства, по которому их можно фильтровать.

Знаете ли вы, есть ли способ заставить скрипт определять, сколько фильтров указывает на один и тот же маркер, и отображать его только в том случае, если на него не указывает ни один фильтр? Это мое предположение о том, как это решить, хотя я не знаю, как это сделать в коде.

Наконец, если вы знаете альтернативные способы заставить фильтры работать, дайте мне знать.


person asraelarcangel    schedule 05.03.2012    source источник
comment
Я поделился кодом с другом. По его мнению, проблема в том, что вся логика функции фильтра ущербна, и предложил переписать ее с нуля. Он сказал, что функция не работает, потому что в настоящее время она обрабатывает параметры фильтрации отдельно друг от друга. Вместо этого я мог бы начать с проверки того, установлен ли хотя бы один из флажков. Следующим шагом будет проверка того, сколько из них действительно проверено. Наконец, поля должны объединять прикрепленные к ним параметры фильтрации в один условный оператор, который будет отображать/скрывать маркеры. Проблема в том, чтобы закодировать это. Я еще понятия не имею.   -  person asraelarcangel    schedule 06.03.2012


Ответы (2)


Я создал приложение с похожей логикой несколько лет назад http://www.ioos.gov/catalog/. Но это было для GMap 2.0 но думаю логика будет та же. Мой подход состоял в том, чтобы расширить объект маркера карт Google (уже раздутый) функциями, по которым я хотел их отфильтровать. Это будут все свойства, которые вы храните в своем прослушивателе кликов, и, возможно, больше: например. item.title, item_start_date и т. д. все, по чему вы в конечном итоге захотите отфильтровать свой маркер.

var all_markers = [];
storyMarker.end_date = item.end_date;
storMarker.title = item.title;
...
all_markers.push(storyMarker);

Затем, когда вы хотите отфильтровать цикл по всем маркерам, проверьте значение маркера на соответствие условию фильтра и установитеVisible(true) или false по мере необходимости.

person Eric Bridger    schedule 06.03.2012
comment
Большое спасибо. Я тестирую ваше решение. Я нашел альтернативу прямо перед тем, как прочитать ваш ответ, но я не думаю, что это самый эффективный способ. - person asraelarcangel; 06.03.2012

Эрик уже предложил решение моей проблемы. Тем не менее, я думаю, что сообществу могут быть полезны другие варианты, и я хочу поделиться решением, которое я придумал. Даже если он может быть не самым эффективным, он работает.

В коде, который я только что упомянул, я объявил все storyMarkers сразу при инициализации карты:

        // display ALL the story markers
        var storyMarker;
        storyMarker = new google.maps.Marker({
            position: new google.maps.LatLng(lat, lng),// ----- > whithin the mutidimentional array, 
            map: map
        });

Теперь я добавил новый аргумент к маркерам, но вместо создания переменной, как в примере, который я нашел в другом посте, этот аргумент был пустым массивом:

storyMarker.pointer = [];

Предыдущая функция фильтра имела три уровня. Первый уровень обнаружил изменение флажка. Второй проверял, был ли флажок установлен или снят. Третий уровень запустил фильтр на маркер e-v-e-r-y, чтобы показать или скрыть его.

Здесь началось мое решение. В самом внутреннем операторе if функции фильтра я добавил произвольный элемент в массив указателей:

storyMarker.pointer.push("элемент");

Сразу после этого я вложил новый оператор if, чтобы проверить, не пуст ли массив. Если он действительно не пуст, программа скрывает маркер, которому принадлежит этот массив.

Программа инвертирует логику, когда флажок снят. Он вызывает фильтр, вычитает один элемент из массива, связанного с этим маркером, а затем проверяет, есть ли другие связанные с ним маркеры. Теперь система показывает только те маркеры, массивы которых пусты.

//alert(storyMarker.pointer);
        function filter(id,criterion,value){
            $(id).change(function() {
                var checkBoxVal = $(id).attr("checked");
                if(checkBoxVal=="checked"){
                    if(criterion!=value){
                        storyMarker.pointer.push("element");
                        //alert("array length: "+storyMarker.pointer.length);
                        if(storyMarker.pointer.length>0){
                            storyMarker.setVisible(false);
                        }
                    }
                }
                else if(checkBoxVal!="checked"){
                    if(criterion!=value){
                        storyMarker.pointer.pop("element");
                        //alert("array length: "+storyMarker.pointer.length);
                        if(storyMarker.pointer.length<=0){
                            storyMarker.setVisible(true);
                        }
                    }
                }
            });
        }

Таким образом, скрипт по-прежнему щелкает маркер несколько раз, если пользователь щелкает более одного маркера. Теперь система может распознавать, сколько раз был указан один маркер, и показывать только тот, на котором вообще нет указателей.

person asraelarcangel    schedule 06.03.2012