Hands-On Deck.gl: Large-Scale 3D Geospatial Data Visualization with MapLibre
Want to render tens of thousands of data points on the web while keeping smooth 3D interaction? Deck.gl is a solid choice for geospatial data visualization.
Why Choose Deck.gl?
In web map development, if you are only adding a few markers, traditional tools like Leaflet or Mapbox are more than enough. But when you need to render hundreds of thousands or even millions of data points, plus a 3D view, smooth zooming, and animation, performance often becomes the biggest bottleneck.
Deck.gl is an open-source WebGL data visualization framework from Uber. It is designed for large-scale datasets and works smoothly with Mapbox GL JS or MapLibre GL, letting you render 3D scatter points, routes, polygons, and even hexagon heatmaps with very strong performance. It is not tied to a specific map library, performs very well, and supports highly customizable shaders.
Implementation Demo (Live Demo)
Below is a Taiwan attractions 3D interactive map I built with Vue 3, Deck.gl, and MapLibre. It implements smooth camera transitions and data rendering:
Try it online: If you are interested in this implementation, you can click here to visit the Live Demo and try the actual 3D interaction.
How Do You Use It in Your Project?
1. Install Packages
You can use npm or pnpm to install Deck.gl and MapLibre as the basemap:
npm install @deck.gl/core @deck.gl/layers maplibre-gl
2. Core Code Implementation
In Vue 3 or Nuxt 3, we need to make sure the code runs on the client side, because it uses the Canvas API and WebGL. Here is a basic 3D scatterplot configuration:
<script setup>
import { onMounted } from 'vue'
import { Deck } from '@deck.gl/core'
import { ScatterplotLayer } from '@deck.gl/layers'
import maplibregl from 'maplibre-gl'
import 'maplibre-gl/dist/maplibre-gl.css'
onMounted(() => {
// 1. Initialize the basemap (MapLibre)
const map = new maplibregl.Map({
container: 'map-container',
style: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
center: [121.5654, 25.0330], // Taipei 101
zoom: 11,
pitch: 45,
})
// 2. Prepare data and the Deck.gl layer
const layer = new ScatterplotLayer({
id: 'scatterplot-layer',
data: [
{ position: [121.5654, 25.0330], size: 100 }
],
getPosition: d => d.position,
getFillColor: [255, 140, 0],
getRadius: d => d.size,
radiusMinPixels: 5,
radiusMaxPixels: 50
})
// 3. Initialize Deck.gl and sync the view with the basemap
new Deck({
canvas: 'deck-canvas',
initialViewState: {
longitude: 121.5654,
latitude: 25.0330,
zoom: 11,
pitch: 45,
bearing: 0
},
controller: true,
onViewStateChange: ({ viewState }) => {
// Sync the map view
map.jumpTo({
center: [viewState.longitude, viewState.latitude],
zoom: viewState.zoom,
bearing: viewState.bearing,
pitch: viewState.pitch
})
},
layers: [layer]
})
})
</script>
<template>
<div style="position: relative; width: 100%; height: 600px;">
<!-- Basemap container -->
<div id="map-container" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>
<!-- Deck.gl canvas -->
<canvas id="deck-canvas" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;"></canvas>
</div>
</template>
Core Layers
Deck.gl provides a rich set of built-in layers for adjusting how map data is displayed:
| Layer Name | Use Case | Visual Effect |
|---|---|---|
ScatterplotLayer | Point data distribution | 2D circles, with radius and color adjustable based on data |
PathLayer | Routes and tracks | Draws polylines with width, suitable for route planning |
PolygonLayer | Administrative areas, buildings | Can extrude polygon data into 3D column-like shapes |
HexagonLayer | Heatmaps for dense data | Aggregates massive point datasets into 3D hexagonal columns |
GeoJsonLayer | General GeoJSON rendering | A composite layer that combines points, lines, and polygons |
Personal Notes
While developing interactive maps with Deck.gl, the thing that stood out most to me was how well it handles large volumes of data.
If you only want to add a few map markers to your project, a regular map library is enough. But if, like me, you want to draw 3D geospatial information with a strong technical and professional feel, while still keeping the frame rate smooth, Deck.gl offers very good value. It takes a bit of time to learn how to sync the camera cleanly with the basemap, but once you understand the core ideas, a few dozen lines of code can render a very polished visual result.
Small suggestion: Deck.gl usually works best with Mapbox, but to avoid Mapbox’s high costs and token limits, I strongly recommend using the fully open-source MapLibre GL JS as the basemap alternative.
Related Links:
Some of the lower-level integration logic in this article references the official Deck.gl documentation, with component-based wrapping adapted for a Vue 3 environment.

