POST
|
I was recently tasked to create a custom basemap layer for our apps that combine some of ESRI's published Vector Basemaps and one of their hillshade basemaps. To accomplish, I did something like this: /**
* Returns a custom ESRI Basemap
*
* @returns {Promise<Object>} ESRI Basemap
*/
export async function createCustomHillshadeBasemap() {
const [Basemap, esriRequest, TileLayer, VectorTileLayer] = await loadModules([
"esri/Basemap",
"esri/request",
"esri/layers/TileLayer",
"esri/layers/VectorTileLayer",
]);
let labelStyle;
let canvasStyle;
// The label style used by the World ESRI Dark Gray Canvas (taken from looking at network request, is this subject to change?):
let labelStyleUrl = "https://www.arcgis.com/sharing/rest/content/items/747cb7a5329c478cbe6981076cc879c5/resources/styles/root.json";
labelStyle = await esriRequest(labelStyleUrl, {
responseType: "json",
});
// The canvas style used by the World ESRI Dark Gray Canvas:
let canvasStyleUrl =
"https://www.arcgis.com/sharing/rest/content/items/5e9b3685f4c24d8781073dd928ebda50/resources/styles/root.json";
canvasStyle = await esriRequest(canvasStyleUrl, {
responseType: "json",
});
let baseLayers = [
new VectorTileLayer({
effect: "opacity(80%) brightness(90%)",
style: canvasStyle.data,
title: "darkCanvas",
url: "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer",
}),
new VectorTileLayer({
style: labelStyle.data,
title: "labels",
url: "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer",
}),
];
baseLayers.unshift(
new TileLayer({
title: "hillshade",
url: "https://services.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer",
})
);
const basemap = new Basemap({
baseLayers: baseLayers,
id: "basemap",
title: "basemap",
});
return basemap;
}
Above works well. But note at line 25 I am using a url to json that I found ESRI uses for its basemap vector styling rules. The only way I encountered this was by inspecting the network requests in my browser when loading this layer. What I'm wondering, is: will this change? Is that style url something we can count on as a constant or will what that entails change without notice (possible concern)? Or is it possible that the url suddenly changes (note that hex string as part of the url) and we're suddenly referencing a dead endpoint (bigger concern)? I didn't see any documentation on this so wondering if there are any pitfalls I should be aware of. Does ESRI want us to make our own styles and publish them ourselves (I hope not) and/or is there a more recommended way to create a custom basemap layer in ArcGIS JavaScript API that does not require specifying the style url for the basemap if we just want to combine a couple of ESRI's already published sources?
... View more
05-09-2022
03:23 PM
|
0
|
4
|
864
|
POST
|
For the answer above, which uses `dojoConfig` to turn off this feature, is there a trick to be able to do the equivalent if we are using es6/esm imports and ""@arcgis/core"? @mgeorge I am assuming no but wanted to check to be certain.
... View more
04-25-2022
11:24 AM
|
0
|
1
|
2304
|
POST
|
I am finally moving our apps to use the new vector basemap services and have set up an ESRI API key to access the data. I would like to write a check at runtime that ensures that the token supplied for my app will indeed work. The logic I'm thinking is something like: At Build: load api key token (from environment variables) At Runtime: do a basic check that token works (isn't expired, lacking credits, works with referrer, supports the services I want to use it against (e.g. search, basemaps) etc) - Make an `esriRequest` to some url endpoint that returns a brief description validating token or no and what services it works against. - If token is invalid handle accordingly, fall back to other basemaps, disable search etc. However I don't see anything anywhere in the ESRI API documentation discussing any such process. Of course I could test trying to fetch a particular basemap tile and see if an error message comes back but I'd rather just have a lightweight explicit "verify token" endpoint not just for a basemap but for the token itself. What I tried so far: This'll work and fail with a bad token, but would like something a bit more descriptive: require([
"esri/config",
"esri/request",
"esri/Map",
"esri/views/MapView",
"esri/widgets/Search",
], function (esriConfig, esriRequest, Map, MapView, Search) {
esriConfig.apiKey = "some-invalid-key-here";
esriRequest(
"https://basemaps-api.arcgis.com/arcgis/rest/services/styles/ArcGIS:Streets",
{
responseType: "json",
}
)
.then(function (response) {
let data = response.data;
console.log(data);
})
.catch((err) => {
console.log("whoops");
}); Wondering if anyone has any advice before I go bother ESRI Canada support and/or make an idea suggestion about this. I also welcome feedback as to why my above approach idea might not be a good idea or is ill-advised.
... View more
04-22-2022
10:39 AM
|
0
|
0
|
587
|
POST
|
Update: After some help from an ESRI Canada support analyst I came up with a preliminary solution. Instead of trying to manipulate the LayerView via createLayerView as I mentioned above, I create my customTileLayer with a color property that I can alter. When I fire an event to change that property I also call the `.refresh` method on the baseTileLayer. This redraws the layer. The browser is smart enough to recognize that tiles will have already been fetched so the update is faster. You can see that in action in this codePen here. Note that I also toggle the layer visible on and off to help ensure the screen is completely redrawn. This is okay but there are problems. The redraw here is a bit slow. I've since tested an approach where my customTileLayer class stores (caches) the processed tileData as a property and this seems to be faster. To mitigate problems with bloating memory size I use an LRUCache to limit the amount/size of cached tiles. I don't have a codePen of that, but you can see a rough working example in GitHub here. the other problem is that sometimes, especially if you are zooming or panning, we see the old style stick around or flash. I've tried making the fetch calls within fetchTile cancellable with using an AbortSignal for esriRequest. I couldn't quite fix the problem with that. Instead I've been experimenting with only allowing style updates when the layer is stationary which seems to help and is acceptable UX for my purposes.
... View more
03-13-2022
02:25 PM
|
0
|
0
|
457
|
POST
|
I would like to create a custom TileLayer for my ArcGIS JavaScript API based application. My requirements are that it consumes tiled data from a specific non-ArcGIS Server source and that I can update the way the data is rendered-- clientside. I looked first at the BaseTileLayer Class and the examples there rendering a Custom Lerc Layer in 2D. That shows how you can override fetchTile() method to process data just after it is fetched and before it is displayed in view. Works well. But what if I want rerender the layer in my 2d/3d View based on an event clientside? Eg. I want behavior like this old example with an ImageryTileLayer where the color scheme can be adjusted, no new data fetching involved. I see that it there is a blurb in the Layer Class API page for each layer type and for BaseTileLayer it says: No editing, client-side rendering, or popup templates; some schema limitations in 3D views. Is that the end of the story then? Because I also know that custom LayerView Classes(BaseLayerView2D, BaseLayerViewGL2D) exist to handle custom rendering of clientside data on various events. Even if my solution is limited to 2D Views, this seems what I would want. Does anyone have any ideas? This is pretty critical to our business needs so I want to make sure I am clear on the limitations and my answer back to my team. What I tried I tried adding a createLayerView method to the extended BaseTileLayer class instance in this Custom Lerc Layer example. and adding my own BaseLayerView2D instance as the LayerView similar to what was done here in this WebGL Example. This causes fetchTile() to not fire. I see that the API says that createLayerView is used internally and should not need to be customized-- yet the ArcGIS Custom LayerView examples do exactly that.
... View more
02-16-2022
03:26 PM
|
0
|
1
|
542
|
POST
|
[Going to mark the question as answered for future users. If an answer comes along that leads to a way to enable this "snapshot logic" feature and have it not cause problems for our large datasets I'll switch to that.]
... View more
01-25-2022
05:57 PM
|
0
|
1
|
2474
|
POST
|
I just confirmed the dojoConfig object change gets around the problem with the "snapshot logic" for my service(s). <script>
var dojoConfig = {
has: {
"featurelayer-snapshot-enabled": 0
}
}
</script>
<script src="https://js.arcgis.com/4.22/"></script> That solves my problem with this being a blocker for us to move to `4.2x` so thank you @mgeorge for that! That's a big relief to our team. We're interested in understanding why this feature doesn't work for us. - we don't have a definitionExpression on the layer. We only draw the layer at a scale of ~1:4k or larger. In most cases, the point layers are evenly spaced in a grid at a certain interval. So we don't have to worry about a user zooming to an area with a too-high count of records that will cause the server performance problems. - The services are not publicly available so I cannot share a link. If you'd like to see the data, I can send a scrubbed representative example in shapefile form for your interest. PM me for details and we can make arrangements. Your point about caching the service is taken and I'm looking at that also. There are some tricks that that introduces for us with updating the data that means its a bit more than trivial effort.
... View more
01-25-2022
05:50 PM
|
0
|
0
|
2474
|
POST
|
Related Idea post for the fix feature improvement! https://community.esri.com/t5/arcgis-api-for-javascript-ideas/fix-4-2x-so-that-initial-requests-for-large-layers/idi-p/1136691
... View more
01-24-2022
05:19 PM
|
0
|
0
|
2719
|
IDEA
|
As of 4.21 ArcGIS JavaScript made a change to the way it initially fetches and sets up a new FeatureLayer in the API. There is a request to get the total count of records. This can be extremely slow for large datasets and degrades performance rather than improves it for apps. ESRI should fix the API to make the behaviour opt-in, update the docs and release notes to clarify the trade-offs so developers understsand what it is doing and what is best for their use case. Once ESRI fixes the behavior to make it opt-in, they can reword the release notes like this:
... View more
01-24-2022
05:18 PM
|
3
|
4
|
1125
|
POST
|
Looking at moving from 4.19 to 4.21+ and ran into a problem loading FeatureLayers from our backend ArcGIS Server REST MapServices. At 4.21 loading point layers with over a few million records becomes really slow on initial load. The time from initial request to draw went from a couple seconds or less to 30+ seconds. When I watch the network traffic I can see that as of 4.21 there is now an initial fetch for the count of records with params like so: `returnIdsOnly=true&returnCountOnly=true&spatialRel=esriSpatialRelIntersects&where=1%3D1` This is returning the count of the records in the service layer and it consistently takes our server over 30 seconds to process. The release notes for ArcGIS 4.21 say: At version 4.19, we improved the performance of point FeatureLayers hosted on ArcGIS Online. Version 4.21 brings these changes to ArcGIS Enterprise point services. It looks like this fetch of the count is part of a trick to try to speed up subsequent requests. As an aside we haven't noticed any improvement for any of our datasets/apps on subsequent fetches/draws either. Some details: Our point layer(s) come from an SDE Database Feature Class layer. The MapService is not cached. ESRI Canada technical support have confirmed they have been able to reproduce this problem with other large datasets of their own. For our large datasets our use case is that these layers are configured to only draw at a very large scale where a couple thousand records draw at a time. Note that in the use case that ESRI demonstrates in their 4.19 release notes shows all the data drawn at once at full scale. I think their trick might provide advantages in that use case at the detriment of my own. I would like this performance improvement approach to be opt-in in the API (Feature Idea) since ESRI won't consider it a bug. I am also interested if users here know of tricks to speed up getting the recordCount of a large dataset via REST. For example I can get the recordCount via a direct SQL request to the database table in less than 2 seconds. Why does it take suddenly 30 seconds for ArcGIS Server? Is there some trick or optimization to cache this?
... View more
01-24-2022
05:06 PM
|
0
|
13
|
3208
|
POST
|
Thanks for this Tom, I tested the last solution in your post and indeed that does the trick nicely. I'm not yet 100% sure what I garbled in my original example, I suspect the way the `getClass` function was returning the class was messing up the context of 'this'. In any case this works well and will fit my usage needs.
... View more
11-21-2021
09:26 PM
|
0
|
0
|
1617
|
POST
|
Thanks, @TomThompsonEsriCA , @GavinRehkemper. I think the problem with the React-ArcGIS library using an older version of the ArcGIS API and not being overridable is a quirk of CodePen.io and the fact that it is using a pre-bundled cdn for the package. I tried to recreate the same Pen using CodeSandbox but that seemed to have trouble with the memory requirements of 3d scenes. So I've made a GitHub repo here with the above code. If you pull that and spin it up (`npm start`) you'll note that the version of the API is now correctly set to 4.20. You should also see an error in the console as per above. An additional error like this should also appear: iframeConsoleRunner-d8236034cc3508e70b0763f2575a8bb5850f9aea541206ce56704c013047d712.js:1 [esri.views.LayerViewManager] Failed to create layerview for layer title:'no title', id:'17d2f3d6194-layer-3' of type 'base-elevation'. {layer: d, error: e} (index):113 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'lastIndexOf') at new a ((index):113) at Function.a.getLogger ((index):117) at (index):770
... View more
11-17-2021
11:27 AM
|
1
|
0
|
1646
|
POST
|
Overdue followup: ESRI did respond with confirmation of **most** (some even they were unsure about) of the fields and suggested that there is no harm in using the dat files this way with the usual disclaimer that things could change at any future release without notice.
... View more
11-11-2021
05:49 PM
|
2
|
0
|
1509
|
POST
|
I'm looking to implement a custom ArcGIS API for JavaScript baseElevationLayer like the example provided here. I basically take the example ESRI provide that creates a custom class and put it in a function `getClass` that returns the class for me. In vanilla JavaScript all seems to work fine. Here is a CodePen of the code. When I do the same thing in my React app, which uses esriLoader to load the API modules and react-arcgis to create a SceneView, loading this custom baseElevationLayer fails. Here is that in CodePen also. If you look at the browser's developer console, you see an error about "Cannot read properties of undefined (reading '_elevation')." Can anyone spot what I'm missing?
... View more
11-11-2021
05:41 PM
|
0
|
5
|
1777
|
POST
|
As @jcarlson has pointed out, and a helpful ESRI Canada representative suggested, there might actually be a `hasZ` property present in json even when the layer does not have z data. It might depend on your service configuration or ArcGIS Server version. In my case, using ArcGIS Server 10.7.1 and 10.8, it turns out that the `hasZ` property was present if the layer does have z values (at least in the case of our configurations for our point layers). But not otherwise. Once I confirmed that, the json response from an endpoint like (/arcgis/services/[servicename]/MapServer/[layer#]?f=json) worked fine. In javascript something like: ``` if(!json.hasZ) { // handle no z values } ``` Will handle both cases nicely.
... View more
10-05-2021
03:09 PM
|
1
|
0
|
835
|
Title | Kudos | Posted |
---|---|---|
2 | 11-07-2023 01:10 PM | |
1 | 10-27-2023 02:01 PM | |
1 | 05-15-2020 04:58 PM | |
1 | 04-15-2021 09:08 AM | |
1 | 04-06-2021 10:29 AM |
Online Status |
Offline
|
Date Last Visited |
03-15-2024
06:57 PM
|