Select to view content in your preferred language

Detect change in zoom when complete

6008
8
Jump to solution
06-19-2017 11:58 AM
AlanMervitz
Deactivated User

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
Frequent Contributor

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
Deactivated User

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
Deactivated User

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
Regular Contributor

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

ThomasSolow
Frequent Contributor

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
Deactivated User

The debounce approach is working beautifully, thanks!

0 Kudos
AbdulKhan
Emerging Contributor

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