This example uses OpenLayers v10.9.0. The latest is v.
Edit

#### Flight Animation

animation 5 vector 86 feature 12 flights 1 arc 1

#####

Demonstrates how to animate flights with ´postrender´.

This example shows how to use postrender and vectorContext to animate flights. A great circle arc between two airports is calculated using arc.js and then the flight paths are animated with postrender. The flight data is provided by OpenFlights (a simplified data set from the Mapbox.js documentation is used).

##### main.js

    import Feature from 'ol/Feature.js';
    import Map from 'ol/Map.js';
    import View from 'ol/View.js';
    import {getWidth} from 'ol/extent.js';
    import LineString from 'ol/geom/LineString.js';
    import TileLayer from 'ol/layer/Tile.js';
    import VectorLayer from 'ol/layer/Vector.js';
    import {getVectorContext} from 'ol/render.js';
    import StadiaMaps from 'ol/source/StadiaMaps.js';
    import VectorSource from 'ol/source/Vector.js';
    import Stroke from 'ol/style/Stroke.js';
    import Style from 'ol/style/Style.js';

    const tileLayer = new TileLayer({
      source: new StadiaMaps({
        layer: 'stamen_toner',
      }),
    });

    const map = new Map({
      layers: [tileLayer],
      target: 'map',
      view: new View({
        center: [-11000000, 4600000],
        zoom: 2,
      }),
    });

    const style = new Style({
      stroke: new Stroke({
        color: '#EAE911',
        width: 2,
      }),
    });

    const flightsSource = new VectorSource({
      attributions:
        'Flight data by ' +
        '<a href="https://openflights.org/data.html">OpenFlights</a>,',
      loader: function () {
        const url = 'data/openflights/flights.json';
        fetch(url)
          .then(function (response) {
            return response.json();
          })
          .then(function (json) {
            const flightsData = json.flights;
            for (let i = 0; i < flightsData.length; i++) {
              const flight = flightsData[i];
              const from = flight[0];
              const to = flight[1];

              // create an arc circle between the two locations
              const arcGenerator = new arc.GreatCircle(
                {x: from[1], y: from[0]},
                {x: to[1], y: to[0]},
              );

              const arcLine = arcGenerator.Arc(100, {offset: 10});
              // paths which cross the -180°/+180° meridian are split
              // into two sections which will be animated sequentially
              const features = [];
              arcLine.geometries.forEach(function (geometry) {
                const line = new LineString(geometry.coords);
                line.transform('EPSG:4326', 'EPSG:3857');

                features.push(
                  new Feature({
                    geometry: line,
                    finished: false,
                  }),
                );
              });
              // add the features with a delay so that the animation
              // for all features does not start at the same time
              addLater(features, i * 50);
            }
            tileLayer.on('postrender', animateFlights);
          });
      },
    });

    const flightsLayer = new VectorLayer({
      source: flightsSource,
      style: function (feature) {
        // if the animation is still active for a feature, do not
        // render the feature with the layer style
        if (feature.get('finished')) {
          return style;
        }
        return null;
      },
    });

    map.addLayer(flightsLayer);

    const pointsPerMs = 0.02;
    function animateFlights(event) {
      const vectorContext = getVectorContext(event);
      const frameState = event.frameState;
      vectorContext.setStyle(style);

      const features = flightsSource.getFeatures();
      for (let i = 0; i < features.length; i++) {
        const feature = features[i];
        if (!feature.get('finished')) {
          // only draw the lines for which the animation has not finished yet
          const coords = feature.getGeometry().getCoordinates();
          const elapsedTime = frameState.time - feature.get('start');
          if (elapsedTime >= 0) {
            const elapsedPoints = elapsedTime * pointsPerMs;

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

            const maxIndex = Math.min(elapsedPoints, coords.length);
            const currentLine = new LineString(coords.slice(0, maxIndex));

            // animation is needed in the current and nearest adjacent wrapped world
            const worldWidth = getWidth(map.getView().getProjection().getExtent());
            const offset = Math.floor(map.getView().getCenter()[0] / worldWidth);

            // directly draw the lines with the vector context
            currentLine.translate(offset * worldWidth, 0);
            vectorContext.drawGeometry(currentLine);
            currentLine.translate(worldWidth, 0);
            vectorContext.drawGeometry(currentLine);
          }
        }
      }
      // tell OpenLayers to continue the animation
      map.render();
    }

    function addLater(features, timeout) {
      window.setTimeout(function () {
        let start = Date.now();
        features.forEach(function (feature) {
          feature.set('start', start);
          flightsSource.addFeature(feature);
          const duration =
            (feature.getGeometry().getCoordinates().length - 1) / pointsPerMs;
          start += duration;
        });
      }, timeout);
    }

##### index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Flight Animation</title>
        <link rel="stylesheet" href="node_modules/ol/ol.css">
        <style>
          .map {
            width: 100%;
            height: 400px;
          }
        </style>
      </head>
      <body>
        <div id="map" class="map"></div>

        <script src="https://api.mapbox.com/mapbox.js/plugins/arc.js/v0.1.0/arc.js"></script>
        <script type="module" src="main.js"></script>
      </body>
    </html>

##### package.json

    {
      "name": "flight-animation",
      "dependencies": {
        "ol": "10.9.0"
      },
      "devDependencies": {
        "vite": "^3.2.3"
      },
      "scripts": {
        "start": "vite",
        "build": "vite build"
      }
    }