Hello all.
I'm a very much new to JS and so am simply copying and pasting code from samples to make this custom widget.
This is simply a hardcoded widget that when enabled will create buffers around a points hosted feature layer in AGOL (my own content). My end goal is to use a field with distance values for the buffer sizes, but for now I just want them to draw a uniform buffer.
When I click on Enable Buffer, I don't see anything, but I'm not getting any error messages. I'm using this in CodePen.
This is the code I'm using. The bold parts are where I think there could be an issue. (I removed the style and html portion).
Much appreciate any feedback.
JS :
require([
"esri/config",
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/renderers/SimpleRenderer",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/geometryEngine"
], function(esriConfig, Map, MapView, FeatureLayer, SimpleRenderer, Graphic, GraphicsLayer, geometryEngine) {
esriConfig.apiKey = "deleted";
//add basemap
const map = new Map({
basemap: "arcgis-imagery" //Basemap layer service
});
//add map view
const view = new MapView({
map: map,
center: [31.205, 49.627], //Longitude, latitude
zoom: 8,
container: "viewDiv"
});
//add new graphics layers for buffers
const graphicsLayer = new GraphicsLayer();
const resultsLayer = new GraphicsLayer();
map.addMany([graphicsLayer, resultsLayer]);
// define style for GPS points layer
let GPS_Renderer = {
type: "simple", // autocasts as new SimpleRenderer()
symbol: {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
size: 6,
color: "orange",
outline: { // autocasts as new SimpleLineSymbol()
width: 0.5,
color: "white"
}
}
};
// add feature layer from URL --
const hitsGPS = new FeatureLayer({
url: "https://services8.arcgis.com/39j38RHYsO16guxW/arcgis/rest/services/GPS_Hits/FeatureServer",
renderer: GPS_Renderer
});
// add GPS layer to the map
map.add(hitsGPS);
// add controls to the top of the screen
view.ui.add(document.getElementById("controls"), "top-right");
document.getElementById("buffer").addEventListener("click", createBuffer);
document.getElementById("reset").addEventListener("click", resetGraphics);
// create buffer function
let bufferGraphic;
function createBuffer() {
if (bufferGraphic) {
return;
}
// execute buffer
const buffer = geometryEngine.geodesicBuffer(
hitsGPS.geometry,
100,
"kilometers"
);
// save resulting buffer as graphic
bufferGraphic = new Graphic({
geometry: buffer,
symbol: {
type: "simple-fill",
color: [227, 139, 79, 0.25],
outline: {
color: [255, 255, 255, 255],
},
},
});
// add graphic to map
graphicsLayer.add(bufferGraphic);
}
// reset function
function resetGraphics() {
graphicsLayer.remove(bufferGraphic);
resultsLayer.removeAll();
bufferGraphic = null;
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="controls" class="esri-widget">
<button id="buffer" class="esri-button">Enable Buffer</button>
<button id="reset" class="esri-button esri-button--secondary">Disable Buffer</button>
</div>
</body>
</html>
Solved! Go to Solution.
You can not call hitsGPS.geometry. HitsGPS is a featurelayer and does not have a geometry property you have to iterate over the results of a query on the featurelayer. Something like this (untested code)
const sym = {
type: "simple-fill",
color: [227, 139, 79, 0.25],
style: "solid",
outline: {
color: [255, 255, 255, 255],
width: 1
}
};
hitsGPS.queryFeatures().then(results){
results.features.map(feat => {
const buffer = geometryEngine.geodesicBuffer(feat.geometry, 100, "kilometers");
bufferGraphic = new Graphic({geometry: buffer, symbol: sym});
// add graphic to map
graphicsLayer.add(bufferGraphic);
});
}
You can not call hitsGPS.geometry. HitsGPS is a featurelayer and does not have a geometry property you have to iterate over the results of a query on the featurelayer. Something like this (untested code)
const sym = {
type: "simple-fill",
color: [227, 139, 79, 0.25],
style: "solid",
outline: {
color: [255, 255, 255, 255],
width: 1
}
};
hitsGPS.queryFeatures().then(results){
results.features.map(feat => {
const buffer = geometryEngine.geodesicBuffer(feat.geometry, 100, "kilometers");
bufferGraphic = new Graphic({geometry: buffer, symbol: sym});
// add graphic to map
graphicsLayer.add(bufferGraphic);
});
}
Robert,
Thanks for this answer. I added the code and it works but the range ring doesn't appear but that's an Uncaught TypeError I will figure out. But this looks promising.
If I wanted to use a field value for the distance instead of a hardcoded distance, is it possible to use a variable in place of the '100'?
Thanks again!
Sure you can easily do that inside the feature loop.
hitsGPS.queryFeatures().then(results){
results.features.map(feat => {
const buffer = geometryEngine.geodesicBuffer(feat.geometry, parseInt(feat.attributes['someFieldName']), "kilometers");
bufferGraphic = new Graphic({geometry: buffer, symbol: sym});
// add graphic to map
graphicsLayer.add(bufferGraphic);
});
}