0

I want to add moving arrows or overlay animation in the Flights Animation example in OpenLayers 6.

I tried doing the overlay moving animation with JavaScript setInterval(), but so far I have only succeeded in animating a single LineString, that too after the line is finished drawing. I wanted to add the moving animation as the line is being drawn, kind of like tracing the LineString's path.

Can someone please help me with this?

Following is the code snippet where I have tried to add the moving animation:

var markerEl = document.getElementById('geo-marker');
var marker = new Overlay({
  positioning: 'center-center',
  offset: [0, 0],
  element: markerEl,
  stopEvent: false
});
map.addOverlay(marker);

function animateFlights(event) {
  var coords;
  var vectorContext = getVectorContext(event);
  var frameState = event.frameState;

  var features = flightSource.getFeatures();
  for (var i = 0; i < features.length; i++) {
    var feature = features[i];
    if (!feature.get('finished')) {
      coords = feature.getGeometry().getCoordinates();
      var elapsedTime = frameState.time - feature.get('start');
      var elapsedPoints = elapsedTime * pointsPerMs;

      if (elapsedPoints >= coords.length) {
        feature.set('finished', true);
      }

      var maxIndex = Math.min(elapsedPoints, coords.length);
      var currentLine = new LineString(coords.slice(0, maxIndex));
      vectorContext.setStyle(strokeStyle1);
      vectorContext.drawGeometry(currentLine);

      if (feature.get('finished')) {
        var interval = setInterval(
          function () { return animatePath(coords, interval) }, 10);
      }
    }
  }
  map.render();
}

function animatePath(path, clearInterval) {
  if (i == path.length) {
    stopAnimatePath(clearInterval);
  }
  marker.setPosition(path[i]);
  i = i + 1;
}

function stopAnimatePath(clearInterval) {
  clearInterval(clearInterval);
}

Here is a link to a snapshot of how my app looks right now

Community
  • 1
  • 1
  • 1
    To use an icon in vector context (which uses an immediate render with no support for asynchronous loading) it must be created from a pre-loaded image, for example https://codesandbox.io/s/dynamic-data-3x8ux – Mike Nov 19 '19 at 15:52
  • I have added a screenshot of how my app looks right now. I have been able to add the arrows to lines , but only on the centre of the lines and have not been able to add moving animation to them. – Saumya Srivastava Nov 19 '19 at 15:52
  • @Mike, Wow... That animation is really cool. And I might be able to get something out of this. Lemme go figure . Thanks ! – Saumya Srivastava Nov 19 '19 at 16:02

1 Answers1

0

Trace your LineString

It should be enough to set your map center to the last point of your LineString if you update often enough

map.getView().setCenter(lastPoint)

If it gets laggy use

var pan = ol.animation.pan({
   source: map.getView().getCenter()
});
map.beforeRender(pan);
map.getView().setCenter(lastPoint);

Draw arrows

To draw arrows on your LineString you can use the following style

var styleFunction = function (feature) {
    var geometry = feature.getGeometry();
    var styles = [
        // linestring
        new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#000',
                width: 2
            })
        })
    ];

    geometry.forEachSegment(function (start, end) {
        var dx = end[0] - start[0];
        var dy = end[1] - start[1];
        var rotation = Math.atan2(dy, dx);

        styles.push(new ol.style.Style({
          geometry: new ol.geom.Point(end),
          image: new ol.style.RegularShape({
            fill: new ol.style.Fill({color: '#000'}),
            points: 3,
            radius: 8,
            rotation: -rotation,
            angle: Math.PI / 2 // rotate 90°
          })
        }));
    });

    return styles;
};

more details: https://stackoverflow.com/a/58237497/546526

megges
  • 570
  • 1
  • 3
  • 11