DEV Community

Cover image for From Photo Metadata to 3D Map: Building an Interactive Travel Diary
Ramiro Gómez
Ramiro Gómez

Posted on • Originally published at geeksta.net on

From Photo Metadata to 3D Map: Building an Interactive Travel Diary

During a recent two-week vacation in Nerja, Spain, I took hundreds of photos with my phone. Many of them captured GPS coordinates and altitude data. Instead of letting that metadata sit unused, I decided to build an interactive 3D visualization that plots each photo on the actual terrain where it was taken.

Quick demo of the interactive viewer

The Concept

The idea was simple: create a chronological journey through my vacation photos, where each photo appears on a 3D terrain map at its location. As you navigate through the photos, the camera flies to each spot, showing the landscape in 3D.

Tech Stack

deck.gl for 3D Visualization

I chose deck.gl for rendering the 3D terrain and photo markers. It's a WebGL-powered framework that handles complex 3D visualizations with impressive performance. Two key layers made this possible:

TerrainLayer - Renders the 3D elevation map using Terrarium-format tiles from AWS:

const terrain = new TerrainLayer({
    id: 'terrain',
    elevationData: 'https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png',
    texture: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    ...
});

Enter fullscreen mode Exit fullscreen mode

ScatterplotLayer - Displays photo locations as 3D points on the terrain. I used two layers: one for visited photos (gray, smaller) and one for the current photo (orange, larger).

Data Processing

The photos' EXIF data provided latitude, longitude, altitude, and timestamps. I extracted this into a CSV file with entries sorted chronologically:

filestem,latitude,longitude,altitude,timestamp
IMG_20260106_132810881,36.78705,-3.883663888888889,197.6,2026:01:06 13:28:12
...

Enter fullscreen mode Exit fullscreen mode

Key Features

Smooth Camera Transitions

When navigating between photos, the camera smoothly flies to the new location using deck.gl's FlyToInterpolator:

deckInstance.setProps({
    initialViewState: {
        longitude: currentPhoto.longitude,
        latitude: currentPhoto.latitude,
        zoom: 15,
        bearing: 180,
        pitch: 40,
        transitionDuration: 2000,
        transitionInterpolator: new deck.FlyToInterpolator()
    }
});

Enter fullscreen mode Exit fullscreen mode

Progressive Trail Visualization

As you move through the photos, previously visited locations remain visible in gray, creating a visual trail of your journey. The current photo is highlighted in orange.

Responsive Layout

The interface adapts to different screen sizes:

  • Landscape: Map takes 60-70% of width, photo/controls on the right
  • Portrait: Map takes 60% of height, photo/controls below
@media (max-aspect-ratio: 1/1) {
    #app-container {
        flex-direction: column;
    }
    #map-container {
        flex: 0 0 60%;
    }
    ...
}

Enter fullscreen mode Exit fullscreen mode

Keyboard Navigation

Keyboard shortcuts for quick navigation:

  • Arrow keys: Previous/Next photo
  • Home/End: First/Last photo
  • Spacebar: Play/Pause auto-advance

Auto-Play Journey

A play button advances through photos automatically (3 seconds each), creating a cinematic journey through the vacation.

Challenges & Solutions

GPS Altitude Accuracy

Phone GPS altitude data can be unreliable, especially near sea level. I added a note in the info modal about this limitation. In future versions, I might cross-reference with the terrain elevation data to improve accuracy.

Photo Loading Performance

I selected 300 of the photos that had GPS data and created smaller web-optimized versions using wim to ensure quick loading without sacrificing too much quality.

Mobile Layout

Getting the controls to fit on small portrait screens required careful tweaking of photo max-height and padding values. The final solution uses a compact info display (icons instead of labels) and reduced button spacing.

What I Learned

  1. deck.gl is powerful but has a learning curve - The layer system is elegant once you understand it, but proper coordinate handling and view state management took some experimentation.
  2. GPS metadata opens creative possibilities - This project barely scratches the surface of what's possible with GPS metadata from photos.
  3. Responsive 3D is tricky - Balancing the 3D visualization with UI controls across different screen sizes required more iteration than expected.
  4. Small touches matter - The smooth camera transitions, progressive trail effect, and keyboard shortcuts help make the experience more engaging.

Try It Yourself

View the live project →

The project is built with vanilla JavaScript and deck.gl - no frameworks needed. If you have GPS-tagged photos from a trip, you could adapt this code to create your own elevation diary.

Have you built something similar or have ideas for improvements? Drop a comment below!


Tech Used:


Thank you for reading!

This article was written by Ramiro Gómez using open source software and the assistance of AI tools. While I strive to ensure accurate information, please verify any details independently before taking action. For more articles, visit the Geeklog on geeksta.net.

Top comments (0)