0

I have a use case where I want to determine if certain coordinates lay within the section of the view visible in the viewport. Our approach is to start by getting the coordinates of some pixels with our map's getCoordinateFromPixel method. This works, but the problem is that we also want to zoom in programmatically. We noticed that calling getCoordinateFromPixel on the map with the exact same arguments returns exactly the same thing before and after calling setZoom on the map's view. Strangely enough (?) we also noticed that when we zoom in manually in between two calls to getCoordinateFromPixel on the map, the results do change.

Take for instance this script:

import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import GeoJSON from 'ol/format/GeoJSON';
import Feature from 'ol/Feature';

let markerView = new View({
    center: [5000, 1000],
    zoom: 2,
});

let map = new Map({
  target: 'map-container',
  layers: [
    new VectorLayer({
      source: new VectorSource({
        format: new GeoJSON(),
        url: './data/countries.json'
      }),
    })
  ],
  view: markerView
});

window.setTimeout(() => {
    console.log(JSON.stringify(map.getCoordinateFromPixel([0, 0])));
    map.getView().setZoom(5);
}, 2000);
window.setTimeout(() => {
    console.log(JSON.stringify(map.getCoordinateFromPixel([0, 0])));
}, 4000);

When one executes this is in an OpenLayers project, the closure running after 2000 ms will print the exact same thing to the console as the one running after 4000 ms, even though we have zoomed in very significantly!

I was wondering if someone knew of a workaround, a fix or just the reason for this. I have tried looking at events the map fires to maybe re-execute getCoordinateFromPixel in a handler, but I haven't found an event the map fires when we (programmatically) change the zoom.

I'll be happy to provide more details if needed.

Thanks a lot in advance,

Joshua

Joshua Schroijen
  • 376
  • 6
  • 23
  • 1
    I doesn't happen when I run that script. The results with vary with map size, so also logging `map.getSize()` I get `[1664,832]` `[-32560951.057032518,16280475.528516259]` `[-4065226.912318814,2035059.4410645324]` – Mike Apr 16 '19 at 15:46
  • To listen for changes to the visible viewport listen for `change:resoliution` and `change:center` on the view `map.getView().on(['change:resolution','change:center'], function() { console.log(JSON.stringify(this.calculateExtent())); });` – Mike Apr 16 '19 at 16:01
  • 1
    However, the result from `map.getCoordinateFromPixel` doesn't seem to be updated when that change event listener function runs. – geocodezip Apr 16 '19 at 16:38
  • I also get that. Pixel [0,0] starts matching the top left of the extent. Then the extent change fires but the coordinate of the pixel hasn't changed. But 2 seconds later is has changed to close to (but not quite) the top left of the new extent. `[1664,832]` `[-32555951.05703252,-16279475.52851626,32565951.05703252,16281475.52851626]` `[-32560951.057032518,16280475.528516259]` `[-4065118.882129065,-2034059.4410645326,4075118.882129065,2036059.4410645326]` `[-32560951.057032518,16280475.528516259]` `[-4065226.912318814,2035059.4410645324]` – Mike Apr 16 '19 at 22:44
  • Hmm, interesting. When I call getCoordinatesFromPixel in a handler of the postrender event of the map (which seems to get executed also after I programmatically zoom in), I get a different value. When I set timeouts to call getCoordinateFromPixel in that handler, I also seem to get consistent results. I will test this more in depth and update this thread if I figure it out more – Joshua Schroijen Apr 17 '19 at 08:43

1 Answers1

1

If you have the extent and map size you can easily calculate the coordinate for a pixel without relying on getCoordinateFromPixel which for some reason doesn't update immediately (it has updated by the precompose event). There is a small different in the x coordinate (about 100 meters in an 8 million extent) but not enough to be significant.

map.getView().on(['change:resolution','change:center'], function() {
  var size = map.getSize();
  var extent = this.calculateExtent(size);
  var coordinate = [
    extent[0] + (extent[2]-extent[0]) * pixel[0]/size[0],
    extent[1] + (extent[3]-extent[1]) * (size[1]-pixel[1])/size[1]
  ];
  console.log(JSON.stringify(extent));
  console.log(JSON.stringify(coordinate));  // as expected
  console.log(JSON.stringify(map.getCoordinateFromPixel(pixel)));  // hasn't been updated
});

.

map.getView().on(['change:resolution','change:center'], function() {
  map.once('precompose', function() {
    console.log(JSON.stringify(map.getCoordinateFromPixel(pixel)));
  });
});
Mike
  • 16,042
  • 2
  • 14
  • 30