3

There is no appropriate zoom event listener in OpenLayers v5.3 yet, but there is a workaround suggested in this ticket:

You can use this.view.instance.on('change:zoom', evt => console.log(this.view.zoom)); where view is a viewChild : @ViewChild(ViewComponent) view: ViewComponent; to detect zoom changes.

Can anyone please explain to newbies how to utilize this? How to use that weird :-) code with an instance of a map view which is usually got by calling map.getView()?

  • 1
    That syntax is being used with Angular. You don't need a zoom change event, if the zoom changes so does the resolution, so you can use view.on('change:resolution', function() { }); – Mike Jan 21 at 15:22
  • The 'change:resolution' event is triggered about a dozen times for one zoom level change. The intermediate values are non-integer and the last one is always integer as far as I can see. Is there a way to catch just the final integer value? – yaugenka Jan 21 at 16:04
  • Mousewheel operations can sometimes leave the map at a fractional zoom level, but if you are only interested in catching integer values you could test if (map.getView().getZoom()%1 == 0) { } inside the callback – Mike Jan 21 at 16:23
  • Is it possible to the final value may be fractional? – yaugenka Jan 21 at 16:56
  • In some situations it might openlayers.org/en/v4.6.5/apidoc/ol.interaction.html but you can set interactions: ol.interaction.defaults({ constrainResolution: true }), as a map option to prevent it – Mike Jan 21 at 17:52
3

To hook on zoom end event is fairly simple: listen to moveend event and compare old and new zoom:

var currZoom = map.getView().getZoom();
map.on('moveend', function(e) {
  var newZoom = map.getView().getZoom();
  if (currZoom != newZoom) {
    console.log('zoom end, new zoom: ' + newZoom);
    currZoom = newZoom;
  }
});

If you want to catch zoom start, it's more complicated. I found a way but I don't like it, it's not how it should be done. I noticed that exposed method view.animate is called before any animated map event. I replaced it with my own, where I check for zoom, and then call original method:

view.origAnimate = view.animate;

view.animate = function(animateSpecs) {
  if (typeof animateSpecs.resolution !== 'undefined') {
    var currZoom = this.getZoom();
    var newZoom = this.getZoomForResolution(animateSpecs.resolution);
    if (newZoom != currZoom)) {
      console.log('zoom start, new zoom: ' + newZoom);
    }
  }
  this.origAnimate(animateSpecs);
};
  • Thanks, TomazicM. This solution works equally well as the one suggested by Mike in the question comments. With moveend event you have to filter map pan events where as with change:resulution you have to filer intermediate zoom change events. – yaugenka Jan 22 at 14:56
  • @yaugenka If it works for you, you could mark it as an answer. – TomazicM Jan 22 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.