show transpacific flights
This commit is contained in:
@@ -7,6 +7,7 @@ import View from '../src/ol/View.js';
|
|||||||
import {Stroke, Style} from '../src/ol/style.js';
|
import {Stroke, Style} from '../src/ol/style.js';
|
||||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||||
import {getVectorContext} from '../src/ol/render.js';
|
import {getVectorContext} from '../src/ol/render.js';
|
||||||
|
import {getWidth} from '../src/ol/extent.js';
|
||||||
|
|
||||||
const tileLayer = new TileLayer({
|
const tileLayer = new TileLayer({
|
||||||
source: new Stamen({
|
source: new Stamen({
|
||||||
@@ -18,7 +19,7 @@ const map = new Map({
|
|||||||
layers: [tileLayer],
|
layers: [tileLayer],
|
||||||
target: 'map',
|
target: 'map',
|
||||||
view: new View({
|
view: new View({
|
||||||
center: [0, 0],
|
center: [-11000000, 4600000],
|
||||||
zoom: 2,
|
zoom: 2,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -31,7 +32,6 @@ const style = new Style({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const flightsSource = new VectorSource({
|
const flightsSource = new VectorSource({
|
||||||
wrapX: false,
|
|
||||||
attributions:
|
attributions:
|
||||||
'Flight data by ' +
|
'Flight data by ' +
|
||||||
'<a href="https://openflights.org/data.html">OpenFlights</a>,',
|
'<a href="https://openflights.org/data.html">OpenFlights</a>,',
|
||||||
@@ -55,18 +55,23 @@ const flightsSource = new VectorSource({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const arcLine = arcGenerator.Arc(100, {offset: 10});
|
const arcLine = arcGenerator.Arc(100, {offset: 10});
|
||||||
if (arcLine.geometries.length === 1) {
|
// paths which cross the -180°/+180° meridian are split
|
||||||
const line = new LineString(arcLine.geometries[0].coords);
|
// into two sections which will be animated sequentially
|
||||||
|
const features = [];
|
||||||
|
arcLine.geometries.forEach(function (geometry) {
|
||||||
|
const line = new LineString(geometry.coords);
|
||||||
line.transform('EPSG:4326', 'EPSG:3857');
|
line.transform('EPSG:4326', 'EPSG:3857');
|
||||||
|
|
||||||
const feature = new Feature({
|
features.push(
|
||||||
geometry: line,
|
new Feature({
|
||||||
finished: false,
|
geometry: line,
|
||||||
});
|
finished: false,
|
||||||
// add the feature with a delay so that the animation
|
})
|
||||||
// for all features does not start at the same time
|
);
|
||||||
addLater(feature, i * 50);
|
});
|
||||||
}
|
// add the features with a delay so that the animation
|
||||||
|
// for all features does not start at the same time
|
||||||
|
addLater(features, i * 50);
|
||||||
}
|
}
|
||||||
tileLayer.on('postrender', animateFlights);
|
tileLayer.on('postrender', animateFlights);
|
||||||
});
|
});
|
||||||
@@ -88,7 +93,7 @@ const flightsLayer = new VectorLayer({
|
|||||||
|
|
||||||
map.addLayer(flightsLayer);
|
map.addLayer(flightsLayer);
|
||||||
|
|
||||||
const pointsPerMs = 0.1;
|
const pointsPerMs = 0.02;
|
||||||
function animateFlights(event) {
|
function animateFlights(event) {
|
||||||
const vectorContext = getVectorContext(event);
|
const vectorContext = getVectorContext(event);
|
||||||
const frameState = event.frameState;
|
const frameState = event.frameState;
|
||||||
@@ -101,26 +106,41 @@ function animateFlights(event) {
|
|||||||
// only draw the lines for which the animation has not finished yet
|
// only draw the lines for which the animation has not finished yet
|
||||||
const coords = feature.getGeometry().getCoordinates();
|
const coords = feature.getGeometry().getCoordinates();
|
||||||
const elapsedTime = frameState.time - feature.get('start');
|
const elapsedTime = frameState.time - feature.get('start');
|
||||||
const elapsedPoints = elapsedTime * pointsPerMs;
|
if (elapsedTime >= 0) {
|
||||||
|
const elapsedPoints = elapsedTime * pointsPerMs;
|
||||||
|
|
||||||
if (elapsedPoints >= coords.length) {
|
if (elapsedPoints >= coords.length) {
|
||||||
feature.set('finished', true);
|
feature.set('finished', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxIndex = Math.min(elapsedPoints, coords.length);
|
||||||
|
const currentLine = new LineString(coords.slice(0, maxIndex));
|
||||||
|
|
||||||
|
// animation is needed in the current and nearest adjacent wrapped world
|
||||||
|
const worldWidth = getWidth(map.getView().getProjection().getExtent());
|
||||||
|
const offset = Math.floor(map.getView().getCenter()[0] / worldWidth);
|
||||||
|
|
||||||
|
// directly draw the lines with the vector context
|
||||||
|
currentLine.translate(offset * worldWidth, 0);
|
||||||
|
vectorContext.drawGeometry(currentLine);
|
||||||
|
currentLine.translate(worldWidth, 0);
|
||||||
|
vectorContext.drawGeometry(currentLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxIndex = Math.min(elapsedPoints, coords.length);
|
|
||||||
const currentLine = new LineString(coords.slice(0, maxIndex));
|
|
||||||
|
|
||||||
// directly draw the line with the vector context
|
|
||||||
vectorContext.drawGeometry(currentLine);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tell OpenLayers to continue the animation
|
// tell OpenLayers to continue the animation
|
||||||
map.render();
|
map.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLater(feature, timeout) {
|
function addLater(features, timeout) {
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
feature.set('start', Date.now());
|
let start = Date.now();
|
||||||
flightsSource.addFeature(feature);
|
features.forEach(function (feature) {
|
||||||
|
feature.set('start', start);
|
||||||
|
flightsSource.addFeature(feature);
|
||||||
|
const duration =
|
||||||
|
(feature.getGeometry().getCoordinates().length - 1) / pointsPerMs;
|
||||||
|
start += duration;
|
||||||
|
});
|
||||||
}, timeout);
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user