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:
@@ -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();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user