拓冰建站拓冰建站
首页 / 资讯中心 / 正文

deck.gl 与 harp.gl 集成实战:纯 JavaScript 双引擎地图叠加渲染指南

deck.gl 与 harp.gl 集成实战纯 JavaScript 双引擎地图叠加渲染指南【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl本指南围绕 deck.gl 仓库中 examples/get-started/pure-js/harp.gl 示例展开讲解如何将 deck.gl 的 WebGL2 图层系统与 HERE 公司的 harp.gl 矢量地图引擎组合在同一个页面中harp.gl 负责加载矢量瓦片底图deck.gl 以透明叠加层的方式在其上渲染 GeoJson 与 Arc 图层并实现双引擎相机视角的实时同步。读者读完后将掌握完整的工程搭建Webpack 打包、HERE API Key 配置、开发/生产命令、Deck类的核心用法、相机同步的关键实现以及 Harp 解码 Worker 的构建接入方式。示例定位为何把 deck.gl 与 harp.gl 组合在一起deck.gl 的核心能力是数据可视化渲染它不关心底图由谁提供只负责把图层渲染为一张透明覆盖物。而 harp.glhere/harp-mapview、here/harp-omv-datasource负责的是地图底图渲染加载 HERE 的矢量瓦片服务输出柏林风格的tilezen底图。两者天然互补把 harp.gl 的MapView画在底层 canvas 上把 deck.gl 的Deck画在上层 canvas 上再通过回调把 deck.gl 的视图状态经纬度、缩放、俯仰、旋转同步给 harp.gl就能得到一个带真实底图的大规模数据可视化应用而不必依赖 Mapbox GL / MapLibre GL 这类常见底图方案。关联文档与完整实现均位于 examples/get-started/pure-js/harp.gl/官方独立使用说明见 docs/get-started/using-standalone.md核心库与图层不依赖 React 或任何特定底图库。前置条件与 HERE API Key 配置运行本示例需要一个HERE maps API key可在 HERE 开发者平台申请。README 提供了两种注入方式二者等价方式一环境变量推荐export HereApiKeyyour_api_key方式二直接在app.js中硬编码在 examples/get-started/pure-js/harp.gl/app.js 中const API_KEY process.env.HereApiKey; // eslint-disable-line该变量在 Webpack 打包阶段被webpack.EnvironmentPlugin([HereApiKey])注入见下文构建配置章节。若采用方式二将上面一行改为const API_KEY your_api_key;即可。安装依赖与运行命令README 给出的完整命令如下两者任选其一示例的package.json基于 npm 生态npm install # 或 yarn安装完成后有两个目标命令见 package.json 中的scripts字段命令目标说明npm start开发通过webpack-dev-server --progress --hot --open启动本地服务器支持热更新并自动打开浏览器npm run build生产通过webpack -p生成最终 bundle 并写入磁盘package.json声明了四类关键依赖deck.gl 侧deck.gl/coreDeck类、deck.gl/layersGeoJsonLayer、ArcLayer版本为^9.0.0harp.gl 侧here/harp-geoutils、here/harp-mapview、here/harp-omv-datasource、here/harp-datasource-protocol版本为^0.14.0构建工具链here/harp-webpack-utils提供 Harp 专用 Webpack 配置合并函数渲染依赖threeharp.gl 内部基于 three.js 渲染。项目文件结构与运行机制总览examples/get-started/pure-js/harp.gl/ ├── app.js # 应用主逻辑创建 MapView、OmvDataSource、Deck 与图层 ├── decoder.js # Harp 矢量瓦片解码 Worker 入口 ├── index.html # 页面骨架双 canvas 叠放 ├── package.json # 依赖与 npm 脚本 └── webpack.config.js # Webpack 配置合并 Harp 专用配置整体运行流程为index.html提供两个绝对定位、各占 100% 的canvas下层#map-canvasharp.gl 底图、上层#deck-canvasdeck.gl 图层webpack.config.js同时以app.js为主入口、decoder.js为 Worker 入口打包app.js初始化MapView与OmvDataSource加载 HERE 矢量瓦片再初始化Deck渲染机场点与弧线数据deck.gl 每次视图变化时通过onViewStateChange回调调用updateMapCamera把相机参数同步给 harp.gl实现同屏同视角。app.js 源码拆解双引擎集成的核心1. 初始化 deck.gl 图层数据import {Deck} from deck.gl/core; import {GeoJsonLayer, ArcLayer} from deck.gl/layers; import {GeoCoordinates} from here/harp-geoutils; import {MapView, MapViewUtils} from here/harp-mapview; import {APIFormat, AuthenticationMethod, OmvDataSource} from here/harp-omv-datasource;数据源采用 Natural Earth 的全球机场点集约 10 米比例尺数据经 geojson.xyz 分发const AIR_PORTS https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson;初始视角INITIAL_VIEW_STATE对准伦敦上空latitude: 51.47, longitude: 0.45, zoom: 4, pitch: 30同时被 harp.gl 的MapView与 deck.gl 的Deck共用。2. 相机同步函数 updateMapCamerafunction updateMapCamera(mapView, viewState) { const coords new GeoCoordinates(viewState.latitude, viewState.longitude); const dist MapViewUtils.calculateDistanceFromZoomLevel( {focalLength: mapView.focalLength}, viewState.zoom 1 ); mapView.lookAt(coords, dist, viewState.pitch, viewState.bearing); mapView.zoomLevel viewState.zoom 1; }这是双引擎同步的关键deck.gl 使用 Web Mercator 投影下的zoom概念而 harp.gl 的MapView使用lookAt(经纬度坐标, 相机距离, 俯仰角, 方位角)的相机模型。二者通过MapViewUtils.calculateDistanceFromZoomLevelhere/harp-geoutils提供把 zoom 层级换算成相机到目标的距离再用lookAt施加 pitch 与 bearing。注意代码中对 zoom 做了1偏移用于补偿两套引擎缩放基准的差异。3. 创建 harp.gl 底图 MapView 与 OmvDataSourceconst map new MapView({ canvas: document.getElementById(map-canvas), theme: https://unpkg.com/here/harp-map-themelatest/resources/berlin_tilezen_night_reduced.json, // Match deck.gls FOV Math.atan(1/3) * 2 / Math.PI * 180 fovCalculation: {fov: 36.87, type: fixed} });theme使用 unpkg 上的柏林夜间精简主题berlin_tilezen_night_reduced.jsonfovCalculation: {fov: 36.87, type: fixed}是对齐两套引擎视野的关键deck.gl 默认相机 FOV 为Math.atan(1/3) * 2 / Math.PI * 180 ≈ 36.87°这里把 harp.gl 的 FOV 固定为同一数值保证上下两层画面透视完全一致否则同步后会出现前景对不上的视觉错位。矢量瓦片数据源通过OmvDataSource接入const omvDataSource new OmvDataSource({ baseUrl: https://vector.hereapi.com/v2/vectortiles/base/mc, apiFormat: APIFormat.XYZOMV, styleSetName: tilezen, authenticationCode: API_KEY, authenticationMethod: { method: AuthenticationMethod.QueryString, name: apikey } }); map.addDataSource(omvDataSource);authenticationCode即前面配置的 API KeyauthenticationMethod指定以 URL 查询字符串?apikey...的方式携带凭证。创建后通过map.addDataSource(omvDataSource)挂载到地图上。4. 创建 deck.gl Deck 实例并双向同步export const deck new Deck({ canvas: deck-canvas, width: 100%, height: 100%, initialViewState: INITIAL_VIEW_STATE, controller: true, onViewStateChange: ({viewState}) updateMapCamera(map, viewState), onResize: ({width, height}) map.resize(width, height), layers: [ /* GeoJsonLayer ArcLayer */ ] });对照 docs/api-reference/core/deck.md 中对Deck类的定义Deck接收图层实例与视口参数把图层渲染为一张透明覆盖层并负责事件处理。关键配置说明canvas: deck-canvas渲染目标为 id 为deck-canvas的 canvas也支持直接传入HTMLCanvasElementwidth/height默认即100%这里显式声明使 deck.gl 覆盖整个容器initialViewStatecontroller: true让 deck.gl 自带交互控制器拖拽、缩放、旋转并自动维护视图状态onViewStateChangedeck.gl 视角变化含用户交互与动画时触发回调签名见 deck.md 的 onViewStateChange 一节此处解构出viewState后转交给updateMapCamera实现deck.gl 动 → harp.gl 跟着动onResize画布尺寸变化时同步调用map.resize保证底图与覆盖层尺寸始终一致。5. 图层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})) })要点数据直接传 GeoJSON URLdeck.gl 会异步加载并解析getPointRadius: f 11 - f.properties.scalerank按机场的scalerank等级动态计算半径等级越高数值越小点越大pointRadiusMinPixels: 2限制最小屏幕像素pointRadiusScale: 2000控制半径放大系数pickable: true开启拾取autoHighlight: true悬停自动高亮onClick在拾取到对象时弹出机场名称与缩写演示了底图之上的交互式数据层。6. 图层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在数据进入图层前做预处理只保留scalerank 4的枢纽机场减少弧线数量getSourcePosition固定为伦敦坐标getTargetPosition取每个机场的经纬度形成伦敦辐射全球的弧线网络起点蓝色[0, 128, 200]、终点洋红色[200, 0, 80]渐变弧线直观表达连接关系。decoder.jsHarp 瓦片解码 Workerimport {OmvTileDecoderService, OmvTilerService} from here/harp-omv-datasource/index-worker; OmvTileDecoderService.start(); OmvTilerService.start();harp.gl 的矢量瓦片OMV 格式解码与切片计算是 CPU 密集型工作因此被放到 Web Worker 中执行。decoder.js 就是该 Worker 的入口启动OmvTileDecoderService解码瓦片与OmvTilerService瓦片网格计算。它与app.js共同构成了 Harp 典型的双入口结构由 Webpack 分别打出主线程 bundle 与 Worker bundle。webpack.config.js如何把 Harp 配置并入构建const webpack require(webpack); const {addHarpWebpackConfig} require(here/harp-webpack-utils/scripts/HarpWebpackConfig); let config { mode: development, entry: {app: ./app.js}, plugins: [new webpack.EnvironmentPlugin([HereApiKey])] }; config addHarpWebpackConfig(config, { mainEntry: ./app.js, decoderEntry: ./decoder.js, htmlTemplate: ./index.html }); module.exports config;要点webpack.EnvironmentPlugin([HereApiKey])把环境变量HereApiKey在编译期替换进代码这就是process.env.HereApiKey在浏览器端可用的原因addHarpWebpackConfig来自here/harp-webpack-utils它会自动为项目补充 Harp 运行所需的 worker-loader 规则、worker 入口以及 HTML 模板处理把decoder.js打成独立 Worker bundle文件末尾注释说明若把该配置复制到仓库之外独立使用需要删除文件底部针对仓库内源码的本地开发覆盖配置本例中module.exports config之上的逻辑即为仓库内开发时的特殊处理。index.html双 Canvas 叠放布局div idcontainer canvas idmap-canvas/canvas canvas iddeck-canvas/canvas /div#container使用position: fixed铺满视口其内部所有子元素position: absolute且各占 100% 宽高。这种下层底图 上层覆盖层的叠放方式与 deck.gl 集成 Mapbox GL / MapLibre GL 时的思路一致只是把底图引擎换成了 harp.gl。deck.gl 的 canvas 默认背景透明因此上层图层可以无遮挡地叠加在底图之上。深入原理Deck 透明覆盖层与事件流从源码结构看本示例把 deck.gl 当作独立于任何底图引擎的渲染器使用Deck类modules/core/src负责管理 luma.gl 设备、视口、控制器与图层生命周期不感知底层地图存在集成方只需通过onViewStateChange把 deck.gl 的视图状态翻译成目标引擎的相机参数再通过onResize保持尺寸同步。这种视图状态单向驱动的同步模式有两个值得注意的实践点由 deck.gl 主导交互controller: true使 deck.gl 拦截所有用户手势并更新自己的 viewState随后回调同步给 harp.gl。这样可避免两套引擎各自处理手势导致的冲突交互一致性由 deck.gl 统一保证FOV 与 zoom 基准对齐示例用fovCalculation: {fov: 36.87, type: fixed}固定 harp.gl 视野并在updateMapCamera中对 zoom 做1偏移。集成其他引擎时也需要做类似的投影/缩放模型换算否则上下层画面会在缩放与俯仰时错位。扩展与注意事项API Key 安全示例将 Key 注入前端 bundle仅适用于开发与演示。生产环境建议通过自有服务端代理转发瓦片请求避免凭证暴露数据替换AIR_PORTS与两个图层的访问器accessor完全解耦把数据换成任意 GeoJSON如全球航线、城市点集即可复用到你自己的可视化更多图层组合deck.gl 的deck.gl/layers、deck.gl/geo-layers、deck.gl/aggregation-layers中的图层均可按同样方式叠加到 harp.gl 底图上适合迁移其他 Mapbox/MapLibre 示例到 harp.gl 场景版本匹配示例依赖 harp.gl^0.14.0与 deck.gl^9.0.0升级任一引擎版本时需重新验证updateMapCamera的距离换算与 FOV 对齐逻辑。参考文件索引关联文档与使用说明examples/get-started/pure-js/harp.gl/README.md应用主逻辑examples/get-started/pure-js/harp.gl/app.jsWorker 入口examples/get-started/pure-js/harp.gl/decoder.js页面骨架examples/get-started/pure-js/harp.gl/index.html构建配置examples/get-started/pure-js/harp.gl/webpack.config.js依赖清单examples/get-started/pure-js/harp.gl/package.json独立使用说明docs/get-started/using-standalone.mdDeck类 APIdocs/api-reference/core/deck.md【免费下载链接】deck.glWebGL2 powered visualization framework项目地址: https://gitcode.com/GitHub_Trending/de/deck.gl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门