Hey everyone,
I've been currently working on a JavaScript API application and I'm stuck on how to formulate a query based on a polygon's geometry...
Right now I have a layer containing a set of polygons and another layer with a set of points. I have a query that returns a set points based on the radius of a bufferGraphic.
Now I need to query these points if they fall within a polygon selection; i.e. the user clicks on the polygon which he/she wants to query and then return the same data as this current code I wrote does.
Any assistance on how to accomplish this would be a huge help! @BlakeTerhune
<html>
<body>
<button id="myButton" type>Query Selected Datasets</button>
<button id="myButton2" type>Query Selected Datasets within Polygons</button>
<div id="viewDiv"></div>
<div id="panel"></div>
<div id="mySQL"></div>
</body>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>ArcGIS API for Javascript: SCCWRP Water</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 95%;
width: 100%;
}
#titleDiv {
padding: 10px;
}
#titleText {
font-size: 20pt;
font-weight: 60;
padding-bottom: 10px;
}
</style>
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" type="text/javascript"></script>
<script src="https://js.arcgis.com/4.21/"></script>
<script>
json_array = [];
// set distance and units - get dots within that boundary
distance = 0.5;
units = "miles";
require([
"esri/Map",
"esri/Graphic",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/widgets/LayerList",
"esri/renderers/SimpleRenderer",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/renderers/UniqueValueRenderer",
"esri/widgets/Legend",
"esri/widgets/BasemapGallery",
"esri/widgets/Expand",
"esri/core/watchUtils",
], function (Map, Graphic, MapView, FeatureLayer, LayerList, SimpleRenderer, SimpleLineSymbol, UniqueValueRenderer, SimpleFillSymbol, Legend, BasemapGallery, Expand, watchUtils) {
const map = new Map({ // creating a new map
basemap: "satellite"
});
var view = new MapView({ // take that new map we just made above and display it
container: "viewDiv",
map: map,
// center: [-118.243683, 34.052235],
// zoom: 5,
popup: {
autoOpenEnabled: false,
dockEnabled: true,
dockOptions: {
// dock popup at bottom-right side of view
buttonEnabled: true,
breakpoint: false,
position: "bottom-right"
}
}
});
// County label + renderer + feature layer + add layer
const countyLabel = ({
symbol: {
type: "text", // autocasts as new TextSymbol()
color: "white",
font: { // autocast as new Font()
family: "Playfair Display",
size: 12,
weight: "regular"
}
},
labelPlacement: "above-center",
labelExpressionInfo: {
expression: "$feature.NAME_PCASE"
},
deconflictionStrategy: "none"
});
const countyRend = {
type: "simple", // autocasts as new SimpleRenderer()
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [0, 76, 115, 0.1],
outline: { // autocasts as new SimpleLineSymbol()
width: 1,
color: "white"
}
}
};
const counties = new FeatureLayer({
url: "https://gis.sccwrp.org/arcserver/rest/services/Hosted/Counties/FeatureServer",
renderer: countyRend,
title: "Counties",
labelingInfo: countyLabel
});
map.add(counties);
// Stations label + renderer + feature layer + add layer
let renderer = {
type: "unique-value",
field: "grp",
uniqueValueInfos: [{
value: "Projects",
symbol: {
size: 3,
type: "simple-marker",
color: [0, 255, 255],
outline: null
},
label: "Projects"
}, {
value: "Regional Monitoring",
symbol: {
size: 3,
type: "simple-marker",
color: [0, 0, 139],
outline: null
},
label: "Regional Monitoring"
}]
};
const layer = new FeatureLayer({
// autocasts as new PortalItem()
portalItem: {
id: "4ce8725b7968421eaa945025e2eca221"
},
renderer: renderer,
outFields: ["*"]
});
map.add(layer);
// Merging the 2 files together...
//create graphic for mouse point click
// Create graphic for distance buffer
const pointGraphic = new Graphic({
symbol: {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [0, 0, 139],
outline: {
color: [255, 255, 255],
width: 1.5
}
}
});
const bufferGraphic = new Graphic({
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [173, 216, 230, 0.2],
outline: {
// autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 1
}
}
});
layer.load().then(() => {
// Set the view extent to the data extent
view.extent = layer.fullExtent;
layer.popupTemplate = layer.createPopupTemplate();
loadLayerList();
});
view.on("click", (event) => {
view.graphics.remove(pointGraphic);
if (view.graphics.includes(bufferGraphic)) {
view.graphics.remove(bufferGraphic);
}
queryFeatures(event);
});
function findLayerByTitle(title) {
return view.map.allLayers.find(function (layer) {
console.log(layer.title);
return layer.title === title;
});
};
let layerList, analysisLayer;
function loadLayerList() {
console.log("loadLayerList");
console.log(json_array);
};
function queryFeatures(screenPoint) {
console.log("click:");
const point = view.toMap(screenPoint);
console.log(point);
console.log(point.latitude);
console.log(point.longitude);
layer
.queryFeatures({
geometry: point,
distance: distance,
units: units,
spatialRelationship: "intersects",
returnGeometry: false,
returnQueryGeometry: true,
outFields: ["*"]
})
.then((featureSet) => {
// set graphic location to mouse pointer and add to mapview
pointGraphic.geometry = point;
view.graphics.add(pointGraphic);
// open popup of query result
console.log(featureSet);
console.log(featureSet);
view.popup.open({
location: point,
features: featureSet.features,
featureMenuOpen: true
});
if (featureSet.queryGeometry) {
bufferGraphic.geometry = featureSet.queryGeometry;
view.graphics.add(bufferGraphic);
}
featureSet.features.forEach(function (item, index) {
//console.log(featureSet.features[index].attributes);
json_array.push(featureSet.features[index].attributes);
//console.log(featureSet.features[0].attributes);
});
});
};
// Query the layer view for statistics on each analysis variable in the layer
function queryLayerViewStats(layerView) {
query = layerView.layer.createQuery();
query.geometry = layerView.extent;
return layerView.queryFeatures(query).then(function (response) {
stats = response.features[0].attributes;
});
};
function formatTable(station, origin_fname, datatype, json) {
console.log("formatTable");
stationdiv = "#" + CSS.escape(station) + "-" + CSS.escape(datatype);
var el = document.querySelector(stationdiv);
console.log(el);
fieldnames = [];
fieldvalues = [];
Object.keys(json.fields).forEach(function (item) {
fieldnames.push(json.fields[item].name);
});
Object.keys(json.features).forEach(function (feature_index) {
fieldvalues[feature_index] = json.features[feature_index].attributes;
});
console.log(fieldnames);
console.log(fieldvalues);
if (json.fields != "empty") {
let table = new simpleDatatables.DataTable(stationdiv, {
data: {
headings: fieldnames,
data: fieldvalues.map(item => Object.values(item))
},
});
} else {
console.log("empty");
};
};
function retrieveData(station, origin_fname, datatype, url) {
h4 = ""
table = document.createElement("table"),
h4 = document.createElement("h4"),
table.id = station + "-" + datatype;
h4.innerHTML = table.id;
document.body.appendChild(h4);
document.body.appendChild(table);
search_url = url + "/query?where=" + origin_fname + "='" + station + "'&outFields=*&f=json";
console.log("search_url:" + search_url);
protocol = "GET";
fetch(search_url, { method: protocol, cache: "no-cache", }).then(function (response) { return response.json(); }).then(function (data) { console.log(data); formatTable(station, origin_fname, datatype, data); }).catch(function (err) { console.log("We had a problem Houston", err); });
};
document.querySelector('#myButton').addEventListener("click", function (event, ui) {
str = " ";
json_array.forEach(function (item, index) {
console.log(item);
str += retrieveData(item.stationid, item.origin_fname, item.dtp, item.link);
});
console.log(str);
});
var layerlist = new LayerList({ // this right here creates a layerlist or "dropdown" menu so that one can toggle off / on any of the layers that are present
view: view
});
var basemapGallery = new BasemapGallery({ // This right here provides the gallery of basemaps users can pull from. I think.
view: view,
container: document.createElement("div")
});
var bgExpand = new Expand({ // This gives users the ability to choose which basemap they want to use
view: view,
content: basemapGallery
});
var legend = new Expand({
content: new Legend({
view: view,
style: "classic"
}),
view: view,
expanded: true
});
view.ui.add(layerlist, { position: "bottom-right" });
view.ui.add(bgExpand, "top-left");
view.ui.add(legend, "bottom-left");
view.ui.add("titleDiv", "top-right"); // for "SCCWRP California Water Data" title on top right
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="titleDiv" class="esri-widget">
<div id="titleText">SCCWRP California Water Data</div>
</body>
</html>
s the data of each point