Search code examples
javascriptopenlayers

Merge Advanced View Positioning and View Animation functions


A while ago I posted a question in gis.stackexchange, but didn't solve very much for me. I'm going to try here now.

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. In the gis.stackexchange question that I linked the user @Mike was able to merge the functions, but it did not worked with the raster extent):


Solution

  • Working snippet based on the second edit on Feb 15 of answer to the original question

      proj4.defs("EPSG:31982","+proj=utm +zone=22 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
      if (ol.proj.proj4 && ol.proj.proj4.register) { ol.proj.proj4.register(proj4); }
    
      var view = new ol.View({
        center: [0, 0],
        zoom: 1
      });
      var map = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          })
        ],
        target: 'map',
        controls: ol.control.defaults({
          attributionOptions: {
            collapsible: false
          }
        }),
        view: view
      });
    
      var flytoparqueorion = document.getElementById('flytoparqueorion');
      flytoparqueorion.addEventListener('click', function() {
    
        var oldCenter = view.getCenter();
        var oldZoom = view.getZoom();
        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});
        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);
      .mapcontainer {
        position: relative;
        margin-bottom: 20px;
      }
      .map {
        width: 1000px;
        height: 600px;
      }
      div.ol-zoom {
        top: 178px;
        left: 158px;
      }
      div.ol-rotate {
        top: 178px;
        right: 58px;
      }
      .map div.ol-attribution {
        bottom: 30px;
        right: 50px;
      }
      .padding-top {
        position: absolute;
        top: 0;
        left: 0px;
        width: 1000px;
        height: 170px;
        background: rgba(255, 255, 255, 0.5);
      }
      .padding-left {
        position: absolute;
        top: 170px;
        left: 0;
        width: 150px;
        height: 400px;
        background: rgba(255, 255, 255, 0.5);
      }
      .padding-right {
        position: absolute;
        top: 170px;
        left: 950px;
        width: 50px;
        height: 400px;
        background: rgba(255, 255, 255, 0.5);
      }
      .padding-bottom {
        position: absolute;
        top: 570px;
        left: 0px;
        width: 1000px;
        height: 30px;
        background: rgba(255, 255, 255, 0.5);
      }
      .center {
        position: absolute;
        border: solid 1px black;
        top: 490px;
        left: 560px;
        width: 20px;
        height: 20px;
      }
    <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
    <div class="mapcontainer">
      <div id="map" class="map"></div>
      <div class="padding-top"></div>
      <div class="padding-left"></div>
      <div class="padding-right"></div>
      <div class="padding-bottom"></div>
      <div class="center"></div>
    </div>
    <button id="flytoparqueorion">Fly to Parque Orion</button>