Merge pull request #12463 from MoonE/feature-animation-example

Improve animation examples
This commit is contained in:
MoonE
2021-07-04 15:39:31 +02:00
committed by GitHub
4 changed files with 56 additions and 67 deletions

View File

@@ -16,8 +16,15 @@ const tileLayer = new TileLayer({
}),
});
const source = new VectorSource({
wrapX: false,
});
const vector = new VectorLayer({
source: source,
});
const map = new Map({
layers: [tileLayer],
layers: [tileLayer, vector],
target: 'map',
view: new View({
center: [0, 0],
@@ -26,17 +33,9 @@ const map = new Map({
}),
});
const source = new VectorSource({
wrapX: false,
});
const vector = new VectorLayer({
source: source,
});
map.addLayer(vector);
function addRandomFeature() {
const x = Math.random() * 360 - 180;
const y = Math.random() * 180 - 90;
const y = Math.random() * 170 - 85;
const geom = new Point(fromLonLat([x, y]));
const feature = new Feature(geom);
source.addFeature(feature);
@@ -44,14 +43,18 @@ function addRandomFeature() {
const duration = 3000;
function flash(feature) {
const start = new Date().getTime();
const start = Date.now();
const flashGeom = feature.getGeometry().clone();
const listenerKey = tileLayer.on('postrender', animate);
function animate(event) {
const vectorContext = getVectorContext(event);
const frameState = event.frameState;
const flashGeom = feature.getGeometry().clone();
const elapsed = frameState.time - start;
if (elapsed >= duration) {
unByKey(listenerKey);
return;
}
const vectorContext = getVectorContext(event);
const elapsedRatio = elapsed / duration;
// radius will be 5 at start and 30 at end.
const radius = easeOut(elapsedRatio) * 25 + 5;
@@ -69,10 +72,6 @@ function flash(feature) {
vectorContext.setStyle(style);
vectorContext.drawGeometry(flashGeom);
if (elapsed > duration) {
unByKey(listenerKey);
return;
}
// tell OpenLayers to continue postrender animation
map.render();
}

View File

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

View File

@@ -120,7 +120,7 @@ function animateFlights(event) {
function addLater(feature, timeout) {
window.setTimeout(function () {
feature.set('start', new Date().getTime());
feature.set('start', Date.now());
flightsSource.addFeature(feature);
}, timeout);
}

View File

@@ -46,7 +46,7 @@ function updateInfo() {
function setTime() {
startDate.setMinutes(startDate.getMinutes() + 15);
if (startDate > new Date()) {
if (startDate > Date.now()) {
startDate = threeHoursAgo();
}
layers[1].getSource().updateParams({'TIME': startDate.toISOString()});