Skip to content

bbecquet/bird-tracking

Repository files navigation

Bird tracking map 🦅

An interactive web map showing the migration paths of some GPS-tracked birds between Northern/Eastern Europe and Africa.

Screenshot of the application

Demo: https://bbecquet.github.io/bird-tracking/

Here is a blog post describing why and how I created this project.

Installing and running

Requirement: Node 18+.

npm install

then, to start a local dev server instance:

npm run dev

To build a standalone version:

npm run build

It will create a build directory with all files ready to be hosted anywhere. As everything happens on the client, it doesn't require any app server, just a plain old HTTP server.

⚠️ Please note that the data file (birds.geojson) is very large (~15 Mb) and needs to be downloaded by the client when the app starts. This means this server-less architecture will not scale well if you want to work with much larger data sets.

Tech overview

Technically, this app is mostly a Deck.gl view, using a MapLibre GL JS instance as mapping library, itself using a freely available basemap by CARTO. Everything is wrapped in a React web app, as it's a natural environment for Deck.gl and it simplifies the management of UI.

The hard part (drawing and animating so many things) is handled by Deck.gl's TripsLayer. Basically, it's a manager for lines with timestamped coordinates. You give it all the coordinates and times, a current timestamp that you update periodically, and voilà!

Data

Source data is coming from the "GPS tracking of Storks, Cranes and birds of prey, breeding in Northern and Eastern Europe" dataset from the Global Biodiversity Information Facility.

After some manual clean-up and simplification in QGIS, I use a Python script to heavily aggregate and transform raw CSV data into a GeoJSON FeatureCollection that is more fitted for JS manipulation. This script is in the data directory, as well as the latest CSV data I used.

If you want to adapt the app to data formatted differently, you probably won't need this script. You just have to ensure the final GeoJSON format is right. Each GeoJSON Feature in the FeatureCollection should be:

{
    "id": <number>, // id of a single bird 
    "type": "Feature",
    "geometry": {
        "type": "LineString",
        "coordinates": <number[][]> // lng/lat pairs for each coordinate of the path of the bird
    },
    "properties": {
        "times": <number[]>, // timestamps for each coordinate 
        "species": <string> // the bird species, used to split birds into groups with different colors
    }
}

In doubt, look at the content of birds.geojson, it's pretty self-explanatory.

License

MIT.