应用App
App是基于vjmap3d开发出的3d应用,他作为 vjmap3d 的核心,主要负责管理场景渲染, 事件交互等。
应用模块
App类本身基本上没有什么方法和属性,他是由以下应用模块 Module功能组合而成。
📌 模块成员是 mixin 注入:模块唤醒时经
applyMixinsTo(app, [...])把成员挂到app上。App.defaultModules(即下表全部模块,含StatModule/CameraModule)不论是否传对应选项都会注入——只有用options.modules自定义模块列表去掉某模块时,对应app.*才不存在。getter 的值可能是undefined(如未设stat.show时app.showStat === undefined),但app.showStat = true照常生效;判断模块是否存在请用app.getModule(vjmap3d.StatModule),不要用typeof app.showStat。
| 应用模块名 | 描述 | 选项参数名 |
|---|---|---|
| WebGLRendererModule | 渲染引擎模块 | render |
| CameraModule | 相机模块 | camera |
| OrbitControlModule | 轨道控制器模块 | control |
| SceneModule | 场景模块 | scene |
| PostProcessModule | 后期处理模块 | postProcess |
| CoordSystemModule | 坐标转换模块 | coordSystem |
| EntityManagerModule | 实体管理模块 | |
| EntityQueryModule | 实体查询模块 | |
| InputModule | 鼠标键盘输入模块 | input |
| PickModule | 拾取交互模块 | |
| UiModule | UI界面模块 | ui |
| RectCollideModule | 矩形碰撞检测模块 | rectCollide |
| ToolStateModule | 工具交互模块 | toolState |
| CommandModule | 命令模块 | command |
| StatModule | 性能统计模块 | stat |
| ParticleRenderModule | 粒子效果模块 | particle |
| PhysicsManagerModule | 物理引擎模块 | physics |
| EntityOutlineModule | 实体描边模块 | entityOutline |
| CSS2DRendererModule | css2d渲染引擎模块 | css2dRender |
| CSS3DRendererModule | css3d渲染引擎模块 | css3dRender |
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
scene: {
gridHelper: { visible: true } // 是否显示坐标网格
}
})
const ui = await app.getConfigPane();
let cfg = app.uiConfig
ui.appendChild(cfg)
提示
默认情况下,按 Ctrl + Shift + U 可弹出或关闭属性面板
信号事件
App 常用的信号事件如下:
| 事件名 | 描述 |
|---|---|
| onSelectedChange | 物体选择信息改变事件 |
| onEntitySelected | 实体设置选择 |
| onEntityUnSelected | 实体取消选择 |
| onBloomedChange | 实体辉光改变 |
| onEntityBloomed | 实体设置辉光 |
| onEntityUnBloomed | 实体取消辉光 |
| onOutlineChange | 实体描边改变 |
| onEntityOutline | 实体设置描边 |
| onEntityUnOutline | 实体取消描边 |
| onMouseUp | 鼠标抬起 |
| onMouseMove | 鼠标移动 |
| onMouseDown | 鼠标按下 |
| onMousePreClick | 鼠标按下之前 |
| onMouseClick | 鼠标单击 |
| onMouseDblClick | 鼠标双击 |
| onMouseOver | 鼠标指针穿过被选元素或其子元素,均会触发事件 |
| onMouseOut | 鼠标指针离开被选元素或其子元素则触发事件 |
| onMouseEnter | 鼠标指针穿过被选元素时才触发事件 |
| onMouseLeave | 鼠标指针离开被选元素时才触发事件 |
| onContextMenu | 上下文菜单事件 |
| onPointerDown | 指针按下(PC和移动端) |
| onPointerMove | 指针移动(PC和移动端) |
| onPointerUp | 指针抬起(PC和移动端) |
| onPointerDownUp | 指针直接按下松开,没有拖动 |
| onPointerCancel | 指针取消 |
| onMouseWheel | 鼠标滚轮 |
| onKeyDown | 键盘按下 |
| onKeyUp | 键盘抬起 |
| onAppBeforeUpdate | 每帧更新前运行 |
| onAppUpdate | 每帧更新 |
| onAppAfterUpdate | 每帧更新后运行 |
| onAppBeforeRender | 每帧渲染前运行 |
| onAppRender | 每帧渲染 |
| onAppAfterRender | 每帧渲染后运行 |
📌 帧信号的派发机制:
callModules("onAppUpdate")是三通道扇出——同一调用同时派发moduleManager.callModules(模块方法)、app.dispatch("onAppUpdate")(app.on监听)和app.signal.onAppUpdate.dispatch(signal.add回调)。三条通道等价可用。注意 RAF 节流:页面不可见/无变化时帧率骤降(同一段 400ms 窗口回调 0~9 次),自动化验证勿按固定帧率断言,单帧确定性回调用app.onNextFrame(cb)。 |onAppBeforeAddEntity|实体增加前回调| |onAppAddEntity|实体增加回调| |onAppBeforeRemoveObject|object3d对象移除前回调| |onAppRemoveObject|object3d对象移除回调| |onAppBeforeRemoveEntity|实体移除前回调| |onAppRemoveEntity|实体移除回调| |onContainerSizeChange|窗口大小变化事件| |onCameraControl|相机控件事件| |onCameraUpdate|相机更新事件| |onCameraChange|相机变化事件,当相机对象变化或远近裁剪面变化时触发| |contextMenuPreOpen|上下文菜单即将打开| |contextMenuOpened|上下文菜单已打开| |contextMenuNoContent|上下文菜单打开无内容| |contextMenuCancel|上下文菜单取消| |onCustomEvent|自定义事件| |onAddScene|新增场景| |onActiveScene|把场景置为当前| |onRemoveScene|移除场景|
示例: 响应点击事件,弹出信息
app.signal.onMouseClick.add(e => app.logInfo("您点击了下!", "success" , 1000))
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
// 渲染参数
scene: {
gridHelper: { visible: true } // 是否显示坐标网格
},
camera: { // 相机设置
viewHelper: { enable: true } // 是否显示视角指示器
}
})
//
app.signal.onMouseClick.add(e => app.logInfo("您点击了下!", "success" , 1000))
模块中常用方法属性
WebGLRendererModule
渲染引擎模块。模块参数 render 中可通过 engine 选择渲染引擎:"webgl"(默认,WebGLRenderer)或 "webgpu"(WebGPURenderer,可配 forceWebGL: true 强制 WebGL2 后端,v2.0.0 起提供,旧版 1.0.23 仅 webgl)。浏览器不支持 WebGPU 时由 three 的 WebGPURenderer 自动降级为 WebGL2 后端(仍属 webgpu 引擎:app.renderer.isWebGPURenderer === true、仍只认 TSL/NodeMaterial);只有 three/webgpu/three/tsl 动态加载失败、渲染器 init() 抛错或地图图层(map2d)模式时才回退到 webgl 引擎,详见 WebGPU 渲染引擎。
| 方法名 | 描述 |
|---|---|
| renderer | 渲染器(webgl 引擎时为 WebGLRenderer,webgpu 引擎时为 WebGPURenderer,可用 isWebGPURenderer 判断) |
| isMapMode | 2d地图模式(为true时表示基于vjmap,3d做为一个图层) |
| getScreenshot | 获取渲染截图(返 Blob;参数名是 mine 不是 mime——getScreenshot({mine:"image/png"}),历史拼写;参数对象不可省略:无参调用时内部读 params.download 抛 TypeError、Promise reject,至少写 app.getScreenshot({})) |
| commonUniforms | 通用的uniforms参数 |
whenReady
webgpu 引擎的渲染器为异步初始化:创建 App 后如需立即访问 app.renderer,应先 await app.whenReady()(webgl 引擎下立即返回)。注意 whenReady 自 v2.0.0 起提供——旧版 1.0.23 的 dist 中无此方法,需跨版本兼容时写 await app.whenReady?.()。
CSS2DRendererModule
css2d渲染引擎模块
| 方法名 | 描述 |
|---|---|
| css2dRenderer | 2d渲染器 |
| getMarker2Ds | 获取所有的marker2d |
| getPopup2Ds | 获取所有的popup2d |
| popup2d | 全局的popup对象 |
CSS3DRendererModule
css3d渲染引擎模块
| 方法名 | 描述 |
|---|---|
| css3dRenderer | css3d渲染器 |
| css3dOccludeRenderer | 能遮挡的css3d渲染器 |
| setCss3dObjectCanOcclude | 设置3d物体能否被场景遮挡 |
SceneModule
场景模块
| 方法名 | 描述 |
|---|---|
| addScene | 增加场景 |
| activeScene | 切换场景 |
| removeScene | 移除场景 |
| initScene | 初始化场景 |
| clearScenes | 清空所有场景 |
| sceneEntity | 场景实体 |
| addDefaultLights | 增加缺省灯光 |
| getSceneStatData | 获取场景的统计数据 |
| envConfig | 环境变量 |
| setEnvConfig | 设置环境变量 |
| setBackgroundEnvironment | 设置场景背景及环境参数 |
| setFocus | 获取焦点 |
| loadResources | 加载资源数组 |
| getLoadedResources | 获取通过loadResources已加载的资源 |
EntityManagerModule
实体管理模块
| 方法名 | 描述 |
|---|---|
| getEntities | 获取所有实体 |
| getRayQueryEntities | 获取可以射线查询的实体 |
| addSelectedEntity | 增加选择实体 |
| removeSelectEntity | 移除选择实体 |
| getSelectObjects | 获取选择实体 |
| getSelectObjectsRef | 获取选择实体响应式对象 |
| addBloomEntity | 增加辉光实体 |
| removeBloomEntity | 移除辉光实体 |
| getBloomObjects | 获取辉光实体 |
| getBloomObjectsRef | 获取辉光实体响应式对象 |
| addOutlineEntity | 增加描边实体 |
| removeOutlineEntity | 移除描边实体 |
| getOutlineObjects | 获取描边实体 |
| getOutlineObjectsRef | 获取描边响应式对象 |
| setSelectBoomRefreshFlag | 设置辉光刷新标识 |
StatModule
性能统计模块
| 方法名 | 描述 |
|---|---|
| showStat | 是否显示性能统计 |
CameraModule
相机模块
| 方法名 | 描述 |
|---|---|
| viewHelperEnable | 是否显示视角显示器 |
| setCameraLookAt | 设置相机朝向 |
| enableCameraControl | 是否启用相机控制器 |
| enableCameraControlRef | 相机控制器响应式对象 |
| enableWheelWhenCtrlDisabled | 当相机禁止时还允许滚轮进行缩放操作 |
CoordSystemModule
坐标转换模块
| 方法名 | 描述 |
|---|---|
| unproject | 屏幕坐标转世界坐标(屏幕坐标为浏览器视口 client 坐标,如 event.clientX/clientY,内部会减去容器 left/top;限定求交实体用 { include: [...], exclude: [...] }——直接传数组会被当成普通对象忽略、退化为全场景求交) |
| unprojectAsync | 屏幕坐标转世界坐标(同 unproject 函数,不同的地方是他支持通过后期处理的深度进行转换,是异步执行的;webgl 引擎下未显式 postProcess: { enable: true } 时 getDepth 恒为 undefined,"depth" 方式随之退化为场景射线求交) |
| project | 世界坐标转屏幕坐标 |
| screenToNdc | 屏幕坐标转NDC坐标 |
| ndcToScreen | NDC坐标转屏幕坐标 |
| centerOrigin | 设置的中心点坐标 |
| scaleOrigin | 开始缩放比例,x,y,z方向都同比例缩放,默认1 |
⚠️ 屏幕位置无实体命中时
unproject/unprojectAsync返回形态不一致——unproject返回null,而unprojectAsync返回一个x/y/z全为undefined的 Vector3(不是 null)。判空须用v == null || v.x == null之类写法兼容两者。
PickModule
拾取交互模块
| 方法名 | 描述 |
|---|---|
| isFreeStatus | 当前应该是否处于自由状态 |
| isFreeStatusRef | 自由状态响应式对象 |
| pickPoint | 拾取一个点 |
| pickEntity | 拾取实体 |
| drawSelectBox | 绘制一个选择框 |
| actionDrawPoint | 绘制一个点,获取点坐标 |
| actionDrawLineSting | 绘制一条线,获取线坐标 |
| actionDrawPolygon | 绘制一个多边形,获取多边形坐标 |
| actionDrawEdit | 编辑绘制的对象 |
| actionPickSelect | 选中一个实体对象 |
| getDrawLayer | 通过图层名称获取当前绘图层的实体 |
InputModule
鼠标键盘输入模块
| 方法名 | 描述 |
|---|---|
| addPointerEventsObject | 增加有事件响应的实体 |
| removePointerEventsObject | 移除有事件响应的实体 |
| Input | 当前输入参数 |
| setMenu | 设置地图右键上下文菜单 |
EntityQueryModule
实体查询模块
| 方法名 | 描述 |
|---|---|
| queryEntitiesByCamera | 通过相机查询实体 |
| queryEntitiesByRaycast | 通过射线查询实体 |
| queryEntitiesByScreenPos | 通过屏幕像素坐标查询实体 |
| queryEntitiesByBox | 通过框选查询实体 |
| getRayByScreenPos | 通过屏幕坐标获取射线 |
| getQueryRaycaster | 获取查询的射线对象 |
PostProcessModule
后期处理模块。webgpu 引擎下由 WebGPU 后处理模块自动接管,下列方法在 App 上保持同名可用(composer 返回的是兼容对象而非 pmndrs 的 EffectComposer,其 passes 恒为空数组;bloomEffect 只有 selection/intensity/luminanceThreshold,outlineEffect/selectedEffect 只有 selection/edgeStrength/visibleEdgeColor/hiddenEdgeColor/pulseSpeed;部分 postProcess 参数被忽略),详见 后期处理。
| 方法名 | 描述 |
|---|---|
| composer | 效果合成器 |
| isComposerEnable | 效果合成器是否可用 |
| setComposerEnable | 设置效果合成器是否可用 |
| addEffectRenderPass | 给效果合成器增加渲染通道 |
| removeEffectRenderPass | 给效果合成器移除渲染通道 |
| refreshEffectRenderPass | 刷新渲染通道(⚠️ composer 内同时存在 UV 变换类效果与卷积类效果(如 GlitchEffect)时调用抛 Effects that transform UVs are incompatible with convolution——内部 addRenderPass/setEffectRenderPassOrder 也走此路径,手动调用前先确认效果组合兼容) |
| getDepth | 根据屏幕坐标获取深度值 |
| outlineEffect | OutlineEffect |
| bloomEffect | bloomEffect |
| selectedEffect | selectedEffect |
| isPostProcessIdle | ⚠️ 仅类型声明(后期处理是否空闲),运行时 undefined,勿用 |
RectCollideModule
矩形碰撞检测模块
| 方法名 | 描述 |
|---|---|
| addCollideRectObject | 增加碰撞检测的对象 |
| removeCollideRectObject | 移除碰撞检测的对象 |
| updateCollideRect | 更新碰撞检测 |
| setCollideRectDirty | 设置更新碰撞检测为脏数据,使其重新检测 |
ToolStateModule
工具交互模块
| 方法名 | 描述 |
|---|---|
| rootState | 根状态 |
| getStatePath | 获取状态路径 |
| stateIsIn | stateIsIn |
| stateInAny | stateInAny |
| setCurrentTool | 设置当前工具 |
| getCurrentTool | 获取当前工具 |
| getCurrentToolId | 获取当前工具id |
| getStateDescendant | getStateDescendant |
| addTool | 增加工具 |
| removeTool | 移除工具 |
| isInActiveTool | 判断当前是否有工具处于运行中 |
| isInteracting | 是否正在交互 |
| transformObject | 对一个物体进行变换控制器操作 |
CommandModule
命令模块
| 方法名 | 描述 |
|---|---|
| commandHistory | 命令历史记录 |
| clearCommands | 清空命令 |
| executeCommand | 执行命令,自动执行。⚠️ 无入参校验——executeCommand(null) 抛 Cannot set properties of null (setting 'app'),务必传 ICommand 实例 |
| executeAllCommands | 执行所有命令,自动执行 |
| executeManyCommands | 执行多个命令,自动执行 |
| addCommand | 增加命令,不会自动执行 |
| addAllCommands | 增加全部命令——⚠️ 实现会包成 MultiCmdsCommand 入栈并立即执行每个子命令(子命令的 autoExecute=false 被忽略),且子命令不会注入 app(依赖 this.app 的自定义命令会抛错,executeAllCommands/executeManyCommands 同);只入栈不执行请逐个 addCommand |
| addManyCommands | 增加多个命令——⚠️ 同 addAllCommands:会立即执行各子命令,只入栈不执行请逐个 addCommand |
| undo | 撤销 |
| redo | 还原 |
UiModule
UI界面模块
| 方法名 | 描述 |
|---|---|
| addControl | 增加控件 |
| removeControl | 移除控件 |
| hasControl | 是否有控件 |
| setCursor | 设置光标 |
| getConfigPane | 获取配置面板 |
| logInfo | 信息弹窗提示 |
ParticleRenderModule
粒子效果模块
| 方法名 | 描述 |
|---|---|
| particleRenderer | 粒子渲染器 |
| addParticleSystem | 增加粒子系统 |
| addParticle | 增加粒子 |
| loadParticle | 从文件加载粒子场景 |
| loadParticleFromJson | 从JSON字符串中加载粒子场景 |
| loadParticleFromRes | 从资源加载粒子场景 |
| removeParticle | 移除粒子系统 |
PhysicsManagerModule
物理引擎模块
| 方法名 | 描述 |
|---|---|
| physicsEnable | 是否能用物理引擎 |
| physicsWorld | 得到物理引擎世界对象 |
| physicsEngine | 得到物理引擎对象 |
| enablePhysicsEngine | 启动物体引擎 |
| addPhysicsBody | 增加物理刚体 |
| removePhysicsObject | 通过实体或对象移除物理刚体 |
| addPhysicsGround | 增加一个物理地面 |
| setPhysicsDebugger | 设置物理引擎调试 |
生命周期补充
app.destroy():AppBase上的方法,仅停止渲染循环并置app.destroyed === true,不移除模块、不释放渲染器/canvas/window resize 监听。彻底销毁用app.dispose()(先removeAllModules()再destroy(),会renderer.dispose()并移除 canvas)。- App 没有
resize方法——画布尺寸只在 window 的resize事件(防抖)时按容器clientWidth/clientHeight更新,不监听容器元素本身(没有 ResizeObserver)。容器因布局变化(侧栏折叠、隐藏的 tab 变为显示)而 window 尺寸未变时不会自适应,需手动window.dispatchEvent(new Event('resize'))。 app.clearScenes():清空所有场景但不销毁 app。app.toJSON()(d.ts 存在但文档未列):对正常new App()实例直接调用抛Cannot convert undefined or null to object——序列化依赖的内部状态未就绪时不可用,调用前需自行 try/catch。