Select to view content in your preferred language

Featureeffect issue

519
0
05-20-2025 11:51 PM
banu
by
Emerging Contributor

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Intro to FeatureLayer | Sample | ArcGIS Maps SDK for JavaScript 4.33</title>

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

<style>
html,

let map, view, Programs, Well, Segment, ProgramIds, SegmentIds, WellIds, searchWidget, sketchGeometry, Selectedvalue, results, layer, zoomin, zoomout;
let sketchRecButton, sketchButton, zoomToSelectButton, clearButton, distanceMeasurement2D, areaMeasurement2D;
let sketchGeometries = [];

const [MapView, Map, FeatureLayer, ImageryLayer, GroupLayer, GraphicsLayer, Graphic, geometryEngine, Search, Home, Expand, SketchViewModel, geometryEngineAsync, LayerList,
AreaMeasurement2D, PictureMarkerSymbol, SimpleLineSymbol, Legend, reactiveUtils, AreaMeasurement2DViewModel, DistanceMeasurement2D, BasemapToggle] =
await $arcgis.import(["@arcgis/core/views/MapView.js", "@arcgis/core/Map.js", "@arcgis/core/layers/FeatureLayer.js", "@arcgis/core/layers/ImageryLayer.js", "@arcgis/core/layers/GroupLayer.js",
"@arcgis/core/layers/GraphicsLayer.js", "@arcgis/core/Graphic.js", "@arcgis/core/geometry/geometryEngine.js", "@arcgis/core/widgets/Search.js",
"@arcgis/core/widgets/Home.js", "@arcgis/core/widgets/Expand.js", "@arcgis/core/widgets/Sketch/SketchViewModel", "@arcgis/core/geometry/geometryEngineAsync.js",
"@arcgis/core/widgets/LayerList.js", "@arcgis/core/widgets/AreaMeasurement2D.js", "@arcgis/core/symbols/PictureMarkerSymbol.js", "@arcgis/core/symbols/SimpleLineSymbol.js",
"@arcgis/core/widgets/Legend.js", "@arcgis/core/core/reactiveUtils.js", "@arcgis/core/widgets/AreaMeasurement2D.js", "@arcgis/core/widgets/DistanceMeasurement2D.js",
"@arcgis/core/widgets/BasemapToggle.js"
]);

import { wellRenderer, segmentRenderer, boundaryRenderer, configLayers, sources, popupWellheads, labelClass } from '/js/renderer.js';

//Well = new FeatureLayer({ url: "https://ucwgis00001.aramco.com/arcgisserver/rest/services/URGIS/WellsUTM/MapServer/0", labelingInfo: [labelClass], renderer: wellRenderer });
//Segment = new FeatureLayer({ url: "https://ucwgis00001.aramco.com/arcgisserver/rest/services/URGIS/URSegments/MapServer/0" });
let savedAssetsInfo = [];
const polygonGraphicsLayer = new GraphicsLayer();

export class renderMaps {
static dotNetHelper;
static setDotNetHelper(value) {
renderMap.dotNetHelper = value;
}
}
export function renderMapValue(value) {
if (value !== null && value !== undefined) {
Selectedvalue = value;
//console.log(`SelectedValue: ${value}`);
} else {
// console.log("No value selected");
Selectedvalue = "Well";
}
}

export async function renderMap() {

const mapImage = document.getElementById("map-image");
const loader = document.getElementById("loader");
//mapImage.style.display = "block";
//loader.style.display = "flex";
if (mapImage) {mapImage.style.display = "block"; }
if (loader) {loader.style.display = "flex";}
if (!mapImage || !loader) {console.error("Either map-image or loader element was not found.");}

//satellite
map = new Map({ basemap: "satellite" });
view = new MapView({
map: map,
center: [35, 26],
zoom: 6,
container: "view-div",
ui: {
components: ["attribution"] // Only show attribution, hide zoom widget
}
});

let basemapToggle = new BasemapToggle({
view: view, // The view that provides access to the map's "streets-vector" basemap
nextBasemap: "hybrid" // Allows for toggling to the "hybrid" basemap
});
// Wait for view to be ready
await view.when();

// Add feature layers
if (configLayers) {
configLayers.forEach((layerInfo) => {
let layer;
switch (layerInfo.id) {
case "Segment":
layer = new FeatureLayer({ id: layerInfo.id, url: layerInfo.url, renderer: segmentRenderer });
Segment = layer;
break;
case "Well":
layer = new FeatureLayer({ id: layerInfo.id, url: layerInfo.url, labelingInfo: [labelClass], renderer: wellRenderer, popupTemplate: popupWellheads });
Well = layer;
break;
case "boundary":
layer = new FeatureLayer({ id: layerInfo.id, url: layerInfo.url, renderer: boundaryRenderer });
break;
default:
console.error(`Unknown layer ID: ${layerInfo.id}`);
return;
}
map.add(layer);
});
}

// Add polygon graphics layer
map.add(polygonGraphicsLayer);

// Wait for layers to be loaded
await Promise.all(configLayers.map((layerInfo) => map.findLayerById(layerInfo.id).when()));

await view.watch("updating", (updating) => {
if (!updating) {
// This function will execute once the map stops updating (is fully loaded/rendered)
console.log("Map is fully loaded and stationary.");
mapImage.style.display = "none"; // Hide the low-opacity image
loader.style.display = "none";
const viewDiv = document.getElementById("view-div");
if (viewDiv) {
viewDiv.style.opacity = 1;
const legendLabels = document.querySelectorAll('.esri-legend__layer-cell.esri-legend__layer-cell--info');
// console.log(legendLabels); // Check if the elements are being found
legendLabels.forEach((label) => {
if (label.textContent === 'Segments') {
console.log("Segment selected");
const previousElementSibling = label.previousElementSibling;
previousElementSibling.style.backgroundColor = "#9028F180";
previousElementSibling.style.height = '26px';
previousElementSibling.style.width= '26px';
previousElementSibling.style.borderTop = '2px solid #9028F1';
}
});
const legendsymbol = document.querySelectorAll('.esri-legend__layer-cell.esri-legend__layer-cell--symbols');
/*console.log(legendsymbol);*/
legendsymbol.forEach((symbol) => {
//console.log(symbol.lastChild.firstChild.firstChild.ariaLabel);
if (symbol.lastChild.firstChild.firstChild.ariaLabel == "Preview for Segments") {
symbol.lastChild.firstChild.style.opacity = 0;
}
});
} else {
console.error("view-div element was not found.");
// You can also add additional error handling or fallback behavior here
}
}
});
// Add search widget
const searchWidget = new Search({
view: view,
sources: sources,
includeDefaultSources: false,
locationEnabled: false,
allPlaceholder: "Search By ID and Name..."
});
const expandSearch = new Expand({ content: searchWidget, view: view, expanded: false, expandIcon: "search" });
view.ui.add(expandSearch, { position: "top-right" });

//const polygonLayers = configLayers.filter((layerInfo) => ["Segment", "boundary"].includes(layerInfo.id));
const polygonLayers = configLayers.filter((layerInfo) => ["Segment"].includes(layerInfo.id));
const polygonGroupLayer = new GroupLayer({
id: "polygons",
title: "Polygons",
layers: polygonLayers.map((layerInfo) => map.findLayerById(layerInfo.id))
});

map.add(polygonGroupLayer,0);

const legend = new Legend({
view: view,
layerInfos: configLayers.reduce((acc, layerInfo) => {
const layer = map.findLayerById(layerInfo.id);
if (layerInfo.id === "Well") {
acc.push({ layer: layer, title: "Legends" });
} else if (["Segment"].includes(layerInfo.id)) {
acc.push({ layer: layer, title: "" }); // Hide the layer title
}
return acc;
}, []).concat([
{ layer: polygonGroupLayer, title: "Polygons" }
])
});
const expandLegend = new Expand({ content: legend, view: view, expanded: false, expandIcon: "information", collapseIcon:"information" });
view.ui.add(expandLegend, "top-right");

const addedLayerTitles = new Set();
// Create a new div to hold the layer list
const layerListDiv = document.createElement("div");
layerListDiv.id = "layer-list-div";
layerListDiv.style.width="300px";
layerListDiv.style.height="max-content";
layerListDiv.style.paddingLeft = "10px";

// Create a new LayerList
const layerList = new LayerList({
view: view,
visibilityAppearance: "none",
listItemCreatedFunction: (event) => {
const item = event.item;

if (item.layer.type === "basemap") {
return;
}
if (item.layer.title === "URSegments") {
item.layer.title = "Segment";
} else if (item.layer.title === "WellsUTM") {
item.layer.title = "Well";
}
else if (item.layer.title === null || item.layer.title === "Polygons") {
return;
}

if (addedLayerTitles.has(item.layer.title)) {
return;
}

addedLayerTitles.add(item.layer.title);

// Create a custom checkbox element
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = "checkbox-" + item.layer.id;
checkbox.checked = item.visible; // Set initial state

// Add an event listener to manage layer visibility
checkbox.addEventListener("change", () => {
item.visible = checkbox.checked;
});

// Watch the item's visibility property to keep the checkbox in sync
// with other potential visibility changes (e.g., zoom level changes)
reactiveUtils.watch(() => item.visible, (visible) => {
checkbox.checked = visible;
});

// Create a container for the label and checkbox
const container = document.createElement("div");
container.style.display = "flex";
container.style.justifyContent = "space-between";
container.style.alignItems = "center";
container.style.marginBottom = "10px";

const label = document.createElement("span");
label.textContent = item.layer.title;
container.appendChild(label);

container.appendChild(checkbox);

// Append the container to the layer list div
layerListDiv.appendChild(container);

// Add CSS rule to change checkbox checked color to green
const style = document.createElement("style");
style.innerHTML = `input[type="checkbox"] {
accent-color: green;
width: 20px;
height: 20px;
}
input[type="checkbox"]:checked {
accent-color: green;
}`;
document.head.appendChild(style);
}
});

// Add the layer list div to the view
view.container.appendChild(layerListDiv);

const expandLayerList = new Expand({
content: layerListDiv,
view: view,
expanded: false,
expandIcon: "layers"
});

view.ui.add(expandLayerList, { position: "top-right" });

distanceMeasurement2D = new DistanceMeasurement2D({
view,
visible: false,
});
areaMeasurement2D = new AreaMeasurement2DViewModel({
view,
visible: false,
});
// Retrieve button elements
const recButton = document.getElementById("select-by-rectangle");
const polyButton = document.getElementById("select-by-freehandpolygon");
zoomToSelectButton = document.getElementById("zoomtoSelect");
clearButton = document.getElementById("Clear");
zoomin = document.getElementById("zoomInButton");
zoomout = document.getElementById("zoomOutButton");

//zoomIn.addEventListener('click', zoomIn);
//zoomout.addEventListener('click', zoomIn);
zoomToSelectButton.style.opacity = 0.5;
clearButton.style.opacity = 0.5;

const areaButton = document.getElementById("areaButton");
const distanceButton = document.getElementById("distanceButton");
const measureClearButton = document.getElementById("measureClearButton");

// Add draw tool widget
const measureToolWidget = document.createElement("div");
measureToolWidget.classList.add("esri-widget", "draw-tool-widget");
measureToolWidget.style.display = "flex";
measureToolWidget.style.flexDirection = "column";

const buttonsmeasure = ["areaButton", "distanceButton","measureClearButton"];
buttonsmeasure.forEach((id) => {
const button = document.getElementById(id);
if (button) {
measureToolWidget.appendChild(button);
button.addEventListener("click", () => {
switch (id) {
case "areaButton":
break;
case "distanceButton":
break;
case "measureClearButton":
break;
}
});
}
});

const expandDraw = new Expand({ content: measureToolWidget, view: view, expanded: false, expandIcon: "measure" });
view.ui.add(expandDraw, { position: "top-right" });

// event listener for distance measurements
distanceButton.addEventListener("click", function () {
setActiveWidget(null);
if (!this.classList.contains("active")) {
setActiveWidget("distance");
} else {
setActiveButton(null);
}
});
// event listener for area measurements
areaButton.addEventListener("click", function () {
setActiveWidget(null);
if (!this.classList.contains("active")) {
setActiveWidget("area");
} else {
setActiveButton(null);
}
});

measureClearButton.addEventListener("click", function () {
setActiveWidget(null);
});
// Array of buttons for easier management
const buttons = [recButton, polyButton, zoomToSelectButton, clearButton];

// Add event listeners to buttons
buttons.forEach((button) => {
if (button) {
button.addEventListener("click", () => {
switch (button.id) {
case "select-by-rectangle":
// polygonGraphicsLayer.removeAll();
sketchViewModel.create("rectangle");
break;
case "select-by-freehandpolygon":
//polygonGraphicsLayer.removeAll();
sketchViewModel.create("polygon");
break;
case "zoomtoSelect":
zoomtoFeature();
break;
case "Clear":
clearSelection();
break;
}
});
}
});
// Add buttons to the view
buttons.forEach((button) => {
view.ui.add(button, { position: "top-right" });
});
// Add sketch view model
const sketchViewModel = new SketchViewModel({
view: view,
layer: polygonGraphicsLayer,
updateOnGraphicClick: false,
});
sketchViewModel.on("create", (event) => {
if (event.state === "complete") {
sketchGeometry = event.graphic.geometry;
sketchGeometries.push(event.graphic.geometry);
//view.graphics.removeAll();
//polygonGraphicsLayer.removeAll();
//savedAssetsInfo = [];

if (configLayers) {
const selectedLayer = configLayers.find((layerInfo) => layerInfo.id === Selectedvalue);
if (selectedLayer) {
selectFeatures(selectedLayer, sketchGeometries);
}
}
}
});

// Remove empty layers
layerList.when(() => {
layerList.operationalItems.forEach((item) => {
if (item.layer.title === null) layerList.view.map.remove(item.layer);
});
});
view.ui.add(zoomin, { position: "top-right" });
view.ui.add(new Home({ view: view }), { position: "top-right"});
view.ui.add(zoomout, { position: "top-right" });
// zoomin.addEventListener()
zoomin.addEventListener("click", function () { zoomIn(); });
zoomout.addEventListener("click", function () { zoomOut(); });
}

export async function queryLayers(assetSegmentIds) {
removeGraphics();
const wells = assetSegmentIds.filter(item => item.assetType === "Well");
const segments = assetSegmentIds.filter(item => item.assetType === "Segment");

polygonGraphicsLayer.removeAll();
let programsGraphicsLayer = new GraphicsLayer();
let wellsGraphicsLayer = new GraphicsLayer();
let segmentsGraphicsLayer = new GraphicsLayer();

switch (Selectedvalue) {
case "Segment":
SegmentIds = segments.map(item => "'" + item.parentAsset.id + "'");
queryAndAddGraphics(Segment, segmentsGraphicsLayer, "URECD.URSegmentTable.SEGMENT_ID", SegmentIds);
break;
case "Well":
WellIds = wells.map(item => "'" + item.parentAsset.id + "'");
queryAndAddGraphics(Well, wellsGraphicsLayer, "URECD.URGIS_Wells.WELL_ID", WellIds);
break;
default:
// You can add a default case to handle any other values
console.log("No matching case found");
break;
}
}

let addedGraphics = []; // Initialize an empty array to store added graphics

async function queryAndAddGraphics(layer, graphicsLayer, whereClause, ids) {
if (ids !== "" && ids.length) {
const query = {
where: whereClause + " IN (" + ids + ")",
returnGeometry: true
};

try {
const results = await layer.queryFeatures(query);
if (results) {
addGraphics(results);
enableButtonsfromComponent(results);
}
} catch (error) {
console.error(error);
}
} else if (savedAssetsInfo.length === 0) {
// console.log("Map features selected");
} else if (typeof removeGraphics === 'function') {
removeGraphics();
}
}
function addGraphics(results) {
if (results.features.length > 0) {
const symbol = getSymbol(results.features[0].geometry.type);

// Check if graphics already exist in the layer
const existingGraphics = new Set(view.graphics.items.map(graphic => graphic.geometry));
const newGraphics = results.features.filter(feature => {
return !existingGraphics.has(feature.geometry);
});

if (newGraphics.length > 0) {
const graphics = newGraphics.map((feature) => {
const graphic = new Graphic();
graphic.geometry = feature.geometry;
graphic.symbol = symbol;
return graphic;
});
addedGraphics.push(...graphics);
view.graphics.addMany(graphics);
}
} else {
// Clear the graphics in the layer if the query is empty
view.graphics.removeAll();
}
}
function getSymbol(geometryType) {
switch (geometryType) {
case "point":
return {
type: "simple-marker",
color: "#17CBE8",
size: 10,
};
case "polygon":
return {
type: "simple-fill",
color: "#8FA6FA",
opacity: 0.7,
outline: {
color: [128, 128, 128, 0.5],
width: "0.5px"
}
};
default:
throw new Error(`Unsupported geometry type: ${geometryType}`);
}
}
function removeGraphics() {
view.graphics.removeAll();
clearAddedGraphics();
}
function clearAddedGraphics() {
addedGraphics = [];
}
function zoomtoFeature() {
if (view.graphics.length > 0) {
view.goTo(view.graphics);
}
}
function clearSelection() {
results = { features: [] };
addGraphics(results);
polygonGraphicsLayer.removeAll();
view.graphics.removeAll();
polygonGraphicsLayer.removeAll();
removeGraphics();
savedAssetsInfo = [];
enableButtons(savedAssetsInfo);
sendArrayListToCSharp(savedAssetsInfo);
sketchGeometries = [];
}

async function selectFeatures(layerInfo, _geometry) {
const savedAssetsInfo = []; // Declare locally
const layer = map.findLayerById(layerInfo.id);

if (Selectedvalue === layerInfo.id) {
const unionGeometry = geometryEngine.union(_geometry);
try {
const query = {
geometry: unionGeometry,
spatialRelationship: "intersects",
returnGeometry: true,
outFields: ["*"],
};

const results = await layer.queryFeatures(query);

let object2 = {
assetName: layer.title,
featuresInfo: []
};
let featuresInfo2 = [];
let id;

if (results.features.length > 0) {
addGraphics(results);
const findsavedAssetsInfo = savedAssetsInfo.find(item => item.assetName === layerInfo.id);
if (!findsavedAssetsInfo) {
//#region Saved Asset Info

for (let i = 0; i < results.features.length; i++) {
if (object2.assetName === "Well") {
id = results.features[i].attributes["URECD.URGIS_Wells.WELL_ID"];
} else if (object2.assetName === "Segment") {
id = results.features[i].attributes["URECD.URSegmentTable.SEGMENT_ID"];
}
featuresInfo2.push({
id: id,
//attributes: results.features[i].attributes,
isSelected: true
});
}
object2.featuresInfo = featuresInfo2;
savedAssetsInfo.push(object2);
}
}
}
catch (error) {
console.error("Error querying features:", error);
}
}
else {
// Clear the graphics in the layer if it's not selected
view.graphics.removeAll();
}
enableButtons(savedAssetsInfo);
sendArrayListToCSharp(savedAssetsInfo);
}
function sendArrayListToCSharp(arrayList) {
//view.graphics.removeAll();
// Convert the ArrayList to a JSON string
let json = JSON.stringify(arrayList);
renderMap.dotNetHelper.invokeMethodAsync("SendArrayListToCSharp", json)
.then(result => console.log(result))
.catch(error => console.error(error));
}
function enableButtons(arrayList) {
if (arrayList.length > 0) {
//zoomToSelectButton.style.backgroundColor = "white";
//clearButton.style.backgroundColor = "white";
zoomToSelectButton.style.opacity = 1;
clearButton.style.opacity = 1;
} else {
zoomToSelectButton.style.opacity = 0.5;
clearButton.style.opacity = 0.5;
}
}
function enableButtonsfromComponent(arrayList) {
if (arrayList.features.length > 0) {
//zoomToSelectButton.style.backgroundColor = "white";
//clearButton.style.backgroundColor = "white";
zoomToSelectButton.style.opacity = 1;
clearButton.style.opacity = 1;
} else {
zoomToSelectButton.style.opacity = 0.5;
clearButton.style.opacity = 0.5;
}
}
function setActiveWidget(type) {
switch (type) {
case "distance":
areaMeasurement2D.visible = false;
distanceMeasurement2D.visible = true;
distanceMeasurement2D.viewModel.start();
setActiveButton(document.getElementById("distanceButton"));
break;
case "area":
distanceMeasurement2D.visible = false;
areaMeasurement2D.visible = true;
areaMeasurement2D.viewModel.start();
setActiveButton(document.getElementById("areaButton"));
break;
case null:
areaMeasurement2D.visible = false;
distanceMeasurement2D.visible = false;
break;
}
}
function setActiveButton(selectedButton) {
// focus the view to activate keyboard shortcuts for sketching
view.focus();
let elements = document.getElementsByClassName("active");
for (let i = 0; i < elements.length; i++) {
elements[i].classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}

// Function to handle zooming in
function zoomIn() {
// Increase the zoom level by 1
let newZoom = view.zoom + 1;
view.goTo({
// target: view.center,
zoom: newZoom
});
}
// Function to handle zooming out
function zoomOut() {
// Decrease the zoom level by 1
let newZoom = view.zoom - 0.5;
view.goTo({
// target: view.center,
zoom: newZoom
});
}


body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
ul {
display: flex;
flex-direction: column;
gap: 5px;
}
</style>

<script type="module">
const [Map, MapView, FeatureLayer,Legend] = await $arcgis.import([
"@arcgis/core/Map.js",
"@arcgis/core/views/MapView.js",
"@arcgis/core/layers/FeatureLayer.js",
"@arcgis/core/widgets/Legend.js",
]);

const map = new Map({
basemap: "hybrid",
});

const view = new MapView({
container: "viewDiv",
map: map,
center:[-73.935242,40.730610],
zoom:10
});

const featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/NY%20Educational%20Attainment/Feat...",
});

map.add(featureLayer);

view.when(()=>{
//#region Default Legend
featureLayer.when(() => {
console.log(featureLayer);
var divCustomLegend=document.getElementById("divCustomLegend");
const lebel=document.createElement("label");
lebel.textContent="NY Educational Attainment";
divCustomLegend.appendChild(lebel);

const ul=document.createElement("ul");
ul.style.listStyleType = 'none';
featureLayer.renderer.uniqueValueInfos.forEach(item=>{
const li=document.createElement("li");

const canvas = document.createElement("canvas");
canvas.width=20;
canvas.height=20;
canvas.style.backgroundColor=item.symbol.color;
li.appendChild(canvas);

const lebel2=document.createElement("label");
lebel2.textContent=item.value;
li.appendChild(lebel2);
ul.appendChild(li);
});

divCustomLegend.appendChild(ul);
view.ui.add(divCustomLegend, "top-right");
});
//#endregion

//#region Default Legend
const legend = new Legend({
view: view,
layerInfos: [
{
layer: featureLayer,
title: "NY Educational Attainment",
},
],
});
view.ui.add(legend, "bottom-left");
//#endregion
});
</script>
</head>

<body>
<div id="viewDiv">
<div id="divCustomLegend" style="background-color: white;max-height: 250px;max-width: 200px;overflow-y: auto;">
</div>
</div>
</body>
</html>

0 Kudos
0 Replies