Update marker animation example

Continually animate between start and end position
Allow changing speed during animation
Stay at current position when animation stops
This commit is contained in:
Maximilian Krög
2021-07-03 01:06:51 +02:00
parent d7d0eeb7c7
commit a6d86ce0dd

View File

@@ -57,17 +57,18 @@ fetch('data/polyline/route.json').then(function (response) {
type: 'route', type: 'route',
geometry: route, geometry: route,
}); });
const geoMarker = new Feature({
type: 'geoMarker',
geometry: new Point(route.getCoordinateAt(0)),
});
const startMarker = new Feature({ const startMarker = new Feature({
type: 'icon', type: 'icon',
geometry: new Point(route.getCoordinateAt(0)), geometry: new Point(route.getFirstCoordinate()),
}); });
const endMarker = new Feature({ const endMarker = new Feature({
type: 'icon', type: 'icon',
geometry: new Point(route.getCoordinateAt(1)), geometry: new Point(route.getLastCoordinate()),
});
const position = startMarker.getGeometry().clone();
const geoMarker = new Feature({
type: 'geoMarker',
geometry: position,
}); });
const styles = { const styles = {
@@ -95,76 +96,65 @@ fetch('data/polyline/route.json').then(function (response) {
}), }),
}; };
let animating = false;
const vectorLayer = new VectorLayer({ const vectorLayer = new VectorLayer({
source: new VectorSource({ source: new VectorSource({
features: [routeFeature, geoMarker, startMarker, endMarker], features: [routeFeature, geoMarker, startMarker, endMarker],
}), }),
style: function (feature) { style: function (feature) {
// hide geoMarker if animation is active
if (animating && feature.get('type') === 'geoMarker') {
return null;
}
return styles[feature.get('type')]; return styles[feature.get('type')];
}, },
}); });
map.addLayer(vectorLayer); map.addLayer(vectorLayer);
let speed, startTime;
const speedInput = document.getElementById('speed'); const speedInput = document.getElementById('speed');
const startButton = document.getElementById('start-animation'); const startButton = document.getElementById('start-animation');
let animating = false;
let distance = 0;
let lastTime;
function moveFeature(event) { function moveFeature(event) {
const speed = Number(speedInput.value);
const time = event.frameState.time;
const elapsedTime = time - lastTime;
distance = (distance + (speed * elapsedTime) / 1e6) % 2;
lastTime = time;
const currentCoordinate = route.getCoordinateAt(
distance > 1 ? 2 - distance : distance
);
position.setCoordinates(currentCoordinate);
const vectorContext = getVectorContext(event); const vectorContext = getVectorContext(event);
const frameState = event.frameState; vectorContext.setStyle(styles.geoMarker);
vectorContext.drawGeometry(position);
if (animating) {
const elapsedTime = frameState.time - startTime;
const distance = (speed * elapsedTime) / 1e6;
if (distance >= 1) {
stopAnimation(true);
return;
}
const currentPoint = new Point(route.getCoordinateAt(distance));
const feature = new Feature(currentPoint);
vectorContext.drawFeature(feature, styles.geoMarker);
}
// tell OpenLayers to continue the postrender animation // tell OpenLayers to continue the postrender animation
map.render(); map.render();
} }
function startAnimation() { function startAnimation() {
if (animating) {
stopAnimation(false);
} else {
animating = true; animating = true;
startTime = Date.now(); lastTime = Date.now();
speed = speedInput.value; startButton.textContent = 'Stop Animation';
startButton.textContent = 'Cancel Animation';
// hide geoMarker
geoMarker.changed();
// just in case you pan somewhere else
map.getView().setCenter(center);
vectorLayer.on('postrender', moveFeature); vectorLayer.on('postrender', moveFeature);
map.render(); // hide geoMarker and trigger map render through change event
} geoMarker.setGeometry(null);
} }
function stopAnimation(ended) { function stopAnimation() {
animating = false; animating = false;
startButton.textContent = 'Start Animation'; startButton.textContent = 'Start Animation';
// if animation cancelled set the marker at the beginning // Keep marker at current animation position
const coord = route.getCoordinateAt(ended ? 1 : 0); geoMarker.setGeometry(position);
geoMarker.getGeometry().setCoordinates(coord);
// remove listener
vectorLayer.un('postrender', moveFeature); vectorLayer.un('postrender', moveFeature);
} }
startButton.addEventListener('click', startAnimation, false); startButton.addEventListener('click', function () {
if (animating) {
stopAnimation();
} else {
startAnimation();
}
});
}); });
}); });