适用于 JavaScript 的 ArcGIS API、Web 应用程序中的 geoJSON 图层过滤器?

问题描述

我正在使用适用于 JavaScript 的 ArcGIS API 处理 3D 地球,总体而言,它运行良好。但是,我在处理 GeoJSON 文件时遇到了一个挑战。

我在地球上添加一个 GeoJSON 层,它基本上保存了世界上几个有趣的地质特征的信息。我为每个位置添加一个弹出窗口和一个符号。但是,所有这些位置都属于不同的类别,例如珊瑚礁、火山、矿床等等。我想添加某种过滤器,以便用户可以选择他们想要在这个地球上探索的类别。

这对于 GeoJSON 层是否可行,如果是,我该如何实现?如果有人能在正确的方向上给我一个推动或一些可能的建议,我将不胜感激。

或者,不同类别的不同符号和图例也可以。我找到了有关它如何与常规要素图层配合使用的信息。尽管如此,我还是找不到有关如何将其应用于 GeoJSON 图层的教程。

这是我的第一个编码项目,非常感谢所有帮助。

解决方法

如果您使用的是 GeoJSON 源,那么您将必须在客户端处理数据,这意味着您在检索源时获得的特征。

在您的情况下,要过滤或查询特征,您可以使用图层(GeoJSONViewLayer 对象)的视图图层。

这是了解它是什么以及如何处理服务器(远程)或客户端(本地)数据的好读物,ArcGIS Docs - Query/Filter

无论如何,我给你做了一个简单的例子来掌握,

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>GeoJSONLayer</title>

    <style>
        html,body,#viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }

        #controls {
            width: 500px;
        }

        #outerContainer {
            padding: 15px;
            width: 500px;
        }
    </style>

    <link rel="stylesheet" href="https://js.arcgis.com/4.16/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.16/"></script>

    <script>
        require([
            "esri/Map","esri/layers/GeoJSONLayer","esri/views/MapView","esri/widgets/Expand","esri/widgets/HistogramRangeSlider","esri/smartMapping/statistics/histogram","esri/core/promiseUtils"
        ],function (
            Map,GeoJSONLayer,MapView,Expand,HistogramRangeSlider,histogram,promiseUtils
        ) {
            // layer set up
            const url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson";
            const template = {
                title: "Earthquake Info",content: "Magnitude {mag} {type} hit {place} on {time}",fieldInfos: [
                    {
                        fieldName: 'time',format: {
                            dateFormat: 'short-date-short-time'
                        }
                    }
                ]
            };
            const renderer = {
                type: "simple",field: "mag",symbol: {
                    type: "simple-marker",color: "rgba(225,125,0.5)",outline: {
                        color: "rgba(225,0.5)"
                    }
                },visualVariables: [{
                    type: "size",stops: [
                        { value: 1,size: "1px" },{ value: 2,size: "2px" },{ value: 3,size: "4px" },{ value: 4,size: "8px" },{ value: 5,size: "16px" },{ value: 6,size: "32px" },{ value: 7,size: "64px" }
                    ]
                }]
            };
            const layer = new GeoJSONLayer({
                url: url,copyright: "USGS Earthquakes",popupTemplate: template,renderer: renderer
            });
            // map and view set up
            const map = new Map({
                basemap: "gray",layers: [layer]
            });
            const view = new MapView({
                container: "viewDiv",center: [10,10],zoom: 3,map: map
            });
            view.whenLayerView(layer).then(layerView => {
                
                // filter logic
                const today = new Date(Date.now());
                const breaks = [
                    new Date(today.getFullYear(),today.getMonth(),1),new Date(today.getFullYear(),7),14),21),today.getMonth() + 1,0),]
                const weeks = [true,true,true];
                const condition = document.getElementById("conditionSpan");
                const inputs = document.querySelectorAll("input[type='checkbox']");
                const updateCondition = _ => {
                    const conditions = [];
                    for (let i = 0; i < 4; i++) {
                        weeks[i] = inputs[i].checked;
                    }
                }
                const updateConditionText = _ => {
                    const conditions = [];
                    for (let i = 0; i < 4; i++) {
                        if (weeks[i]) {
                            conditions.push(
                                `(updated >= ${breaks[i].toDateString()} AND updated <= ${breaks[i + 1].toDateString()})`
                            )
                        }
                    }
                    condition.innerText = conditions.join(" OR ");
                };
                const updateLayer = _ => {
                    const conditions = [];
                    for (let i = 0; i < 4; i++) {
                        if (weeks[i]) {
                            conditions.push(
                                `(updated >= ${breaks[i].getTime()} AND updated <= ${breaks[i + 1].getTime()})`
                            )
                        }
                    }
                    layerView.filter = { where: conditions.length === 0 ? "false" : conditions.join(" OR ") };
                }
                inputs.forEach(input => input.addEventListener("click",_ => {
                    updateCondition();
                    updateConditionText();
                    updateLayer();
                }));
                updateCondition();
                updateConditionText();
            });
        });
    </script>
</head>

<body>
    <div class="esri-widget">
        <h3>Filter Month Earthquakes By Week</h3>
        <input id="week1" type="checkbox" value="1" checked><label for="week1">First Week</label>
        <input id="week2" type="checkbox" value="2" checked><label for="week2">Second Week</label>
        <input id="week3" type="checkbox" value="3" checked><label for="week3">Third Week</label>
        <input id="week4" type="checkbox" value="4" checked><label for="week4">Last Week</label>
        <p>Condition: <span id="conditionSpan"></span></p>
    </div>
    <div id="viewDiv"></div>
</body>

</html>