【问题标题】:Mapbox - filters override each otherMapbox - 过滤器相互覆盖
【发布时间】:2021-01-04 15:54:50
【问题描述】:

我正在根据此示例创建地图: https://labs.mapbox.com/education/impact-tools/finder-with-filters/

在他们的示例中,他们有两个下拉过滤器和一个复选框过滤器。我想要三个复选框过滤器。我创建了三个复选框过滤器,它们本身似乎运行良好。问题是过滤器似乎按点击的顺序相互覆盖。在他们的示例中,过滤器似乎一起工作,所以当我更改过滤器类型时,我无法弄清楚为什么它不再工作了。

这是我的项目的代码: https://codepen.io/flyinginsect2/pen/eYdyqxZ

这里是过滤相关代码的sn-ps:

const config = {
    style: "mapbox://styles/mapbox/light-v10",
accessToken: "pk.eyJ1IjoibGF1cmFqZWFudGhvcm5lIiwiYSI6ImNraXl5M29oMDEyMjgzM3BhNTh1MGc1NjkifQ.g4IAFIrXPpl3ricw3f_Onw",
    CSV: "https://docs.google.com/spreadsheets/d/106xm254us29hAUEtR7mTo0hwbDJv8dhyQs9rxY601Oc/gviz/tq?tqx=out:csv&sheet=Attributes",
    center: [-104.339, 46.869],
    zoom: 2, 
    title: "ENVIROlocity Mapper",
    description: "Environmental Networking, Volunteering, Internship, and R.... Opportunities",
    sideBarInfo: ["Org_name", "CityState"],
    popupInfo: ["Org_name"],
    filters: [
        {
            type: "checkbox",
            title: "Sector: ",
            columnHeader: "Sector",
            listItems: ["Local Government", "Nonprofit"]
        },
        {
            type: "checkbox",
            title: "Industry: ",
            columnHeader: "Industry_type",
            listItems: ["Conservation", "Policy"]
        },
        {
            type: "checkbox",
            title: "Internships: ",
            columnHeader: "internships_YN",
            listItems: ["Yes"]
        }
    ]

};

const selectFilters = [];
const checkboxFilters = [];

function createFilterObject(filterSettings) {
    filterSettings.forEach(function (filter) {
        if (filter.type === 'checkbox') {
            columnHeader = filter.columnHeader;
            listItems = filter.listItems;

            const keyValues = {};
            Object.assign(keyValues, { header: columnHeader, value: listItems });
            checkboxFilters.push(keyValues);
        }
        if (filter.type === 'dropdown') {
            columnHeader = filter.columnHeader;
            listItems = filter.listItems;

            const keyValues = {};

            Object.assign(keyValues, { header: columnHeader, value: listItems });
            selectFilters.push(keyValues);
        }
    });
}

function applyFilters() {
    const filterForm = document.getElementById('filters');

    filterForm.addEventListener('change', function () {
        const filterOptionHTML = this.getElementsByClassName('filter-option');
        const filterOption = [].slice.call(filterOptionHTML);

        const geojSelectFilters = [];
        const geojCheckboxFilters = [];
        filteredFeatures = [];
        filteredGeojson.features = [];

        filterOption.forEach(function (filter) {
            if (filter.type === 'checkbox' && filter.checked) {
                checkboxFilters.forEach(function (objs) {
                    Object.entries(objs).forEach(function ([key, value]) {
                        if (value.includes(filter.value)) {
                            const geojFilter = [objs.header, filter.value];
                            geojCheckboxFilters.push(geojFilter);
                        }
                    });
                });
            }
            if (filter.type === 'select-one' && filter.value) {
                selectFilters.forEach(function (objs) {
                    Object.entries(objs).forEach(function ([key, value]) {
                        if (value.includes(filter.value)) {
                            const geojFilter = [objs.header, filter.value];
                            geojSelectFilters.push(geojFilter);
                        }
                    });
                });
            }
        });

        if (geojCheckboxFilters.length === 0 && geojSelectFilters.length === 0) {
            geojsonData.features.forEach(function (feature) {
                filteredGeojson.features.push(feature);
            });
        } else if (geojCheckboxFilters.length > 0) {
            geojCheckboxFilters.forEach(function (filter) {
                geojsonData.features.forEach(function (feature) {
                    if (feature.properties[filter[0]].includes(filter[1])) {
                        if (
                            filteredGeojson.features.filter(
                                (f) => f.properties.id === feature.properties.id
                            ).length === 0
                        ) {
                            filteredGeojson.features.push(feature);
                        }
                    }
                });
            });
            if (geojSelectFilters.length > 0) {
                const removeIds = [];
                filteredGeojson.features.forEach(function (feature) {
                    let selected = true;
                    geojSelectFilters.forEach(function (filter) {
                        if (
                            feature.properties[filter[0]].indexOf(filter[1]) < 0 &&
                            selected === true
                        ) {
                            selected = false;
                            removeIds.push(feature.properties.id);
                        } else if (selected === false) {
                            removeIds.push(feature.properties.id);
                        }
                    });
                });
                removeIds.forEach(function (id) {
                    const idx = filteredGeojson.features.findIndex(
                        (f) => f.properties.id === id
                    );
                    filteredGeojson.features.splice(idx, 1);
                });
            }
        } else {
            geojsonData.features.forEach(function (feature) {
                let selected = true;
                geojSelectFilters.forEach(function (filter) {
                    if (
                        !feature.properties[filter[0]].includes(filter[1]) &&
                        selected === true
                    ) {
                        selected = false;
                    }
                });
                if (
                    selected === true &&
                    filteredGeojson.features.filter(
                        (f) => f.properties.id === feature.properties.id
                    ).length === 0
                ) {
                    filteredGeojson.features.push(feature);
                }
            });
        }

        map.getSource('locationData').setData(filteredGeojson);
        buildLocationList(filteredGeojson);
    });
}

function filters(filterSettings) {
    filterSettings.forEach(function (filter) {
        if (filter.type === 'checkbox') {
            buildCheckbox(filter.title, filter.listItems);
        } else if (filter.type === 'dropdown') {
            buildDropDownList(filter.title, filter.listItems);
        }
    });
}

function removeFilters() {
    let input = document.getElementsByTagName('input');
    let select = document.getElementsByTagName('select');
    let selectOption = [].slice.call(select);
    let checkboxOption = [].slice.call(input);
    filteredGeojson.features = [];
    checkboxOption.forEach(function (checkbox) {
        if (checkbox.type == 'checkbox' && checkbox.checked == true) {
            checkbox.checked = false;
        }
    });

    selectOption.forEach(function (option) {
        option.selectedIndex = 0;
    });

    map.getSource('locationData').setData(geojsonData);
    buildLocationList(geojsonData);
}

function removeFiltersButton() {
    const removeFilter = document.getElementById('removeFilters');
    removeFilter.addEventListener('click', function () {
        removeFilters();
    });
}

createFilterObject(config.filters);
applyFilters();
filters(config.filters);
removeFiltersButton();

我阅读了有关组合过滤器的 Mapbox 文档,但我不知道如何使用它。 https://docs.mapbox.com/mapbox-gl-js/style-spec/other/#other-filter

我知道还有许多其他 Stack Exchange 帖子解决了多个标准的过滤问题,但我找不到似乎解决这个特定问题的帖子。

【问题讨论】:

    标签: javascript gis mapbox geospatial mapbox-gl-js


    【解决方案1】:

    问题在于"Local Government" 的值空间

    如果您查看生成的 HTML,您会在 id 中看到一个空格,这是无效的 HTML

    <input class="px12 filter-option" type="checkbox" id="Local Government" value="Local Government">
    

    在构建 HTML id 属性时只需删除空格

    input.setAttribute('id', listItems[i].replace(/\s/g,''));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-23
      • 2017-03-23
      • 2011-08-16
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多