4
votes

I'm developing integration between google maps and openlayers 4. I based my work on this example from documentation for openlayers 3.

My problem is that somewhere between ol 3 and ol 4.4.2 behaviour of change:resolution event was changed. Previously this code

view.on('change:resolution', () => {
    console.log(view.getZoom())  
})

was only called once per mouse wheel rotation and logged (for example):

5

and now it produces something like this:

4.017277252772164
4.08563754449778
4.152661471658049
4.522609511830051
4.691606503462093
4.793368457643155
4.891103916717288
4.980192777999678
4.999621855713164
5

So when I try to synchronize zoom between google map and openlayers (like in the example) it causes google map to flash on every zoom. It seems that google map doesn't support fractional values for zoom.

Can I either restrict openlayer zoom values to integers or do some work around?

I tried to use ceil/floor values of openlayers zoom when calling googleMap.setZoom but because zooming also involves changes of center location it results in jerky, unpleasant behaviour.

2

2 Answers

1
votes

The default behavior is for better tablet and trackpad support when pinch zooming.

interactions: ol.interaction.defaults({mouseWheelZoom: false}).extend([
      new ol.interaction.MouseWheelZoom({
        constrainResolution: true // force zooming to a integer zoom
      })
    ])

per http://openlayers.org/en/latest/examples/mousewheel-zoom.html

0
votes

For anyone who would be struggling with this issue, the way I solved this was to set the zoomDuration of the default zoom interactions to 0, combined with the constrainResolution property.

The in-between zoom levels come from the animation used to zoom from one level to another (default duration of the animation is 250ms). By using constrainResolution you ensure that you have an integer value that can be used by Google Map, and by setting zoomDuration to 0 you remove the animation that caused the fractional values in the change:resolution handler.

The result is a little bit more abrupt without the animation, but that way there's no more weird behavior between OpenLayers and Google Map.

I'm working with OpenLayers 6.5.0, but I guess that it would work with earlier versions as well. Here is the working piece of code:

import { defaults } from 'ol/interaction';

// ...

this.view = new View({
    // ...
    constrainResolution: true,
});
    
const olMap = new Map({
    target: 'map',
    controls: [],
    layers: [],
    view: this.view,
    interactions: defaults({ zoomDuration: 0 }),
});