
GeoLibre 地图共享与嵌入完整指南从分享令牌配置到 iframe 运行时 API【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre本文以 GeoLibre 官方教程为基础系统讲解如何把一张制作完成的地图发布为公共链接.geolibre.json再以iframe的形式嵌入任何网页并进一步通过geolibre/embed类型化客户端在运行时双向驱动地图。读完本文你将掌握分享令牌配置、项目发布、URL 参数定制嵌入外观、只读viewer布局语义以及基于版本化postMessage协议的运行时驱动能力可以直接应用到门户、ERP、仪表盘或报表页面的地图集成中。1. 前置准备一张值得分享的地图分享与嵌入的前提是已经制作好一张地图。教程建议先参考 Your First Map 教程 完成基础制图添加图层layers、配置样式styling并把地图视图map view设定为希望访问者落地看到的视角。Project → Share...分享出去的内容就是当前项目的完整快照因此想让观众第一眼看到什么决定了分享前需要调整的视图状态。如果想在分享前微调界面呈现哪些控件例如隐藏某些按钮、调整控件顺序可以查阅 Controls 菜单说明。界面细节对嵌入场景尤其重要因为 iframe 内的地图会原样继承这些设置。2. 第一步配置分享令牌Share TokenGeoLibre 的项目分享功能会把项目文件上传到share.geolibre.app上传过程使用个人 API 令牌personal API token鉴权。配置只需一次步骤如下打开Settings → Environment Variables设置 → 环境变量在Share.GeoLibre API token字段中粘贴你的令牌令牌可在 share.geolibre.app/settings 的Settings → API tokens下创建。配置一次后后续所有分享操作都会复用该令牌无需重复填写。从部署角度看分享服务的地址本身也是可配置的。Docker 镜像通过GEOLIBRE_SHARE_URL环境变量指定自建分享服务地址设置off则会从界面中完全移除 Share 与 Project Gallery 入口。具体逻辑见 docker/entrypoint.sh 中service_url对分享地址的校验与发布流程。3. 第二步分享项目Project → Share...完成制图并确认视图后执行打开Project → Share...项目 → 分享确认项目标题project title无误点击上传。GeoLibre 会返回一个指向.geolibre.json文件的公共 URL例如https://share.geolibre.app/you/my-map.geolibre.json分享文件包含什么分享出去的文件与本地保存的项目文件等价图层、样式、插件状态plugin state以及地图视图都会完整捕获。这意味着观众打开链接后看到的地图与你在本地保存时完全一致包括图层开关状态、样式设置和相机视角。例外读取本地文件的数据图层唯一例外是读取你电脑本地文件的数据图层。share.geolibre.app只存储项目文件本身永远不会上传你的数据文件。因此在分享前对话框会把这些图层列为缺失missing提示你处理。处理方式是把本地数据托管到公网可访问的位置再让图层指向远程 URL。具体操作参考 projects.md 中的 Sharing local data 章节。简单来说凡是依赖本机文件路径的图层本地 GeoJSON、MBTiles、栅格文件等在分享场景下都必须替换为可公开访问的远程数据源。4. 第三步在在线查看器中打开共享地图分享得到的.geolibre.jsonURL 可以通过url参数直接交给在线查看器打开https://web.geolibre.app/?urlhttps://share.geolibre.app/you/my-map.geolibre.json任何人拿到这个链接都可以在浏览器中直接查看共享地图无需安装任何软件、无需登录账号。在线查看器Live Viewer的运行模式理解查看器的工作方式有助于判断分享/嵌入方案的适用边界。浏览器构建版本托管在https://web.geolibre.app/是一个部署在 GitHub Pages 上的纯静态站点全部在浏览器端运行没有服务器账号体系你加载的数据全部在客户端处理数据流出原则数据只有在两种情况下离开浏览器——你主动添加远程 URL或你显式分享项目隐私说明托管站点会用 Google Analytics 统计页面访问量但分析脚本看不到你加载的数据详见 Privacy Policy 的 Website Analytics 一节如果你自己托管一份副本则完全没有任何统计代码私有数据注意url与data参数由浏览器以同源凭证same-origin credentials方式请求。因此受会话 Cookie 保护的私有项目或数据集只有在 GeoLibre 与数据源同源时才可能加载成功。把需要登录的 URL 传给web.geolibre.app托管查看器会失败因为跨源请求不会携带 Cookie。此时应当自托管应用或使用带签名、有时效的 URL参考 Self-Hosting Private Data。5. 第四步把地图嵌入网页把共享项目嵌入网页的最直接方式是使用iframe并配合嵌入参数控制界面外壳chrome。一个干净、只显示地图的嵌入示例iframe srchttps://web.geolibre.app/?urlhttps://share.geolibre.app/you/my-map.geolibre.jsonamp;maponly titleGeoLibre map width100% height600 styleborder: 0; loadinglazy allowfullscreen; geolocation /iframe注意src中在 HTML 属性里需要写成amp;避免被解析为实体分隔符。URL 参数总览可任意组合GeoLibre 的浏览器构建完全通过 URL 查询参数配置参数之间可以组合使用。下表整理了完整的参数清单详细定义见 embedding.md 的 URL parameters 章节参数示例说明urlurlhttps://share.geolibre.app/you/project.geolibre.json从公共 URL 加载.geolibre.json项目loadingloadingtrue在html元素上暴露截图就绪信号接受裸标记、true、1、yes、on默认关闭datadatahttps://assets.geolibre.app/data/places.geojson加载公共 GeoJSON、GeoParquet、PMTiles、COG或包含多个 GeoJSON 的 ZIP/REST 响应stylestylehttps://assets.geolibre.app/data/sample.style.json为data加载的数据应用 GeoLibre/MapLibre 矢量样式或栅格样式 JSONlayoutlayoutviewerviewer提供只读外壳compact是仅图标的完整应用布局embed、iframe是别名toolbartoolbarnone隐藏顶部工具栏但保留面板与状态栏icons显示图标按钮icon、icon-only为别名hidden、hide、off是none的别名panelspanelscollapsed让 Layers 和 Style 面板以图标轨icon rail形式折叠none隐藏全部面板hidden、hide、off为别名hidePanelshidePanelstrue隐藏面板的另一种写法maponlymaponly隐藏所有外壳工具栏、面板、状态栏只留地图裸标记或true、1、yes、on均可启用welcomewelcome0隐藏首次启动的欢迎向导接受0、false、off、no带url或data的深链会自动抑制themethemedark设置初始主题色覆盖操作系统偏好接受dark或light之后应用内的切换仍然有效settingsUrlsettingsUrlhttps://example.com/desktop-settings.json首次渲染前加载共享的呈现设置支持language、layout、accenttheme、uiProfile仅对当前页面生效不替换本地设置settingUrl是别名tooltooladaptive_filter打开 ProcessingWhitebox 工具箱对话框并预选指定 id 的工具未知 id 会打开对话框但不预选教程中的核心外观参数针对最常见的调外观需求教程给出了六个关键参数及其使用场景maponly隐藏全部外壳只保留地图。适合把地图当作页面中的一张图figure的场景例如报表配图layoutviewer只读地图布局。Layers、View、Controls、底图切换、搜索/识别等功能保留但所有会编辑项目的功能被隐藏layoutcompact保留一条精简的纯图标工具栏适合需要完整功能但空间受限的场景toolbarnone隐藏顶部工具栏但保留侧边面板与状态栏panelsnone隐藏侧边与底部面板但保留工具栏themedark加载时强制使用深色主题。组合使用示例——一个窄宽度、无外壳、深色的共享项目嵌入https://web.geolibre.app/?urlhttps://share.geolibre.app/you/project.geolibre.jsonmaponlythemedark选型建议当希望读者能切换图层、探索数据但不能修改数据时使用layoutviewer当地图只是页面中的一个插图、不需要交互时使用maponly。layoutviewer的只读语义viewer布局不是简单隐藏几个按钮而是一整套只读保证。参考 embedding.md 的 Embedding in a page 章节 的详细说明图层列表镜像了作者端的 Layers 面板文件夹结构原样保留分组名称会带过去携带快速过滤器quick filters的图层会在其行下方显示过滤器因此观众既能读图也能提问数据Controls 菜单作为查看器外壳的一部分保留但移除两个会写入项目的入口Field Collection 与 GPS TrackingRecord Tour 和 Record Video 只读取地图因此保留键盘快捷键项目级快捷键Ctrl/CmdN、O、S与命令面板Ctrl/CmdK随所属菜单一起消失View 菜单保留因此视图快捷键[、]、n、u、r仍然可用拖放导入把文件拖到地图上不会导入任何数据写项目的插件几何编辑器、Annotations、GeoAgent 等会把内容写入项目的 on-map 控件无法激活——即使加载的项目保存了这些状态也不行。也就是说嵌入页面无法通过按键、拖拽或项目文件把嵌入地图诱导进编辑模式。显示型插件图层控制、底图、时间滑块、图例与色标组件正常工作因此项目外观与保存时一致。深链到 Processing 工具tool 参数toolid会打开 Processing 对话框并预选对应工具额外的查询参数会按工具自身的参数名预填表单让链接到达时即可运行。此时应用处于工具模式url参数表示工具输入而非要加载的项目项目加载器会退避而theme、layout、panels、maponly等嵌入参数保持原有含义绝不会传给工具。https://web.geolibre.app/?toolextract_cog_subseturlhttps%3A%2F%2Fdata.source.coop%2Fgiswqs%2Fopengeos%2Fdem.tifbbox_crs4326工具 id 与 Processing 菜单一致与 Whitebox 工具箱 使用的 id 相同。已知 id 但当前引擎不提供浏览器中是 WASM、桌面端是 Python 侧车时不会预选。等待截图就绪loadingtrue当需要用无头浏览器截图嵌入地图例如 CI 生成封面图loadingtrue可以提供机器可读的就绪信号且不会给截图增加可见覆盖层。启用后html元素暴露三个属性属性值data-geolibre-load-stateloading、ready或errordata-geolibre-load-pending待加载图层名称或初始化工作的 JSON 数组data-geolibre-load-errors失败消息的 JSON 数组ready的含义是项目/数据 URL 已加载、可见图层已挂载、当前视口瓦片已加载、相机已停止、浏览器字体已加载并且这些条件需在动画帧之间持续满足 500ms。改变视图或图层会让信号回到loading。隐藏图层、完全透明图层、超出缩放范围的图层不会阻塞就绪该机制不会下载视口外的数据集或瓦片。就绪探测支持原生 MapLibre 图层、栅格控件的 COG 图层以及 deck.gl 可视化图层Cesium、LiDAR、Zarr、splats、video 等无就绪探针的自定义渲染器会显式报告错误而不是假装就绪。120 秒内未收敛的加载会随超时一并上报。Playwright 中使用示例await page.setViewportSize({ width: 1600, height: 1000 }); await page.goto(projectLink maponlyloadingtrue); await page.waitForFunction( () [ready, error].includes(document.documentElement.dataset.geolibreLoadState), undefined, { timeout: 150_000 }, ); const result await page.evaluate(() ({ state: document.documentElement.dataset.geolibreLoadState, errors: JSON.parse(document.documentElement.dataset.geolibreLoadErrors || []), })); if (result.state ! ready) throw new Error(result.errors.join(; )); await page.screenshot({ path: map.png });注意ready就绪状态既不同于 embed API 的ready事件也不同于浏览器的networkidle状态截图前应以该信号为准。直接打开远程数据data 参数data参数可以打开公共 GeoJSON、GeoParquet、PMTiles、云优化 GeoTIFFCOG或包含多个.geojson/.jsonFeatureCollection 的 ZIP 归档ZIP 中每个 GeoJSON 文件会变成独立图层。可选的styleURL 为矢量数据应用 Mapbox/MapLibre 样式 JSONhttps://web.geolibre.app/?datahttps://assets.geolibre.app/data/places.geojsonstylehttps://assets.geolibre.app/data/sample.style.json重复data可以在同一地图上加载多个独立数据集按相同顺序重复style为每个数据集指定样式用空的style作为占位符让某数据集使用默认样式。data也可以指向返回 GeoJSONFeatureCollection或包含多个 GeoJSON 的 ZIP 的 REST 端点端点自带查询参数时需要对 URL 做百分号编码会被误读为 GeoLibre 自己的参数分隔符。编码规则普通https://URL 可直接传递:和/在查询值中合法无需转义仅当嵌套的 data/style URL 含、、%、#时才需要encodeURIComponent。远程服务器必须允许浏览器跨源请求CORSCOG、GeoParquet、PMTiles 服务器还应支持 HTTP 字节范围请求byte-range。6. 第五步在运行时驱动地图Runtime APIURL 参数只能在加载时一次性配置嵌入。要与正在运行的地图持续对话——例如用户在你的页面 UI 中点击某条记录时飞到对应位置或监听地图内部的用户行为——需要使用运行时 API。这依赖geolibre/embed包提供的类型化客户端npm install geolibre/embedimport { connect } from geolibre/embed; const map await connect(document.querySelector(iframe), { origin: https://web.geolibre.app, }); map.on(selectionChanged, ({ featureIds }) showRecordFor(featureIds[0])); async function focusField(field) { await map.setView({ bbox: field.bbox }); await map.highlightFeature({ layerId: fields, filter: { parcel_id: field.id }, fit: true }); }教程特别强调一个关键前提该 API 只对白名单内部署生效。web.geolibre.app没有配置允许列表因此运行时 API 只能在你自托管的构建中使用。为什么默认关闭origin 允许列表运行时 API默认关闭公开部署的实例永远不能被包裹它的页面所驱动。开启方式是为部署命名信任的 origin 列表。Docker 镜像通过一个环境变量开启docker run --rm -p 8080:80 \ -e GEOLIBRE_EMBED_ORIGINShttps://portal.example.com,https://erp.example.com \ ghcr.io/opengeos/geolibre:latest静态构建则把值烘焙进去VITE_GEOLIBRE_EMBED_ORIGINShttps://portal.example.com npm run build条目是 originscheme://host[:port]尾部路径会被忽略*允许任意 origin只适合私有网络。允许列表是双向强制的来自未列出 origin 的消息被忽略应用发出的每条消息也只投递给列出的 origin。配置*时出站消息会先投递给*直到主机的第一条消息标识出它——这正是应该明确列出 origin 的又一个理由。源码层面这个解析逻辑位于 apps/geolibre-desktop/src/lib/embed-api.tsparseEmbedOrigins会把逗号/空白分隔的值规范化为去重的 origin 列表无法解析为 origin 的条目会被丢弃而不是悄悄扩大白名单readEmbedOrigins会先读取 Docker 入口脚本写入window.__GEOLIBRE_DEPLOYMENT_ENV__的运行时配置这样运维人员无需重新构建即可用-e GEOLIBRE_EMBED_ORIGINS...配置再回退到构建期 Vite 环境变量isEmbedOriginAllowed则执行实际的匹配。Docker 侧对GEOLIBRE_EMBED_ORIGINS的校验必须是 http(s) origin、拒绝带凭据或路径的值在 docker/entrypoint.sh 中完成。允许列表决定谁可以发命令。要进一步收窄存在哪些命令可以结合 deployment capabilities 构建避免受信任的主页把嵌入地图变成通用的数据抓取代理。被拒绝的命令会以Missing capability capability拒绝而非静默无操作loadProject需要project:editaddLayer和addData需要data:addopenTool需要processing:runexportImage需要export:data。setView、highlight、图层可见性等命令无特权始终可用。类型化客户端Typed Clientgeolibre/embed是一个零依赖的 ESM 包随每个 GeoLibre 发布版同步发布到 npm因此包版本与应用版本保持一致见 packages/embed/package.json 与 packages/embed/README.md。connect(iframe, options)返回一个 Promise应用发出ready事件后即 resolve因此无需自己编写握手逻辑。客户端还会为每条命令打上requestId并从对应的ack中结算该命令的 Promise——这就是多条命令可同时在途而不串答案的原因。import { connect } from geolibre/embed; const map await connect(iframe, { origin: https://web.geolibre.app, // 托管 iframe 的精确 origin timeoutMs: 15_000, // 等待 ready默认 15s requestTimeoutMs: 15_000, // 等待每个 ack默认 15s });origin是必填项必须是 http(s) origin它既是所有出站消息的目标也是入站消息的过滤器来自其他 frame 或 origin 的消息会被忽略。传入的是应用app的 origin而不是你自己的。这个校验逻辑在 packages/embed/src/index.ts 的validOrigin中实现且connect把同步异常也统一转入返回的 Promise避免调用方写connect(...).catch(...)时捕获不到。客户端方法一览方法解析值说明loadProject(url)void不重载 iframe 直接切换项目setView(target)void{ bbox }或{ center, zoom, bearing, pitch, duration }中的任意组合highlightFeature({ layerId, … })voidfeatureId、featureIds或filterfit: true会缩放至匹配要素openTool(id, params?)void?tool的运行时孪生setLayerVisibility(layerId, visible)void显示或隐藏项目图层listLayers()LayerSummary[]每个图层返回{ id, name, type, visible, opacity }setFilter(layerId, expression)voidMapLibre 过滤器表达式null清除getViewport()Viewport{ bbox, center, zoom, bearing, pitch }addLayer(spec)新图层id接收项目格式的图层规格addData(url, options?)新图层id数组类似?data加载远程数据options 为{ styleUrl, fit }exportImage()PNGdata:URL当前渲染画面on(event, listener)反订阅函数非 Promise事件见下表disconnect()非 Promise移除监听并拒绝所有在途请求每条命令都是拒绝reject而不是假性 resolve携带ok: false的ack会以应用自己的错误消息拒绝requestTimeoutMs内无应答的命令以超时拒绝。connect本身在timeoutMs内收不到ready时拒绝——最常见的原因是部署没有白名单你的 origin或origin与 iframe 不匹配。拆除 iframe 时应调用disconnect()如 React effect 清理、路由切换它会停止 message 监听并拒绝所有挂起的命令避免 Promise 在页面生命周期内悬挂。on返回自己的反订阅函数接受下表全部事件按名称类型化。原始 postMessage 协议无法引入依赖的宿主可以直接说协议。所有消息双向都带版本号{ v: 2, type: setView, payload: { center: [-95.7, 37.1], zoom: 5 } }应用发出的消息还带source: geolibre方便你在页面其他 postMessage 流量中过滤。Host → GeoLibre 命令类型Payload效果loadProject{ url }不重载 iframe 加载.geolibre.json项目setView{ bbox }或{ center, zoom, bearing, pitch, duration }适配包围盒或飞到指定相机highlightFeature{ layerId, featureId \| featureIds \| filter, fit }选择并高亮要素filter匹配属性fit缩放过去openTool{ id, params }打开 Processing 对话框并预填params?tool的运行时孪生setLayerVisibility{ layerId, visible }显示或隐藏项目图层listLayers{}在 ack 的result中返回图层摘要setFilter{ layerId, expression }应用 MapLibre 过滤器表达式发null清除getViewport{}在result中返回当前相机与范围addLayer{ spec }运行时添加项目格式图层规格addData{ url, styleUrl?, fit? }不重载 iframe 加载 GeoJSON/API、ZIP、GeoParquet、PMTiles 或 COG 数据exportImage{}在result中返回渲染地图的 PNG data URL细节约束源码见 apps/geolibre-desktop/src/lib/embed-api.ts 的parseEmbedRequest单独发{ layerId }给highlightFeature表示清除高亮命名了要素或过滤器但无匹配的请求会被拒绝而不是当作清除处理防止打错 id 时静默清掉用户的选择。高亮读取的是项目中的图层要素因此只适用于 GeoLibre 以 GeoJSON 持有的矢量图层不适用于要素只存在于瓦片源中的图层setFilter在存储前会通过 MapLibre 样式规范编译表达式checkFilterExpression保证ok的 ack 意味着地图现在真的按此过滤addLayer要求 source 是地图能真正读取的url、非空tiles或仅限geojson与deckgl-viz两种内联要素图层类型内联geojson同时拒绝javascript:、vbscript:、data:、file:、blob:开头的 URLpmtiles://等自定义地图协议允许addData与dataURL 参数共用格式检测、CORS 要求、安全限制与可选样式导入默认把新数据适配到视野传fit: false保留当前相机。给任何消息加requestId应用就会以ack应答其执行结果。GeoLibre → Host 事件类型Payload触发时机ready{ version }应用挂载完成并开始监听ack{ requestId, ok, error, result }你发送的带requestId的消息被执行或被拒绝projectLoaded{ url, name, layerIds }项目加载完成无论谁触发的selectionChanged{ layerId, featureIds }用户或你的highlightFeature改变了选择viewChanged{ bbox, center, zoom, bearing, pitch }相机移动约每秒 4 次节流toolCompleted{ id, name, status, engine, durationMs, outputLayerNames }处理任务结束成功与否都会触发serverFileWritten{ path, toolId }文件型工具写入了输出转换与栅格工具运行时接线位于 apps/geolibre-desktop/src/hooks/useEmbedApi.tsready事件保证所有命令可用viewChanged事件以 250ms 为窗口节流并带尾沿trailing edge发送保证拖拽结束后宿主仍能收到最终位置toolCompleted与serverFileWritten来自对处理历史processing history的订阅。协议兼容性方面当前为 v2应用仍接受 v1 请求信封并以 v1 事件应答 v1 宿主已有的手写集成保持兼容。一个完整的宿主页面无依赖写法iframe idmap srchttps://gis.example.com/?urlhttps://erp.example.com/fields.geolibre.jsonmaponly titleGeoLibre map width100% height600 styleborder: 0 /iframe script const frame document.getElementById(map); const APP_ORIGIN https://gis.example.com; const send (type, payload) frame.contentWindow.postMessage({ v: 2, type, payload }, APP_ORIGIN); window.addEventListener(message, (event) { if (event.origin ! APP_ORIGIN) return; const message event.data; if (message?.source ! geolibre || message.v ! 2) return; if (message.type ready) { // 从这里开始发送命令是安全的。 } else if (message.type selectionChanged) { showRecordFor(message.payload.featureIds[0]); } }); // 点击你自己 UI 中的记录飞过去并高亮无需重载。 function focusField(field) { send(setView, { bbox: field.bbox }); send(highlightFeature, { layerId: fields, filter: { parcel_id: field.id }, fit: true, }); } /script关键要点先等ready再发命令应用挂载完成前到达的消息不会排队把ready视为幂等应用重新挂载时会重发frame 内导航、开发热重载允许列表同时收窄了?embed1项目/脚本桥Python 包 使用到同样的 origin 列表额外的加固可以在反向代理上添加Content-Security-Policy: frame-ancestors your origins阻止其他站点嵌入你的应用。切换渲染器嵌入地图也支持在 MapLibre 与 Cesium 渲染器之间切换client.on(rendererchange, ({ renderer }) console.log(renderer)); await client.setRenderer(cesium); const renderer await client.getRenderer();两个方法接受或返回maplibre或cesium。setRenderer确认选择后新画布会异步挂载在发出相机或截图命令前应等待下一次ready事件。exportImage()两种渲染器都支持会在可见图层稳定后返回 PNG data URL。7. 测试与验证仓库为嵌入 API 提供了完整的单元测试可作为协议实现的权威行为说明tests/embed-api.test.ts覆盖应用侧的消息解析、origin 白名单、命令校验与拒绝语义tests/embed-client.test.ts覆盖geolibre/embed客户端的请求关联、超时与事件订阅行为。端到端层面e2e/embed-api.spec.ts 与 e2e/embed-client.spec.ts位于 e2e 目录验证了真实浏览器中的 iframe 通信链路。阅读这些测试可以精确掌握每个参数、每条命令的边界条件。8. 后续步骤分享前用 Controls 菜单 调整哪些控件出现回到 Your First Map 制作想要分享的地图完整参数表与协议参考见 Embedding Sharing 完整参考部署到自己的域名并开启运行时 API参考 Self-Hosting 与 Deployment Capabilities。【免费下载链接】GeoLibreA lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.项目地址: https://gitcode.com/GitHub_Trending/ge/GeoLibre创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考