问题描述
我正在使用适用于 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>