Detect change in zoom when complete

5333
8
Jump to solution
06-19-2017 11:58 AM
AlanMervitz
New Contributor

Hello,

I'm trying to detect when a map has been zoomed in or out, and when that is complete to execute a function. I have tried using watchUtils.watch on both the view.zoom and view.extent properties, but am finding that the callbacks get executed too many times.

Here's the TypeScript code I'm using, where the console.log statements are getting executed too many times:

constructor(basemap: string = "streets", container: string = "viewDiv", center: number[] = [-104.61, 50.45], zoom: number = 12) {
    this.map = new Map({
        basemap: basemap
    });

    this.view = new MapView({
        container: container,
        map: this.map,
        center: center,
        zoom: zoom
    });

    watchUtils.watch(this.view, "zoom", function (zoom) { console.log(`zoom is now ${zoom}`) });
    watchUtils.watch(this.view, "extent", function (extent) { console.log(`extent is now ${extent}`) });
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Here's what the output looks like in the console:

Is there a way to detect the change only when the zoom is complete? Perhaps there's another approach for accomplishing this than watching these properties?

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
ThomasSolow
Occasional Contributor III

Interesting solution, if it works I'd go with it.

Another option would be to use a debounce function.  So each time the zoom changes that function would be called but the actual logic would be delayed until the function hasn't been called in some user defined amount of time (maybe 200 ms would be good for something like this).

I always copy the underscore.js debounce function when I need this: underscore.js 

View solution in original post

8 Replies
RobertScheitlin__GISP
MVP Emeritus

Alan,

   You should watch the updating property of the view for a false condition after the zoom property changes.

https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#updating 

AlanMervitz
New Contributor

Hi Robert,

Thanks for the suggestion, I've given that a quick try but it doesn't seem to be working reliably. The updating status seems to be changing multiple times throughout the zooming process.

constructor(basemap: string = "streets", container: string = "viewDiv", center: number[] = [-104.61, 50.45], zoom: number = 12) {
...
    watchUtils.watch(this.view, "zoom", this.onZoomChange);
}

onZoomChange(newValue: number, oldValue: number, propertyName: string, target: MapView) {
    console.log(`zoom is ${newValue}`);
    if (target.updating) {
        console.log("zoom in progress");
    }
    else {
        console.log("finished zoom");
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Here's a working approach I've found, any feedback?

onZoomChange(newValue: number, oldValue: number, propertyName: string, target: MapView) {
    console.log(`zoom is ${newValue}`);
    if (newValue % 1 !== 0) {
        console.log("zoom in progress");
    }
    else {
        console.log("finished zoom");
    }
}

Thanks,

Alan

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Alan,

   Something more like this:

watchUtils.watch(this.view, "zoom", function(){
  watchUtils.whenFalseOnce(this.view, "updating", yourFunction);
});
AlanMervitz
New Contributor

I've tried that but the whenFalseOnce callback is getting triggered multiple times. This would have been ideal if it had worked.

0 Kudos
RomanKönig
New Contributor III

I found it more useful to check the stationary attribute of the view than updating, as updating waits for export, etc. responses.

ThomasSolow
Occasional Contributor III

Interesting solution, if it works I'd go with it.

Another option would be to use a debounce function.  So each time the zoom changes that function would be called but the actual logic would be delayed until the function hasn't been called in some user defined amount of time (maybe 200 ms would be good for something like this).

I always copy the underscore.js debounce function when I need this: underscore.js 

AlanMervitz
New Contributor

The debounce approach is working beautifully, thanks!

0 Kudos
AbdulKhan
New Contributor II

Alan,

I'm looking to do that same thing and was wondering - did you have any lag issues when using the denounce approach? Was there a delay between when the map is actually zoomed and when the zoom event is done?

0 Kudos