Deck.gl 大規模 3D 地理數據視覺化框架與 MapLibre 整合實戰
想要在網頁上渲染數以萬計的數據點,同時保持流暢的 3D 互動?Deck.gl 是處理地理空間資料視覺化的絕佳利器。
為什麼選擇 Deck.gl?
在網頁地圖開發中,如果只是加上幾個標記,傳統的 Leaflet 或 Mapbox 已經綽綽有餘。但當你需要渲染數十萬甚至數百萬個數據點,並且需要 3D 視角、流暢的縮放與動畫時,效能往往會成為最大的瓶頸。
Deck.gl 是由 Uber 開源的 WebGL 數據視覺化框架。它專為大規模數據集設計,能夠輕鬆與 Mapbox GL JS 或 MapLibre GL 結合,讓你以極高的效能渲染 3D 散點、路線、多邊形甚至是六邊形熱力圖。它不依賴特定的地圖庫,效能極佳,且支援高度自定義的 Shader。
實作展示 (Live Demo)
下面是我使用 Vue 3 結合 Deck.gl 與 MapLibre 製作的台灣景點 3D 互動地圖,實現了平滑的視角切換與資料渲染:
線上體驗:如果你對這個實作感興趣,可以點擊這裡前往 Live Demo 體驗實際的 3D 互動效果。
如何在你的專案中使用?
1. 安裝套件
你可以使用 npm 或 pnpm 安裝 Deck.gl 以及作為底圖的 MapLibre:
npm install @deck.gl/core @deck.gl/layers maplibre-gl
2. 核心代碼實作
在 Vue 3 或 Nuxt 3 中,我們需要確保程式碼在客戶端執行(因為涉及 Canvas API 與 WebGL)。這裡展示一個基礎的 3D 散點圖配置:
<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. 初始化底圖 (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], // 台北 101
zoom: 11,
pitch: 45,
})
// 2. 準備數據與 Deck.gl 圖層
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. 初始化 Deck.gl 並與底圖同步視角
new Deck({
canvas: 'deck-canvas',
initialViewState: {
longitude: 121.5654,
latitude: 25.0330,
zoom: 11,
pitch: 45,
bearing: 0
},
controller: true,
onViewStateChange: ({ viewState }) => {
// 同步地圖視角
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;">
<!-- 底圖容器 -->
<div id="map-container" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>
<!-- Deck.gl 畫布 -->
<canvas id="deck-canvas" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;"></canvas>
</div>
</template>
核心圖層 (Layers) 說明
Deck.gl 提供了豐富的內建圖層讓你調整地圖資料的外觀:
| 圖層名稱 | 適用場景 | 視覺效果 |
|---|---|---|
ScatterplotLayer | 點狀數據分佈 | 2D 圓點,可依據數據調整半徑與顏色 |
PathLayer | 路線與軌跡 | 繪製有粗細的折線,適合路線規劃 |
PolygonLayer | 行政區劃、建築物 | 可將多邊形數據擠壓成 3D 柱狀體 (Extruded) |
HexagonLayer | 密集數據的熱力圖 | 將海量點數據聚合為 3D 六邊形柱體 |
GeoJsonLayer | 通用 GeoJSON 渲染 | 結合了點、線、面的複合式圖層 |
個人心得
在使用 Deck.gl 開發互動地圖時,最大的感受是它對於海量數據的處理能力真的無可挑剔。
如果你只是想為你的專案加入幾個地圖標記,使用一般的地圖庫就足夠了。但如果像我一樣,想要在地圖上繪製具有強烈「科技感」與「專業感」的 3D 地理資訊,同時又不能犧牲畫面幀數,Deck.gl 的 CP 值真的非常高。雖然學習如何與底圖完美同步視角需要一點時間,但只要掌握了核心概念,幾十行程式碼就能渲染出驚艷的視覺效果。
小建議:Deck.gl 通常與 Mapbox 配合得最好,但為了避免 Mapbox 的高額收費與 token 限制,強烈建議使用完全開源的 MapLibre GL JS 作為底圖替代方案!
相關連結:
本文部分底層整合邏輯參考自 Deck.gl 官方文件,並針對 Vue 3 環境進行組件化封裝。