From f506f4bdc999f32da8009f9aefa5f293ff520bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Fri, 2 Jul 2021 22:55:13 +0200 Subject: [PATCH 1/3] Improve feature-animation example Keep features within tile bounds Skip drawing fully transparent style Don't clone the geometry each frame --- examples/feature-animation.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/examples/feature-animation.js b/examples/feature-animation.js index c1391ff2a1..7d469cc1e0 100644 --- a/examples/feature-animation.js +++ b/examples/feature-animation.js @@ -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); @@ -45,13 +44,17 @@ function addRandomFeature() { const duration = 3000; function flash(feature) { const start = new Date().getTime(); + 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(); } From d7d0eeb7c745a060bc6acd1fd7e828e665604f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Fri, 2 Jul 2021 23:01:11 +0200 Subject: [PATCH 2/3] Prefer Date.now() when possible --- examples/feature-animation.js | 2 +- examples/feature-move-animation.js | 2 +- examples/flight-animation.js | 2 +- examples/wms-time.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/feature-animation.js b/examples/feature-animation.js index 7d469cc1e0..a9aa58ed69 100644 --- a/examples/feature-animation.js +++ b/examples/feature-animation.js @@ -43,7 +43,7 @@ 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); diff --git a/examples/feature-move-animation.js b/examples/feature-move-animation.js index 95573e7a92..c5b6166cc1 100644 --- a/examples/feature-move-animation.js +++ b/examples/feature-move-animation.js @@ -142,7 +142,7 @@ fetch('data/polyline/route.json').then(function (response) { stopAnimation(false); } else { animating = true; - startTime = new Date().getTime(); + startTime = Date.now(); speed = speedInput.value; startButton.textContent = 'Cancel Animation'; // hide geoMarker diff --git a/examples/flight-animation.js b/examples/flight-animation.js index 8948b4a438..8c13b907b2 100644 --- a/examples/flight-animation.js +++ b/examples/flight-animation.js @@ -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); } diff --git a/examples/wms-time.js b/examples/wms-time.js index 356634a31a..a2c7419f32 100644 --- a/examples/wms-time.js +++ b/examples/wms-time.js @@ -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()}); From a6d86ce0dd967ae8bfddf992db5142968f100164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sat, 3 Jul 2021 01:06:51 +0200 Subject: [PATCH 3/3] Update marker animation example Continually animate between start and end position Allow changing speed during animation Stay at current position when animation stops --- examples/feature-move-animation.js | 86 +++++++++++++----------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/examples/feature-move-animation.js b/examples/feature-move-animation.js index c5b6166cc1..7db598150d 100644 --- a/examples/feature-move-animation.js +++ b/examples/feature-move-animation.js @@ -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 = Date.now(); - 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(); + } + }); }); });