Merge pull request #12463 from MoonE/feature-animation-example
Improve animation examples
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()});
|
||||
|
||||
Reference in New Issue
Block a user