How to simulate listening for zoom-end in the 4.x framework.

2577
3
Jump to solution
08-27-2018 10:41 AM
StanLambert
New Contributor II

I'm upgrading a current application from the 3.x framework to 4.x.  In the current application I listen for the zoom-end event in order to know when to enable/disable branches in my custom layer tree based on the defined min scale for each layer.  

I realize the new framework "makes it easier" to watch for changes in object properties with the watch method. The problem is that when the user is zooming in and out I do not want to execute a function on every change in the zoom level.  My layer tree has hundreds of branches.  I don't want to iterate through all of that data every time the zoom level changes while the user is spinning the mouse wheel.

I have found this as a workaround:

watchUtils.when(myMapView, "stationary", function() {
    const currentScale = myMapView.get('scale'));
   // now go through all of the layers and enable/disable based on the current scale...
});

The problem is that this event is fired when the user does other things such as panning the map.  I'm only interested in knowing when the user has finished zooming the map.

Does anybody have any ideas about this?  Maybe I have missed something in the documentation. Thanks for your help.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Stan,

   Here is a simple solution:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
  <title>Intro to MapView - Create a 2D map - 4.8</title>
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

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

  <script>
    var beginScale;
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/core/watchUtils",
      "dojo/domReady!"
    ], function(Map, MapView, watchUtils) {

      var map = new Map({
        basemap: "streets"
      });

      var view = new MapView({
        container: "viewDiv",
        map: map,
        zoom: 4,
        center: [15, 65] // longitude, latitude
      });
      
      watchUtils.when(view, "interacting", function() {
        beginScale = view.get('scale');
      });
      
      watchUtils.when(view, "stationary", function() {
        const currentScale = view.get('scale');
        if (currentScale !== beginScale) {
          console.log("zoom done");
          // now go through all of the layers and enable/disable based on the current scale...
        }
      });

    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>
</html>

View solution in original post

0 Kudos
3 Replies
RobertScheitlin__GISP
MVP Emeritus

Stan,

   Here is a simple solution:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
  <title>Intro to MapView - Create a 2D map - 4.8</title>
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

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

  <script>
    var beginScale;
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/core/watchUtils",
      "dojo/domReady!"
    ], function(Map, MapView, watchUtils) {

      var map = new Map({
        basemap: "streets"
      });

      var view = new MapView({
        container: "viewDiv",
        map: map,
        zoom: 4,
        center: [15, 65] // longitude, latitude
      });
      
      watchUtils.when(view, "interacting", function() {
        beginScale = view.get('scale');
      });
      
      watchUtils.when(view, "stationary", function() {
        const currentScale = view.get('scale');
        if (currentScale !== beginScale) {
          console.log("zoom done");
          // now go through all of the layers and enable/disable based on the current scale...
        }
      });

    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>
</html>
0 Kudos
StanLambert
New Contributor II

Robert,

I've applied your example to my own situation and it works fine.  It's a little more code than was necssary with the 3.x version but I'm not complaining.  One more item I can check off the list.  Thanks!

-Stan

0 Kudos
GavinRehkemper
Esri Contributor

Depending on your application and requirements (especially browser version support), using "Number.isInteger()" may be a slightly simpler way to do this: 

view.when(() => {
  view.watch("zoom", (evt) => {
    if (Number.isInteger(evt)) {
      // your code here will only run on zoom-end
    }
  });
});

Full example: https://codepen.io/gavinr/pen/yLvOaod 

0 Kudos