在 deck.gl 中以纯 JavaScript 方式无 React、无底图构建地图可视化应用
2026/9/15 15:21:07 网站建设 项目流程

在 deck.gl 中以纯 JavaScript 方式无 React、无底图构建地图可视化应用

【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl

导读

本文基于 deck.gl 仓库中examples/get-started/pure-js/basic示例(见 README.md),讲解如何不引入 React,也不依赖 Mapbox / MapLibre 等任何底图服务,仅用原生 JavaScript 与 Vite 构建一个可交互的 WebGL2 地图可视化应用。读完本文,你将掌握:@deck.gl/core@deck.gl/layers的最小化安装与配置、Deck类的核心用法(视图状态、控制器、事件交互)、GeoJsonLayerArcLayer的组合实战,以及开发/生产两种构建流程的完整命令。

为什么需要"无 React、无底图"的纯 JS 方案

deck.gl 的核心库与各层(layers)对 React、Mapbox GL、MapLibre GL没有任何强制依赖,可以被任意 JavaScript 应用直接使用(参见 docs/get-started/using-standalone.md)。这对很多场景非常关键:

  • 轻量接入:只想在现有页面里叠加一层地理数据可视化,不必引入整个 React 运行时;
  • 自由组合底图:可以自行渲染底图(例如用其他瓦片库、离线数据或 GeoJSON 绘制的世界地图),或干脆不要底图;
  • 作为学习起点Deck类一次调用即可创建画布、管理视图状态并处理事件,是理解 deck.gl 渲染管线(GPU 渲染、数据管理、交互)的最短路径。

examples/get-started/pure-js/basic就是这样的最小化起点:它用GeoJsonLayer把世界行政边界(Natural Earth 数据)当作"底图"渲染,再叠加机场点与航线弧线,全程零 React、零地图 Token。

项目结构与依赖清单

该示例目录下只有 4 个文件:

文件作用
examples/get-started/pure-js/basic/package.json声明依赖与 npm 脚本
examples/get-started/pure-js/basic/index.html页面入口,加载 ES Module 脚本
examples/get-started/pure-js/basic/app.js应用逻辑:创建 Deck、定义图层
examples/get-started/pure-js/basic/README.md使用说明

查看 package.json 可以看到其依赖非常精简:

{ "name": "deckgl-example-pure-js-basic", "version": "0.0.0", "private": true, "license": "MIT", "scripts": { "start": "vite --open", "start-local": "vite --config ../../../vite.config.local.mjs", "build": "vite build" }, "dependencies": { "@deck.gl/core": "^9.0.0", "@deck.gl/layers": "^9.0.0" }, "devDependencies": { "vite": "^7.3.3" } }

关键点:

  • @deck.gl/core:核心模块,负责 GPU 渲染管线、数据管理与用户交互,导出Deck类(其文档见 docs/api-reference/core/deck.md);
  • @deck.gl/layers:基础图层集合,本示例用到其中的GeoJsonLayerArcLayer
  • vite:负责打包与本地开发服务器,是"零配置"背后的支撑。

如果项目从零开始,也可参照 docs/get-started/getting-started.md 安装全家桶npm install deck.gl --save,或按需单独安装子模块(本示例即采用后者,以获得最小依赖树)。注意:子模块版本需要手动保持同步,才能保证结果一致。

安装与运行:三条命令快速跑起来

1. 安装依赖

在示例目录下执行:

npm install # 或 yarn

2. 启动开发服务器

npm start

该命令对应vite --open:启动开发服务器并在浏览器中自动打开页面,支持热更新(HMR),改完代码立即生效。

3. 构建生产包

npm run build

该命令对应vite build:生成最终 bundle 并写入磁盘(默认输出到dist/),可直接部署到静态服务器。

补充:直接基于仓库源码运行

如果想用仓库里最新的 deck.gl 源码(而非package.json中锁定的已发布版本)运行示例,可执行:

npm run start-local

该命令会使用仓库根目录下的 vite.config.local.mjs 配置。使用前提是先在 deck.gl 仓库根目录执行过npm install,否则本地源码依赖无法解析(详见 docs/get-started/getting-started.md 中的说明)。

该示例不需要 Mapbox Token,因为根本不加载任何商业底图服务;如果切换到其他使用 mapbox 底图的示例,则需要设置MapboxAccessToken环境变量。

页面骨架:一个全屏画布就够

index.html 是整个应用的"壳",极其简洁:

<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>deck.gl Example</title> <style> body {margin: 0; width: 100vw; height: 100vh; overflow: hidden;} </style> </head> <body> </body> <script type="module" src="app.js"></script> </html>

三个要点:

  • <script type="module">:以原生 ES Module 方式加载app.js,由 Vite 负责后续的依赖解析与打包,无需任何框架;
  • body 全屏样式margin: 0+100vw/100vh+overflow: hidden,确保Deck自动创建的 canvas 铺满视口且不出现滚动条;
  • 无任何 DOM 容器Deck默认会把自动创建的 canvas 挂到document.body(对应Deckparent属性默认值),因此<body>可以是空的。

核心逻辑:用 Deck 类搭建可视化

app.js 是整个示例的灵魂,共分三步:导入、定义视图状态、创建图层并实例化Deck

1. 导入

import {Deck} from '@deck.gl/core'; import {GeoJsonLayer, ArcLayer} from '@deck.gl/layers';

只引入Deck与两个图层类,这就是"无 React"的直接体现——没有 JSX、没有组件生命周期,只有类与实例。

2. 准备数据与初始视图状态

const COUNTRIES = 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_50m_admin_0_scale_rank.geojson'; const AIR_PORTS = 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson'; const INITIAL_VIEW_STATE = { latitude: 51.47, longitude: 0.45, zoom: 4, bearing: 0, pitch: 30 };
  • 数据源:图层data属性直接传入远程 GeoJSON URL,deck.gl 会自动异步加载(加载管理是@deck.gl/core数据管线的一部分);
  • INITIAL_VIEW_STATE:初始视角定位在英国上空(经度 0.45、纬度 51.47),缩放级别 4,pitch: 30让视图产生轻微 3D 透视效果,bearing为航向角(0 表示正北朝上)。

3. 实例化 Deck 并叠加三个图层

new Deck({ initialViewState: INITIAL_VIEW_STATE, controller: true, layers: [ /* 三个图层实例 */ ] });

Deck类接收图层实例与视口参数,将它们渲染为一个透明覆盖层并处理事件(参见 docs/api-reference/core/deck.md)。核心配置项:

配置项作用本示例取值
initialViewState初始相机视角(经纬度、缩放、俯仰、航向)上文对象
controller是否启用地图控制器(拖拽平移、滚轮缩放、右键旋转等交互)true
layers要渲染的图层数组GeoJsonLayer × 2 + ArcLayer

controller: true自动接入 MapController,用户即可在浏览器里自由漫游整个世界地图,无需编写任何事件监听代码。

图层详解:GeoJsonLayer 与 ArcLayer 的组合实战

图层一:用 GeoJsonLayer 渲染世界"底图"

new GeoJsonLayer({ id: 'base-map', data: COUNTRIES, stroked: true, filled: true, lineWidthMinPixels: 2, opacity: 0.4, getLineColor: [60, 60, 60], getFillColor: [200, 200, 200] })

这个图层把世界行政边界当底图用:

  • stroked: true描边 +filled: true填充,lineWidthMinPixels: 2保证缩放时边界线至少 2 像素粗(避免线过细不可见);
  • opacity: 0.4半透明填充,让下层内容(如有)透出;
  • getLineColor/getFillColor返回 RGB 颜色数组,分别控制边界线与填充色。

图层二:用 GeoJsonLayer 渲染机场点并支持点击

new GeoJsonLayer({ id: 'airports', data: AIR_PORTS, filled: true, pointRadiusMinPixels: 2, pointRadiusScale: 2000, getPointRadius: f => 11 - f.properties.scalerank, getFillColor: [200, 0, 80, 180], pickable: true, autoHighlight: true, onClick: info => info.object && alert(`${info.object.properties.name} (${info.object.properties.abbrev})`) })

同一个GeoJsonLayer类,只要数据是点要素(Point/MultiPoint),就可以用点相关样式属性渲染:

  • 点样式pointRadiusScale: 2000pointRadiusMinPixels: 2组合——半径按经纬度比例缩放但保底 2 像素;getPointRadius用访问器函数按机场scalerank(规模等级)动态计算半径,等级越高(值越小)圆越大;
  • 交互三件套pickable: true开启拾取、autoHighlight: true鼠标悬停自动高亮该要素、onClick回调读取被点击要素的属性(这里是弹出机场名称与缩写)——这正是"无 React"也能获得完整交互体验的证明。

图层三:用 ArcLayer 绘制航线弧线

new ArcLayer({ id: 'arcs', data: AIR_PORTS, dataTransform: d => d.features.filter(f => f.properties.scalerank < 4), getSourcePosition: f => [-0.4531566, 51.4709959], // London getTargetPosition: f => f.geometry.coordinates, getSourceColor: [0, 128, 200], getTargetColor: [200, 0, 80], getWidth: 1 })
  • dataTransform:在渲染前对原始 GeoJSON 做一次数据变换——只保留scalerank < 4的大型机场,避免弧线过多、画面过乱。这是 deck.gl 数据管线的实用技巧,可在数据进入图层前做过滤/映射/聚合;
  • getSourcePosition/getTargetPosition:所有弧线起点固定在伦敦坐标,终点指向各机场坐标,形成以伦敦为中心的"辐射航线图";
  • 颜色渐变getSourceColor起点蓝、getTargetColor终点红,ArcLayer 会自动做起点到终点的颜色插值;
  • getWidth:弧线宽度 1 像素,保持整体画面轻盈。

三个图层按数组顺序由下至上叠加:世界地图 → 机场点 → 航线弧线,共同构成一个信息层次清晰的可视化。

从源码看设计:Deck 与图层的职责边界

结合仓库源码结构可以进一步理解这套架构的设计意图:

  • Deck@deck.gl/core:核心渲染引擎。它负责创建 GPU 设备与画布、管理视图状态与动画循环、处理拾取与事件分发,并对图层做 diff 更新。源码位于 modules/core/src,其公共 API 文档见 docs/api-reference/core/deck.md(其中initialViewStatecontrollerlayersonClickpickable等属性都有详细说明);
  • GeoJsonLayer@deck.gl/layers:复合图层,内部按要素几何类型分别委托给ScatterplotLayer(点)、PathLayer(线)、SolidPolygonLayer(面)等基础图层渲染,因此一个图层即可统一处理点、线、面混合数据;其 API 文档见 docs/api-reference/layers/geojson-layer.md;
  • ArcLayer@deck.gl/layers:独立基础图层,专用于两点间弧线,支持颜色渐变与宽度控制,文档见 docs/api-reference/layers/arc-layer.md。

从代码结构可以推断:开发者只需"声明图层 + 声明数据 + 声明样式",渲染细节(着色器、缓冲区、属性更新)全部由框架接管——这正是 deck.gl 区别于手写 WebGL 的核心价值。测试侧,仓库 test/modules 与 test/render 目录提供了对图层渲染结果与交互行为的验证,可作为深入阅读的入口。

把它改造成自己的应用:三步上手

  1. 换数据:把COUNTRIES/AIR_PORTS换成你自己的 GeoJSON URL 或本地数组。deck.gl 的data属性同时接受 URL、数组、Promise与任意可迭代对象;
  2. 调样式:按上文表格调整getFillColorgetLineColorgetPointRadiusgetWidth等访问器,颜色统一使用[r, g, b][r, g, b, a]数组;
  3. 加交互:给任意图层加上pickable: trueautoHighlight: trueonClick/onHover回调,即可实现拾取与事件响应。

当项目规模变大、需要更复杂的 UI 时,再考虑引入 docs/api-reference/react/deckgl.md(React 封装)或 @deck.gl/widgets 组件;但在起步阶段,"纯 JS + Deck" 是理解 deck.gl 心智模型的最佳路径。

常见问题与排查

  • 页面空白:确认index.htmlbody样式为全屏(100vw/100vh)且未设置会遮挡 canvas 的定位元素;Deck自动创建的画布 id 默认为deckgl-overlay,可通过 CSS 检查其尺寸;
  • 数据加载失败:本示例依赖远程 Natural Earth 数据源,若网络受限会导致图层为空,可把数据下载到本地后改为本地路径;
  • npm run start-local报错:先在 deck.gl 仓库根目录执行npm install,确保本地模块依赖完整,再运行该命令;
  • 想切换底图:本示例用 GeoJSON 自己"画"底图,若需要真实地图服务,可参考同目录下的 examples/get-started/pure-js/mapbox、examples/get-started/pure-js/maplibre 等示例(这些示例才需要底图服务配置)。

小结

examples/get-started/pure-js/basic以最小代价演示了 deck.gl 的核心能力:Deck类一站式完成视图、渲染与交互,GeoJsonLayer统一处理点线面数据,ArcLayer提供生动的弧线表达,Vite 提供开箱即用的开发与构建体验。它既是学习 deck.gl 心智模型的起点,也是无需 React、无需地图 Token 的轻量可视化方案的参考模板。掌握这份骨架后,无论你是要叠加三维建筑、聚合热力还是海量轨迹,都可以在此基础上按需引入 @deck.gl/geo-layers、@deck.gl/aggregation-layers 等模块继续扩展。

【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询