Limit pan in Web AppBuilder

451
6
Jump to solution
06-19-2018 11:51 PM
EinarDørheim1
New Contributor III

Hi 

I have made a basic app portraying a single feature hosted Feature layer(points) on top of esri basemaps. The basemaps covers the whole world, but my app should only focus on Oslo city. To do this I've tried to restrict the panning possibilities to the city, throwing the user back if he pans to far out, this works fine now. Using a script with Web AppBuilder for developers. However I have a challenge that I havn't been able to solve. 

1. When my app loads, it sets the specified extent from a script for the basemap, but it doesn't seem to affect my feature layer, resulting in the features beeing placed with a certain offset from their correct place. (I suspect the script is forcing the basemap to a certain extent, while the features are still using the default extent set by the map layer). The moment I zoom in or out, the problem corrects itself and will work fine until you reload the application. 

Right pic, nr1, shows the initial placement, while left pic, nr2, shows how it should look

Left pic, nr1 shows the initial extent, whil right pic,nr2, shows how it should be.

This is the script I've tried, placed in the file "LayoutManager.js" 

    _doPostLoad: function(map){
      //load somethings that may be used later.
      //let it load behind the stage.
      require(['dynamic-modules/postload']);
      
       var osloExtent;
      
       if(!osloExtent){
          osloExtent = map.extent;
          osloExtent.xmin = 1164244.8971553196;
          osloExtent.xmax= 1218767.932529483;
          osloExtent.ymin= 8360539.398234147;
          osloExtent.ymax= 8390138.410556029;
     }
      
          
      
       map.on('extent-change', function(event) {
          //If the map has moved to the point where it's center is outside the initial boundaries,
          //then move it back to the edge where it moved out
          var currentCenter = map.extent.getCenter();
          if (osloExtent && !osloExtent.contains(currentCenter) && event.delta && event.delta.x !== 0 && event.delta.y !== 0) {
            var newCenter = map.extent.getCenter();

            //check each side of the initial extent and if the current center is outside that extent,
            //set the new center to be on the edge that it went out on
            if (currentCenter.x < osloExtent.xmin) {
               newCenter.x = osloExtent.xmin;
            }
            if (currentCenter.x > osloExtent.xmax) {
               newCenter.x = osloExtent.xmax;
            }
            if (currentCenter.y < osloExtent.ymin) {
               newCenter.y = osloExtent.ymin;
            }
            if (currentCenter.y > osloExtent.ymax) {
               newCenter.y = osloExtent.ymax;
            }
            map.centerAt(newCenter);
          }
       });
    },

    _onOpenWidgetRequest: function(widgetId){
      this.layoutManager.openWidget(widgetId);
    }
  });

If i remove the script, allowing end users to pan all over the world, the features will be at their correct place when reloading the application - so there's nothing wrong with the layer. 

Ps: I'm new to scripting java, had a lot of help coming up with this one.

Have noticed that there are some similiar questions out there, but their quite old, and not linked to Web AppBuilder as far as I can tell. 

0 Kudos
1 Solution

Accepted Solutions
EinarDørheim1
New Contributor III

I got the same functionality with that code, but the same error as well. I think it has something to do with setting the variable osloExtent. 

used some of your code and combined it with previous attempts/code i've found, works quite well : 

         _onMapLoaded: function(map) {
        this.map = map;
        this.layoutManager.setMap(map);
        this.layoutManager.loadAndLayout(this.appConfig);

        var initialExtent = map.extent;
        map.on('extent-change', function(event) {
          //If the map has moved to the point where it's center is outside the initial boundaries,
          //then move it back to the edge where it moved out
          var currentCenter = map.extent.getCenter();
          if (!initialExtent.contains(currentCenter) &&
            event.delta.x !== 0 && event.delta.y !== 0) {

            var newCenter = map.extent.getCenter();

            //check each side of the initial extent and if the
            //current center is outside that extent,
            //set the new center to be on the edge that it went out on
            if (currentCenter.x < initialExtent.xmin) {
                newCenter.x = initialExtent.xmin;
            }
            if (currentCenter.x > initialExtent.xmax) {
                newCenter.x = initialExtent.xmax;
            }
            if (currentCenter.y < initialExtent.ymin) {
                newCenter.y = initialExtent.ymin;
            }
            if (currentCenter.y > initialExtent.ymax) {
                newCenter.y = initialExtent.ymax;
            }
            map.centerAt(newCenter);
          }
        });
      },

Thanks for your help Robert!

View solution in original post

0 Kudos
6 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Einar,

   Where is this code? 

When my app loads, it sets the specified extent from a script for the basemap

The only code you posted was for re-centering the map after a pan.

0 Kudos
EinarDørheim1
New Contributor III

Hi Robert

We had trouble finding the code snippet that specify the initial extent, thats why we wrote the code that recenters the map to desired extent postload. 

I can see in the config.json that it referes back to my web map in my portal, and in some way it gathers the extent saved in my web map and uses it to set initial extent. Which my code now overrules with the mention flaud in my original answer. 

Sorry for the incomplete response..

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Einar,

   In the Web AppBuilder you can set the maps initial extent to something other than the web maps initial extent. On the map tab on the left of WAB there is the Set Initial Extent section and there is a "Use current map view" button that allows you to set the apps initial extent to what you want.

0 Kudos
EinarDørheim1
New Contributor III

Indeed, and thats fine and all, the problem, as tried explained in my question, is that the code I've put in to my LayoutManager.js is affecting the initial extent. so by adjusting the initial extent from Web AppBuilder or the Web Map the app is using, I'm getting a result where the basemap and the feature layer loads in two different extents. 

If i remove all of the code written above the map and feature will both load in their rightful place, but then i lose the desired panning restriction..

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Einar,

   OK I see your issue then. Remove your code from that function and put it into this one instead (in the LayoutMnager.js still):

      _onMapLoaded: function(map) {
        this.map = map;
        this.layoutManager.setMap(map);
        this.layoutManager.loadAndLayout(this.appConfig);

        var osloExtent;

        if(!osloExtent) {
          osloExtent = map.extent;
          osloExtent.xmin = 1164244.8971553196;
          osloExtent.xmax = 1218767.932529483;
          osloExtent.ymin = 8360539.398234147;
          osloExtent.ymax = 8390138.410556029;
        }

        map.on('extent-change', function(event) {
          //If the map has moved to the point where it's center is outside the initial boundaries,
          //then move it back to the edge where it moved out
          var currentCenter = map.extent.getCenter();
          if(osloExtent && !osloExtent.contains(currentCenter) && event.delta && event.delta.x !== 0 && event.delta.y !== 0) {
            var newCenter = map.extent.getCenter();

            //check each side of the initial extent and if the current center is outside that extent,
            //set the new center to be on the edge that it went out on
            if(currentCenter.x < osloExtent.xmin) {
              newCenter.x = osloExtent.xmin;
            }
            if(currentCenter.x > osloExtent.xmax) {
              newCenter.x = osloExtent.xmax;
            }
            if(currentCenter.y < osloExtent.ymin) {
              newCenter.y = osloExtent.ymin;
            }
            if(currentCenter.y > osloExtent.ymax) {
              newCenter.y = osloExtent.ymax;
            }
            map.centerAt(newCenter);
          }
        });
      },
EinarDørheim1
New Contributor III

I got the same functionality with that code, but the same error as well. I think it has something to do with setting the variable osloExtent. 

used some of your code and combined it with previous attempts/code i've found, works quite well : 

         _onMapLoaded: function(map) {
        this.map = map;
        this.layoutManager.setMap(map);
        this.layoutManager.loadAndLayout(this.appConfig);

        var initialExtent = map.extent;
        map.on('extent-change', function(event) {
          //If the map has moved to the point where it's center is outside the initial boundaries,
          //then move it back to the edge where it moved out
          var currentCenter = map.extent.getCenter();
          if (!initialExtent.contains(currentCenter) &&
            event.delta.x !== 0 && event.delta.y !== 0) {

            var newCenter = map.extent.getCenter();

            //check each side of the initial extent and if the
            //current center is outside that extent,
            //set the new center to be on the edge that it went out on
            if (currentCenter.x < initialExtent.xmin) {
                newCenter.x = initialExtent.xmin;
            }
            if (currentCenter.x > initialExtent.xmax) {
                newCenter.x = initialExtent.xmax;
            }
            if (currentCenter.y < initialExtent.ymin) {
                newCenter.y = initialExtent.ymin;
            }
            if (currentCenter.y > initialExtent.ymax) {
                newCenter.y = initialExtent.ymax;
            }
            map.centerAt(newCenter);
          }
        });
      },

Thanks for your help Robert!

View solution in original post

0 Kudos