@zhangdali1996/lr-map-viewer
v0.0.50
Published
`@zhangdali1996/lr-map-viewer` 是面向 Vue 3 项目的三维地图组件库,提供龙软三维场景承载能力,以及基于组件实例的视角控制与模型信息查询能力。
Downloads
5,781
Readme
@zhangdali1996/lr-map-viewer
@zhangdali1996/lr-map-viewer 是面向 Vue 3 项目的三维地图组件库,提供龙软三维场景承载能力,以及基于组件实例的视角控制与模型信息查询能力。
主要能力:
- 支持 Vue 3 项目中以组件方式挂载二维图纸容器。
- 支持 Vue 3 项目中以组件方式挂载三维地图容器。
- 支持
2d / 3d模式切换与统一壳层承载。 - 支持龙软三维 SDK 的运行时加载。
- 支持通过运行时配置传入二维图纸参数。
- 支持通过运行时配置传入云 GIS 参数。
- 支持通过运行时配置显式传入三维场景
basePoint。 - 支持按需显示区域显隐面板、调试面板和监测点面板。
- 支持通过组件实例调用
moveView(x, y, z)移动三维视角。 - 支持通过组件实例保存/恢复视角,以及控制演示人员的初始化、运动和聚焦。
- 支持通过组件实例注册
registerModelInfoQuery(callback)查询点击模型信息。
安装
npm install @zhangdali1996/lr-map-viewervue 和 element-plus 作为 peerDependencies 提供,要求使用方项目自行安装。
二维图纸依赖的 @longruan/lr-map 已随当前组件库构建产物内置,客户项目安装本包时不需要再额外访问公司内网 npm 拉取这个依赖。
安装后请显式引入组件库样式:
import '@zhangdali1996/lr-map-viewer/style.css'说明:
- 这部分样式对应组件库自身的布局、面板、占位态等 UI。
- 龙软 SDK 的
/editorapp、/resource静态资源及其中的样式,仍需由实施方单独提供。
静态资源放置
该包不会携带龙软 SDK 的大体积静态资源。以下目录需要由实施方单独提供给客户:
editorappresource
推荐放置到客户项目的 public 目录:
public/
editorapp/
resource/对应默认访问路径:
/editorapp/editorapp.bundle.js/resource/js/three.min.js/resource/js/vue.2.6.11.js/resource/js/element_ui.js/resource/js/jquery-3.1.1.min.js
如果客户项目的静态资源目录不是根路径,需要通过 lr3dConfig.sdk 自定义覆盖路径。
如果客户项目把龙软静态资源统一挂在某个业务前缀下,可以通过组件入参 resource-prefix 传入,让组件自动给默认的 /editorapp 和 /resource 路径补前缀。
例如:
<LrMapViewer resource-prefix="gkpt" />会自动解析为:
/gkpt/editorapp/editorapp.bundle.js/gkpt/resource/js/three.min.js/gkpt/resource/js/vue.2.6.11.js/gkpt/resource/js/element_ui.js/gkpt/resource/js/jquery-3.1.1.min.js
说明:
- 不传
resource-prefix时,默认仍然使用/editorapp和/resource - 支持传
gkpt、/gkpt、gkpt/、/gkpt/,最终都会归一化为/gkpt - 如果你已经显式传了完整的
sdk.scriptSrc或sdk.dependencies[].src,则建议直接传最终路径
最小接入示例
三维示例
<script setup>
import '@zhangdali1996/lr-map-viewer/style.css'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const credentialKey = 'your_credential_key'
const lr3dConfig = {
// 是否在场景初始化成功后自动加载云 GIS 数据
autoLoad: true,
cloud: {
// 数据源 guid
dsGuid: 'your_ds_guid',
// 三维场景基点
basePoint: {
x: 37517614.46684,
y: 4410289.679932,
z: 972.148557,
},
// 需要加载的巷道图层名
layers: ['your_lane_layer_name'],
laneSize: {
// 巷道渲染宽度
width: 10,
// 巷道渲染高度
height: 10,
},
},
}
</script>
<template>
<div style="height: 100vh;">
<LrMapViewer :lr3d-config="lr3dConfig" :credential-key="credentialKey" />
</div>
</template>二维图纸示例
<script setup>
import '@zhangdali1996/lr-map-viewer/style.css'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const credentialKey = 'your_credential_key'
const map2dConfig = {
behavior: {
autoInitLayer: true,
autoShowLayer: true,
captureLayerTree: true,
},
options: {
ygis_dsGuid: 'your_ds_guid',
layerName: 'your_layer_name',
layerCode: '',
},
}
</script>
<template>
<div style="height: 100vh;">
<LrMapViewer
mode="2d"
:modes="['2d']"
:map2d-config="map2dConfig"
:credential-key="credentialKey"
/>
</div>
</template>二维三维切换示例
<script setup>
import { ref } from 'vue'
import '@zhangdali1996/lr-map-viewer/style.css'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const activeMode = ref('2d')
const credentialKey = 'your_credential_key'
const map2dConfig = {
options: {
ygis_dsGuid: 'your_ds_guid',
layerName: 'your_layer_name',
},
}
const lr3dConfig = {
autoLoad: true,
cloud: {
dsGuid: 'your_ds_guid',
basePoint: {
x: 37517614.46684,
y: 4410289.679932,
z: 972.148557,
},
layers: ['your_lane_layer_name'],
},
}
</script>
<template>
<div style="height: 100vh;">
<LrMapViewer
:mode="activeMode"
:modes="['2d', '3d']"
:map2d-config="map2dConfig"
:lr3d-config="lr3dConfig"
:credential-key="credentialKey"
/>
</div>
</template>如果你需要默认显示右上角区域显隐面板和调试面板:
<LrMapViewer
:lr3d-config="lr3dConfig"
:credential-key="credentialKey"
:show-region-panel="true"
:show-debug-panel="true"
/>说明:
- 三维组件已内置默认的
sdk、scene、initOptions、dataSource.type、dataSource.loadMode配置,通常不需要手动传入。 - 推荐只传
autoLoad和cloud下的业务参数即可。 - 如果你有特殊需求,仍然可以继续传完整的
lr3dConfig结构来覆盖默认值。
推荐接入方式
推荐直接按需引入组件:
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'也支持作为插件安装:
import { createApp } from 'vue'
import LrMapViewerPlugin from '@zhangdali1996/lr-map-viewer'
import App from './App.vue'
createApp(App).use(LrMapViewerPlugin).mount('#app')命名导出
除默认导出的插件对象外,包入口还提供以下命名导出:
- 组件:
LrMapViewer、Lr2dViewer、Lr3dViewer - 2D 配置工具:
getDefaultLr2dConfig、getLr2dConfig、getLr2dMapOptions、setLr2dConfig、resetLr2dConfig、resolveLr2dConfig、getMissingLr2dOptionFields、getRequiredLr2dOptionFields、isLr2dConfigReady - 3D 配置工具:
getDefaultLr3dConfig、getLr3dConfig、setLr3dConfig、resetLr3dConfig、resolveLr3dConfig - 模式工具:
getSupportedMapModes、normalizeMapMode、resolveMapModes、resolveInitialMapMode、canSwitchMapMode - 2D/3D 适配与数据方法:同时导出
adapters/lr2d、adapters/lr3d和services/gis中的方法,适合在需要直接操作底层地图实例或手动加载云 GIS 数据时使用
公开能力
组件 Props:
mode当前激活模式,支持2d或3d。modes当前组件允许启用的模式列表,默认['3d']。map2dConfig二维图纸运行时配置。lr3dConfig龙软三维运行时配置。resourcePrefix三维静态资源业务前缀,用于统一给默认/editorapp与/resource路径补前缀。credentialKey内部凭证解密 Key,二维与三维都会使用它解析内置认证信息。showRegionPanel是否显示区域显隐面板,默认false。showDebugPanel是否显示调试面板,默认false。showMonitorPanel是否显示监测点面板,默认false。
组件事件:
mode-change当前显示模式切换时触发,回调参数结构如下:
{
mode: '2d' | '3d',
previousMode: '2d' | '3d',
supportedModes: ['2d', '3d'],
}组件 expose:
switchMode(mode)getCurrentMode()getCurrentEngine()get2dInstance()get3dInstance()resize()refreshScene()registerModelInfoQuery(callback)
说明:
switchMode(mode)支持在2d / 3d间切换当前显示引擎。get2dInstance()返回当前二维 adapter 实例,其中包含map、options、behavior、layerTree等信息。refreshScene()仅对三维场景有效。registerModelInfoQuery(callback)会在用户点击三维中的模型对象时触发回调。- 模型信息查询返回 4 个字段:
id、name、layerName、position。
监测点模块
监测点相关能力通过组件实例提供,适合业务侧自己实现外部按钮、列表和联动逻辑。
监测点模块 expose:
initMonitorPoints()queryMonitorPointList()reloadMonitorPoints()focusMonitorPoint(target)focusPerson(target)movePerson(target)
说明:
initMonitorPoints()用于初始化监测点,组件会查询监测点数据并加载显示到三维场景中。queryMonitorPointList()会重新查询最新监测点数据,并返回列表结果,但不会把结果重新加载到地图上。reloadMonitorPoints()会先清空当前场景中已加载的监测点,再重新查询并加载,避免重复添加。focusMonitorPoint(target)会将视口移动到指定监测点,并打开该监测点的信息弹窗;target支持传监测点id或监测点对象。focusPerson(target)用于聚焦指定人员定位对象;target支持传人员sceneId、人员名称或人员对象,不传时默认聚焦第一名人员。movePerson(target)用于触发指定人员的轨迹移动;target的传参规则与focusPerson(target)保持一致。
视角控制模块
视角控制相关能力同样通过组件实例提供,便于业务侧自己实现“视角列表 + 当前视口保存恢复”。
视角控制模块 expose:
getViewPointList()switchToViewPoint(target)getCurrentViewInfo()applyViewInfo(viewInfo)
说明:
getViewPointList()返回当前预设视角列表,列表项包含key、name、cameraPos、viewCenter。switchToViewPoint(target)用于切换到指定预设视角;target支持传预设视角key、视角名称或视角对象。getCurrentViewInfo()用于读取当前视口的视角信息,返回结果可直接作为applyViewInfo(viewInfo)的入参。applyViewInfo(viewInfo)用于按传入的视角参数恢复视口位置和视角中心。
其他 3D 方法
以下方法继续保留,主要用于兼容现有接入方式或演示人员联动:
initializeDemoPerson()startDemoPersonMotion(x, y, z)stopDemoPersonMotion()toggleDemoPersonMotion(x, y, z)focusDemoPerson()moveView(x, y, z)
说明:
initializeDemoPerson()用于初始化人员演示对象或人员轨迹对象。startDemoPersonMotion()、stopDemoPersonMotion()、toggleDemoPersonMotion()为旧的人员演示控制方法。focusDemoPerson()用于聚焦当前主人员对象。moveView(x, y, z)用于按绝对坐标快速聚焦目标点。
范围选点模块
范围选点相关能力单独通过组件实例提供,适合外部业务系统自己实现按钮、面板和联动逻辑,而不是依赖组件内部调试面板。
范围选点模块 expose:
startRangeSelection(options)cancelRangeSelection(options)setRangeSelection(center, options)setRangeSelectionByCoordinate(center, options)setRangeSelectionRadius(radius)clearRangeSelection()getRangeSelectionResult()registerRangeSelectionChange(callback)focusMonitorPoint(target)
说明:
startRangeSelection(options)用于启动范围选点,支持通过options.radius指定初始半径。cancelRangeSelection(options)用于取消当前范围选点,可通过options.preserveCurrentResult控制是否保留当前结果。setRangeSelection(center, options)用于直接传入三维坐标生成球形范围,适合业务系统通过外部坐标直接驱动范围选点。setRangeSelectionByCoordinate(center, options)用于通过外部接口传入坐标生成球形范围,内部复用setRangeSelection的范围绘制、测点过滤和回调链路。setRangeSelectionRadius(radius)用于更新当前范围半径;如果当前已完成选点,会同步更新球体和范围内测点。clearRangeSelection()用于清除当前范围球、选点标记和测点过滤结果。getRangeSelectionResult()返回当前范围选点结果,包含状态、半径、球心坐标、当前巷道信息和范围内测点列表。registerRangeSelectionChange(callback)会在开始选点、选点完成、半径变化、取消、清除时触发回调。focusMonitorPoint(target)用于定位并打开指定测点的信息窗,支持传测点id或测点对象。
二维图纸配置说明
推荐写法:
const map2dConfig = {
behavior: {
autoInitLayer: true,
autoShowLayer: true,
captureLayerTree: true,
},
options: {
ygis_dsGuid: 'your_ds_guid',
ygis_url: 'https://your-cloud-gis-server/',
Url: 'https://your-map-server/',
layerName: 'your_layer_name',
layerCode: '',
token: 'your_token',
extent: '',
rotate: false,
animate: false,
zoomAnimation: false,
markerZoomAnimation: false,
fadeAnimation: false,
},
}推荐接入方式分为两种:
- 通过
credentialKey接入: 组件会自动补齐ygis_url、map_server_url/Url、ygis_username、ygis_password,此时你通常只需要传业务相关字段,例如ygis_dsGuid、layerName、layerCode。 - 不通过
credentialKey,直接手动传完整二维配置: 需要自行补齐地址和认证信息。
手动直传完整二维配置时的必填字段:
map2dConfig.options.ygis_dsGuid二维图纸数据源 guid。map2dConfig.options.ygis_url云 GIS 服务地址。map2dConfig.options.Url二维地图服务地址。map2dConfig.options.token二维认证 token,和用户名密码二选一。
认证兼容说明:
- 如果没有
token,则需要同时传入map2dConfig.options.ygis_username和map2dConfig.options.ygis_password。 map2dConfig.options.map_server_url与map2dConfig.options.Url在组件内部会自动对齐,二者传一个即可。- 当
map2dConfig.behavior.autoShowLayer为true时,map2dConfig.options.layerName也属于必填项。
常用可选字段:
map2dConfig.options.layerCode图层编码,默认可传空字符串。map2dConfig.options.extent初始范围。map2dConfig.behavior.autoInitLayer是否自动初始化图层,默认true。map2dConfig.behavior.autoShowLayer是否自动显示指定图层,默认true。map2dConfig.behavior.captureLayerTree是否抓取图层树,默认true。
接口示例
推荐通过 ref 调用组件实例方法:
监测点模块示例
<script setup>
import { ref } from 'vue'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const viewerRef = ref(null)
async function handleInitMonitorPoints() {
await viewerRef.value?.initMonitorPoints?.()
}
async function handleReloadMonitorPoints() {
await viewerRef.value?.reloadMonitorPoints?.()
}
async function handleQueryMonitorPoints() {
const list = await viewerRef.value?.queryMonitorPointList?.()
console.log('monitor points', list)
}
function handleFocusMonitorPoint() {
viewerRef.value?.focusMonitorPoint?.('mock-monitor-point-1')
}
function handleFocusPerson() {
viewerRef.value?.focusPerson?.()
}
function handleMovePerson() {
viewerRef.value?.movePerson?.()
}
</script>
<template>
<div style="height: 100vh;">
<button type="button" @click="handleInitMonitorPoints">初始化监测点</button>
<button type="button" @click="handleReloadMonitorPoints">重新加载监测点</button>
<button type="button" @click="handleQueryMonitorPoints">查询监测点</button>
<button type="button" @click="handleFocusMonitorPoint">聚焦监测点</button>
<button type="button" @click="handleFocusPerson">聚焦人员</button>
<button type="button" @click="handleMovePerson">人员移动</button>
<LrMapViewer ref="viewerRef" :lr3d-config="lr3dConfig" />
</div>
</template>视角控制模块示例
<script setup>
import { ref } from 'vue'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const viewerRef = ref(null)
const currentViewInfo = ref(null)
function handleSwitchViewPoint() {
viewerRef.value?.switchToViewPoint?.('井口')
}
function handleCaptureViewInfo() {
currentViewInfo.value = viewerRef.value?.getCurrentViewInfo?.() ?? null
}
function handleRestoreViewInfo() {
if (currentViewInfo.value) {
viewerRef.value?.applyViewInfo?.(currentViewInfo.value)
}
}
</script>
<template>
<div style="height: 100vh;">
<button type="button" @click="handleSwitchViewPoint">切换到井口视角</button>
<button type="button" @click="handleCaptureViewInfo">读取当前视口</button>
<button type="button" @click="handleRestoreViewInfo">按视角参数恢复</button>
<LrMapViewer ref="viewerRef" :lr3d-config="lr3dConfig" />
</div>
</template>范围选点模块示例
如果你需要通过组件实例控制范围选点:
<script setup>
import { ref, watch } from 'vue'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const viewerRef = ref(null)
function startRangeSelection() {
viewerRef.value?.startRangeSelection?.({
radius: 500,
})
}
function setRangeSelectionByCoordinate() {
viewerRef.value?.setRangeSelectionByCoordinate?.(
{ x: 37515615.6365, y: 4412429.261443, z: 1270.872 },
{ radius: 500 },
)
}
function clearRangeSelection() {
viewerRef.value?.clearRangeSelection?.()
}
function focusFirstMonitorPoint() {
const result = viewerRef.value?.getRangeSelectionResult?.()
const firstMonitorPoint = result?.monitorPoints?.[0]
if (firstMonitorPoint) {
viewerRef.value?.focusMonitorPoint?.(firstMonitorPoint)
}
}
watch(
viewerRef,
(viewer) => {
if (!viewer?.registerRangeSelectionChange) {
return
}
viewer.registerRangeSelectionChange((payload) => {
console.log('range selection', payload)
})
},
{ immediate: true },
)
</script>
<template>
<div style="height: 100vh;">
<button type="button" @click="startRangeSelection">开始范围选点</button>
<button type="button" @click="setRangeSelectionByCoordinate">按坐标生成范围</button>
<button type="button" @click="clearRangeSelection">清除范围</button>
<button type="button" @click="focusFirstMonitorPoint">定位首个测点</button>
<LrMapViewer ref="viewerRef" :lr3d-config="lr3dConfig" />
</div>
</template>如果你需要切换二维与三维模式:
<script setup>
import { ref } from 'vue'
import { LrMapViewer } from '@zhangdali1996/lr-map-viewer'
const viewerRef = ref(null)
function switchTo2d() {
viewerRef.value?.switchMode?.('2d')
}
function switchTo3d() {
viewerRef.value?.switchMode?.('3d')
}
</script>
<template>
<div style="height: 100vh;">
<button type="button" @click="switchTo2d">查看二维</button>
<button type="button" @click="switchTo3d">查看三维</button>
<LrMapViewer
ref="viewerRef"
:modes="['2d', '3d']"
:map2d-config="map2dConfig"
:lr3d-config="lr3dConfig"
/>
</div>
</template>模型信息查询回调返回结构:
{
// 模型或实体标识
id: '...',
// 模型或实体名称
name: '...',
// 所属图层名
layerName: '...',
position: {
// 模型本地坐标 x
x: 0,
// 模型本地坐标 y
y: 0,
// 模型本地坐标 z
z: 0,
},
}云 GIS 配置说明
推荐写法:
const lr3dConfig = {
autoLoad: true,
cloud: {
server: 'https://your-cloud-gis-server/',
username: 'your_username',
password: 'your_password',
dsGuid: 'your_ds_guid',
basePoint: {
x: 37517614.46684,
y: 4410289.679932,
z: 972.148557,
},
layers: ['your_lane_layer_name'],
laneSize: {
width: 10,
height: 10,
},
},
}推荐接入方式同样分为两种:
- 通过
credentialKey接入: 组件会自动补齐cloud.server、cloud.username、cloud.password,此时你通常只需要传autoLoad、cloud.dsGuid、cloud.basePoint以及业务图层参数。 - 不通过
credentialKey,直接手动传完整三维配置: 需要自行补齐三维服务地址和认证信息。
手动直传完整三维配置时的必填字段:
autoLoad是否在场景初始化成功后自动加载云 GIS 数据。cloud.server云 GIS 服务地址。cloud.username云 GIS 用户名。cloud.password云 GIS 密码。cloud.dsGuid数据源 guid。cloud.basePoint.x三维场景基点 x 坐标。cloud.basePoint.y三维场景基点 y 坐标。cloud.basePoint.z三维场景基点 z 坐标。
可选字段:
cloud.layers需要加载的巷道图层名数组。cloud.laneSize.width巷道渲染宽度,默认10cloud.laneSize.height巷道渲染高度,默认10
兼容说明:
- 组件内部仍兼容完整的
lr3dConfig写法。 basePoint推荐传入{ x, y, z }对象。resource-prefix可用于统一给默认的/editorapp与/resource路径增加业务前缀,例如gkpt -> /gkpt/editorapp/...、/gkpt/resource/...。- 如果你需要覆盖 SDK 路径、容器参数、初始化参数等高级配置,仍然可以继续传入
sdk、scene、initOptions、dataSource完整结构。
示例配置
下面这份三维配置可直接作为联调参考:
const playgroundLr3dConfig = {
autoLoad: true,
cloud: {
server: 'https://your-cloud-gis-server/',
username: 'your_username',
password: 'your_password',
dsGuid: 'your_ds_guid',
basePoint: {
x: 37517614.46684,
y: 4410289.679932,
z: 972.148557,
},
layers: ['your_lane_layer_name'],
laneSize: {
width: 10,
height: 10,
},
},
}常见错误排查
1. 场景初始化失败:SDK 前置依赖加载失败
典型错误:
场景初始化失败:SDK 前置依赖加载失败: /resource/js/jquery-3.1.1.min.js排查方向:
- 确认客户项目里确实存在
public/resource/js/jquery-3.1.1.min.js。 - 确认浏览器访问
/resource/js/jquery-3.1.1.min.js返回 200,而不是 404。 - 如果资源目录不在根路径,使用完整
lr3dConfig.sdk.dependencies配置覆盖默认脚本路径。 - 确认
editorapp与resource属于同一套 SDK 版本,不要混用不同批次文件。
2. 场景初始化失败:未检测到全局对象
这类错误通常表示脚本文件虽然加载了,但脚本执行后没有挂出预期全局变量。
排查方向:
- 检查使用的 SDK 版本是否与组件默认配置匹配。
- 检查脚本是否被浏览器拦截、跨域策略阻止,或返回了错误 HTML 页面。
- 检查依赖加载顺序是否正确,前置依赖必须先于
editorapp.bundle.js完成加载。
3. 云 GIS 数据源配置缺失
典型原因:
- 组件库默认配置已不再携带真实业务参数。
- 接入方没有传入
server、username、password、dsGuid、basePoint。
处理方式:
- 在
lr3dConfig.cloud中补齐实际项目所需字段。
