1

I'm trying to merge two functions that are displayed as OL's samples, the Advanced View Positioning and the View Animation. I can successfully change the view with the animation method, but I can't fix the zoom as in the Advanced View Postitioning method. I'm using these methods to change the view of some rasters loaded in OL. My problem is related only with the zoom level, how can I make it fit to the raster that I'm using? I believe that I need to get the raster extent (already did it) and somehow calculate and link to the zoom section in the flyTo() function.

OL version: 5.3

Function I'm using for the animation:

//This is one of the locations I using with the View Animation method
var randomLocation = transform(getCenter([565280.904542, 6924581.621580, 565319.267400, 6924554.342636]), 'EPSG:31982', 'EPSG:3857');

function flyTo(location, done) {
  var duration = 3000;
  var zoom = view.getZoom();
  var parts = 2;
  var called = false;
  function callback(complete) {
    --parts;
    if (called) {
      return;
    }
    if (parts === 0 || !complete) {
      called = true;
      done(complete);
    }
  }
  view.animate({
    center: location,
    duration: duration
  }, callback);
  view.animate({
    zoom: zoom - 2,
    duration: duration / 2
  }, {
    zoom: zoom,
    duration: duration / 2
  }, callback);
}

Some links that are related but did not help me (most of them use the fit(extent) function. I tried to use it but it cancels the animate() function):

3
  • 1
    Instead of flying to location you should fly to where the full map will be centered if location is centered in the padded area. An offset of n pixels on the screen is n * view.getResolution() in map coordinates. You will need map.getSize() and the padding array to calculate the horizontal and vertical values for n.
    – Mike
    Feb 11, 2019 at 15:39
  • Although it might be overkill in this case, for more complex animations such as rotation in an offset view you might need to offset the center of the map by using an oversized map and hiding the overflow. Then as a quick way to reposition all the controls overlay the main map with a shared view map (as in openlayers.org/en/latest/examples/side-by-side.html except not side by side). mikenunn.16mb.com/demo/view-on-view-br.html mikenunn.16mb.com/demo/view-on-view-bl.html mikenunn.16mb.com/demo/view-on-view-tl.html mikenunn.16mb.com/demo/view-on-view-tr.html
    – Mike
    Feb 11, 2019 at 19:35
  • I'm not sure if I understand correctly, the location that I'm using and trying to fly to is going to be centered on map, just as in the View Animation. I added a location that I'm using on top of the code to be more clear. In the Advanced View Positioning the algorithm get the geometry from the GeoJSON VectorSource to use the view.fit() function. I wonder if it is not possible to do the same with a raster and apply in this flyTo() function. Feb 12, 2019 at 10:49

1 Answer 1

1

I've experimented with the example and found an easy way to do it. Use .fit to get the desired final outcome, save the resulting center and zoom, then immediately go back to the starting point. You can then flight animate the same movement. Any of the other animation examples should also work.

  var flytolausanne = document.getElementById('flytolausanne');
  flytolausanne.addEventListener('click', function() {

    var feature = source.getFeatures()[1];
    var point = /** @type {ol.geom.SimpleGeometry} */ (feature.getGeometry());
    var oldCenter = view.getCenter();
    var oldZoom = view.getZoom();
    view.fit(point, {padding: [170, 50, 30, 150], minResolution: 50});
    var newCenter = view.getCenter();
    var newZoom = view.getZoom();
    view.setCenter(oldCenter);
    view.setZoom(oldZoom);

    flightZoom = Math.min(oldZoom, newZoom) - 2;
    zoomUp = oldZoom - flightZoom;
    zoomDown = newZoom - flightZoom;

    var duration = 2000;
    var parts = 2;
    var called = false;
    function callback(complete) {
      --parts;
      if (called) {
        return;
      }
      if (parts === 0 || !complete) {
        called = true;
        //done(complete);
      }
    }
    view.animate({
      center: newCenter,
      duration: duration
    }, callback);
    view.animate({
      zoom: flightZoom,
      duration: duration * zoomUp / (zoomUp + zoomDown)
    }, {
      zoom: newZoom,
      duration: duration * zoomDown / (zoomUp + zoomDown)
    }, callback);

  }, false);

enter image description here

enter image description here

Just as someone has entered the coordinates for the outline of Switzerland in switzerland.geojson in the example you will need to define your own extent. It you want to use same the extent as above you would simply replace the minimum resolution fit with constrain resolution for a best fit:

var extent = ol.proj.transformExtent([565280.904542, 6924581.621580, 565319.267400, 6924554.342636], 'EPSG:31982', 'EPSG:3857');
view.fit(extent, {padding: [170, 50, 30, 150], constrainResolution: false});
7
  • Thanks Mike, I already tried something like this. The problem is that I can't get the features with the source.getFeatures()[1]; or the geometry from the raster. This is my only problem with the view.fit() function, since I can't use with the raster extention or other raster related object. I tried several ways to accomplish this, but all unsuccessful. Thats why I passed the raster extent in top of the code, being that I can get the extent from the ImageLayer without problems. This works nice if I have only vectors though. Feb 13, 2019 at 10:30
  • To convert coordinates to a geometry point = new.ol.geom.Point(randomLocation); The extent of a single coordinate is randomLocation.concat(randomLocation);
    – Mike
    Feb 13, 2019 at 11:34
  • Okay, so using the point = new Point({randomLocation}); gave me a blank screen with no erros. Passing the var point to console shows that the extension as: extent_: (4) [Infinity, Infinity, -Infinity, -Infinity], I guess that is the problem. Using the randomLocation.concat(randomLocation); as a point works in your function, but the zoom is still wrong related to the raster, being now too far away and positioned northwest. Feb 14, 2019 at 12:03
  • Point syntax should be new Point(randomLocation) without the { }
    – Mike
    Feb 15, 2019 at 10:00
  • Thank you for the correction. This fixed the blank screen problem, but the zoom keeps with the same situation, too far and northwest related to the location. Feb 15, 2019 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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