Why adding a TileLayer to the map changes zoom of MapView?

1625
7
Jump to solution
01-29-2020 03:52 AM
AlexanderParshin
New Contributor II

Test case:

  1. Create an empty Map without basemap
  2. Create MapView with EPSG:4326 projection and initial position (center and zoom)
  3. Asynchronously add the following TileLayer to the map: wgs84/gebco_2019_contours (MapServer) 
  4. The map will zoom out to zoom=0 after adding the layer.

CodePen: https://codepen.io/parshin/pen/RwNmgRx?editors=1000 

Why zoom is changed? Is it expected behavior? I can't find any information about it in the documentation...

Notes:

  • Synchronous layers adding doesn't change map's zoom
  • Many other layers with MapView in WebMercator projection work fine (no zoom change)
  • I can reproduce this issue with 4.14 and "next" API

Environment:

  • Browser: Chromium Version 79.0.3945.79 

  • OS: Ubuntu 16.04 (64-bit)

  • ArcGIS API versions: 4.14, next
0 Kudos
1 Solution

Accepted Solutions
UndralBatsukh
Esri Regular Contributor

Hi there, 

The MapView.constraints.lods property should be specified when no basemap is being set or when using a dynamic service for a basemap. Setting MapView.zoom is meaningless without setting LODs.  You can set the LODs by by either explicitly setting the lods within this property, or create the lods via the create() method on the TileInfo class. This method is used to create a new TileInfo instance with preset properties for lods.

Because you are adding a MapImageLayer with a spatialReference of 4326, you create the LODs as shown below:

var view = new MapView({
 container: "viewDiv",
 map: map,
 spatialReference: {
   wkid: 4326
 },
 zoom: 4,  // <-- initial zoom is 4
 center: [15, 65],
 constraints: {
   lods: TileInfo.create({
     spatialReference: {
     wkid: 4326
   }
   }).lods
 }
});

I also updated your test app to use this approach. 

Hope this helps,

-Undral

View solution in original post

7 Replies
UndralBatsukh
Esri Regular Contributor

Hi there, 

The MapView.constraints.lods property should be specified when no basemap is being set or when using a dynamic service for a basemap. Setting MapView.zoom is meaningless without setting LODs.  You can set the LODs by by either explicitly setting the lods within this property, or create the lods via the create() method on the TileInfo class. This method is used to create a new TileInfo instance with preset properties for lods.

Because you are adding a MapImageLayer with a spatialReference of 4326, you create the LODs as shown below:

var view = new MapView({
 container: "viewDiv",
 map: map,
 spatialReference: {
   wkid: 4326
 },
 zoom: 4,  // <-- initial zoom is 4
 center: [15, 65],
 constraints: {
   lods: TileInfo.create({
     spatialReference: {
     wkid: 4326
   }
   }).lods
 }
});

I also updated your test app to use this approach. 

Hope this helps,

-Undral

AlexanderParshin
New Contributor II

Hey Undral,

Thank you very much for the tip! I didn't understand that I must set LODs myself without basemaps... That completely fixes my problem!

Just for my better understanding, why does it work without explicitly setting LODs for a synchronously added layer (https://codepen.io/parshin/pen/povmVyE?editors=1000 )?

0 Kudos
AlexanderParshin
New Contributor II

Undral, one more case: why LODs are initialized properly with asynchronous adding of WebTileLayer (instead of TileLayer): https://codepen.io/parshin/pen/eYmajyp?editors=1000  ?

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there, 

That is because MapView's lods are set to use ArcGIS Online tiling scheme for WKID:102100 by default. This WebTileLayer has Web Mercator (wkid:102100) spatial reference. That is why you did not have to set the LODs. For example, I updated your app to use TileLayer with Web Mercator SpatialReference. As you can see it behaves as same as your WebTileLayer. If your cached layer's spatialReference is not WebMercator then you have to do what I suggested above. 

Hope this makes sense,

-Undral

AlexanderParshin
New Contributor II

Hi Undral,

Thanks for the explanation!

It's weird, but your last example with Web Mercator and TileLayer doesn't work for me with disabled browser cache (initial zoom value is ignored). For example, it can be the first load of the page after I clean the cache manually or if I turn on Chrome DevTools and disable network cache from there. I checked this with Chrome and Firefox and with a standalone HTML (to make sure that it's related to CodePen framework).

Could it be some sort of race condition inside ArcGIS JS API?

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there,

It is working as designed. If the view is initialized with the zoom, it just start out at that zoom. It does not change to it. Hence, you will not see the view.zoom changing at the initial load. If you need to catch this initial zoom then you can use watchUtils.init() method as shown below:

watchUtils.init(view, "watch", function(){
  console.log("view's init zoom", view.zoom)
});

-Undral

0 Kudos
AlexanderParshin
New Contributor II

Hi Undral,

First of all, thank you again for the explanation and examples - I set LODs explicitly and it completely solved my problems!

The only reason I wrote the message above is that it seems strange to me that the map after load in your example https://codepen.io/U_B_U/pen/JjoqmGV?editors=1000 is shown at different zoom depending on turning on/off cache in browser. I thought that it might be a bug in ArcGIS JS API and is interesting to you. 

0 Kudos