0

I'm currently on a ReactJS+Nodejs application, trying to integrate OpenLayers. What I need is to change the GPS position of a marker, in real-time (via socket.io).

So far, I've come up with this code:

this.map = new Map({
        target: "map",
        layers: [
            new TileLayer({
                source: new XYZ({
                    attributions: 'Tiles © <a href="https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer">ArcGIS</a>',
                    url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'
                })
            }),
        ],
        view: new View({
            center: fromLonLat([-8.455826, 40.168307]),
            rotation: 1.1344640138,
            easing: 0.5
        })
    });

    var vectorSource = new VectorSource({});

    var markersLayer = new VectorLayer({
        source: vectorSource,
    });

    this.map.addLayer(markersLayer);

    var point1 = new Point(
        fromLonLat([-8.455826, 40.168307])
    );

    var point2 = new Point(
        fromLonLat([-8.456819, 40.166388])
    );

    var marker = new Feature({
        geometry: point1,
        name: "My point",
    });

    vectorSource.addFeature(marker);

    var style = new Style({
        image: new CircleStyle({
            radius: 7,
            fill: new Fill({color: 'black'}),
            stroke: new Stroke({
                color: 'white', width: 2
            })
        })
    });

    marker.setStyle(style);

    setTimeout(function () {
        marker.setGeometry(point2);
        marker.getGeometry().translate(40, -40);
    }, 3500);

The marker moves, however the transition occurs in an instant. Is there a way to make it move like a "CSS linear transition" to give it a more realistic look?

edwardffs
  • 412
  • 1
  • 5
  • 17

1 Answers1

1

Using a timer you could split the move into steps along the line between the old and new positions, e.g. for 100 10ms steps

var line = new LineString([oldCoordinates, newCoordinates])];
var step = 0;
var key = setInterval( function() {
  if (step < 100) {
    step++;
    marker.setGeometry(new Point(line.getCoordinateAt(step/100)));
  } else {
    clearInterval(key);
  }
}, 10);

You might also be able to base something on the flight animation example https://openlayers.org/en/latest/examples/flight-animation.html

Mike
  • 16,042
  • 2
  • 14
  • 30
  • Really neat trick. I only discovered OpenLayers yesterday, so it still amazes/scares me how feature-rich this is. How good will this method perform with 50-100 markers being updated? (Performance-wise, I mean) – edwardffs Feb 27 '19 at 16:49
  • 1
    It would probably be best to have a single timer where you update the steps of each marker which need it in one go so only one re-render of the layer is needed. Multiple timers running independently for each marker might affect performance. – Mike Feb 27 '19 at 20:03
  • That would work if the updates were independent. I'm currently receiving the updates together in an array. I'll still have to figure something out. – edwardffs Feb 28 '19 at 12:35