VoxelViewer API 参考
本页是 voxel-kit 2.14.14 中预览能力的完整公开 API 参考。它既可以当作字段字典,也可以在接入后按“组件 → Controller → Options → 视觉参数”的顺序阅读。Native 编译、PRVW 和 THMB 生成属于 Compiler API,不改变本页的 Viewer 调用方式。
只有本页列出的包根导出属于支持契约。VoxelJsonScene、VoxelSceneResult、ArkGraphics Scene / Camera / Mesh、TaskPool 输入和 bindStateListener() 都是实现细节;不要导入、保存或包装它们。
公开导出总览
| 类型 | 作用 | 什么时候使用 |
|---|---|---|
VoxelViewer | ArkUI 的实际 3D 可视组件 | 在页面 build() 中挂载 |
VoxelViewerController | 导入、查询、设置和释放的唯一入口 | 页面字段中创建并稳定复用 |
VoxelViewerOptions | 输入大小、手势、背景、动画、遮罩与纹理配置 | 创建 Controller 前和下次加载前 |
VoxelLoadAnimationMode | 六种载入动画 | 配置 animationMode |
VoxelBackgroundMode / VoxelBackgroundState | 背景的四种责任模式与 Builder 入参 | 用内置、可配置、Builder 或外部背景 |
VoxelLoadOverlayMode / VoxelLoadOverlayPhase / VoxelLoadOverlayState / VoxelLoadOverlayStyle | Loading 的四种责任模式、状态、样式 | 保留或替换 Loading UI |
VoxelLoadResult | 每次 load*() 成功后的摘要 | 更新作品信息、埋点或 UI |
VoxelPreviewError | 预留错误数据结构 | 当前加载入口不会 reject 此类型;使用普通 Error |
VoxelRenderTuning | 光照、色调、阴影、后处理和描边 | 做产品视觉调校 |
VoxelViewer
构造参数
VoxelViewer({
controller: this.controller,
backgroundBuilder: this.options.backgroundMode === VoxelBackgroundMode.BUILDER
? this.backgroundBuilder : undefined,
loadOverlayBuilder: this.options.loadOverlayMode === VoxelLoadOverlayMode.BUILDER
? this.overlayBuilder : undefined
})
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
controller | VoxelViewerController | 是 | 同一页面生命周期内稳定的 Controller。 |
backgroundBuilder | @Builder (state: VoxelBackgroundState) => void | 否 | 只有 backgroundMode = BUILDER 时生效,替换完整背景层。 |
loadOverlayBuilder | @Builder (state: VoxelLoadOverlayState) => void | 否 | 只有 loadOverlayMode = BUILDER 时生效,替换遮罩中的提示卡片。 |
Builder 不会取得 Scene、Camera、Mesh,也不能控制 Overlay 出现/消失的时机;前者由 Controller 管理,后者由 Viewer 状态机管理。背景或 Loading 需要使用父组件状态时,遵循 ArkUI @BuilderParam 规则将 Builder 包装成父组件可调用形式。
VoxelViewerController
创建与使用规则
private readonly options: VoxelViewerOptions = new VoxelViewerOptions();
private readonly controller: VoxelViewerController = new VoxelViewerController(this.options);
- Controller 必须在
build()外创建;ArkUI 重组不应改变它的身份。 - 一个 Controller 同时只发起一条导入链路。等待一个
load*()的 Promise 成功或失败后,再开始下一次。 dispose()后不要再次加载或重新挂载;重新进入页面时创建新的 Controller。
加载方法
loadText(text, sourceName = 'model.json')
const result: VoxelLoadResult = await this.controller.loadText(jsonText, 'house.json');
| 项目 | 说明 |
|---|---|
| 输入 | JSON 字符串。 |
| 限制 | UTF-8 编码后的字节数不得大于 options.maxJsonBytes(默认 15 MiB)。 |
| JSON 合同 | grid_size 是 1..128 整数;必须有 colors 与 data;数据按 data[z][y][x],展开长度为 grid_size³。. 表示空体素。 |
| 成功 | 返回 Promise<VoxelLoadResult>,格式为 JSON。 |
| 失败 | Promise reject 为普通 Error;同时更新 getLastError() 与 getStatus()。 |
适合已经在网络、数据库或 rawfile 中得到文本的情况。不要把超过 15 MiB 的 JSON 以“改大限制”当作性能方案;更大的资产应考虑 VFP 或业务侧的显式容量策略。
loadBytes(bytes, sourceName = 'model')
const bytes: ArrayBuffer = copy.buffer;
const result = await this.controller.loadBytes(bytes, 'castle.vfp');
| 项目 | 说明 |
|---|---|
| 输入 | JSON UTF-8 或 VFP 的完整 ArrayBuffer。 |
| 格式识别 | 前四字节是 VFPK 时走 VFP;否则按 UTF-8 JSON 处理。 |
| JSON 分支 | 仍受 maxJsonBytes 限制,并复用 loadText() 的合同。 |
| VFP 分支 | 支持 1.2/1.3;VFP 1.3 优先使用只读预览缓存路径。 |
| 空输入 | 直接 reject:体素文件为空。 |
这个入口会使业务侧和组件同时短暂持有完整字节。对于较大的 Picker 文件,优先使用 loadUri();对于包内 rawfile,复制 Uint8Array 后传入其独立 ArrayBuffer,不要把可被资源管理器复用的缓冲交给异步加载。
loadUri(uri, sourceName = '')
const result = await this.controller.loadUri(uris[0], 'from-picker.vfp');
| 项目 | 说明 |
|---|---|
| 输入 | DocumentPicker 返回的 URI,不是普通 POSIX 路径。 |
| 文件上限 | 64 MiB;JSON 即使经 URI 导入仍受 JSON 15 MiB 默认上限。 |
| 文件描述符 | HAR 在 Promise 完成前打开、读取并关闭;调用方不应自行打开/关闭同一 URI。 |
| 文件名 | sourceName 为空时尝试从 URI 最后一段取得;失败时使用 imported-model。 |
| VFP 1.3 | 优先随机读取 Header/Footer/DIR0/META/PAL0/PMSH 等首帧所需数据,不先读取完整 VOX0/VBUF。 |
这是系统 Picker 导入的首选入口。用户取消选择不是 loadUri() 的错误;应由宿主在 Picker 返回空数组时直接结束操作。
加载成功结果 VoxelLoadResult
try {
const result = await this.controller.loadBytes(buffer, 'asset.vfp');
console.info(`${result.sourceFormat} ${result.gridSize}³, ${result.voxelCount} voxels`);
} catch (error) {
console.error(error.message);
}
| 字段 | 类型 | 含义 |
|---|---|---|
sourceName | string | 本次成功提交的显示名称。 |
sourceFormat | string | JSON 或 VFP。 |
gridSize | number | 立方网格边长。 |
voxelCount | number | 非空体素数。 |
surfaceCount | number | 贪心合并后的表面面数,不是三角形数。 |
vfpCacheHit | boolean | VFP 是否使用了可用预览缓存;JSON 固定为 false。 |
结果表示“场景已提交给 Viewer”,不是全局进度、编辑准备完成或权威内容验证完成的证明。
状态查询
| 方法 | 返回 | 何时读取 | 说明 |
|---|---|---|---|
isLoading() | boolean | 自定义页面状态 | 解析和场景创建期间为真。 |
getStatus() | string | 显示辅助文字/诊断 | 面向用户的中文阶段文本,不是稳定机器枚举。 |
getLastError() | string | Promise reject 后 | 最近失败文本;新导入开始时清空。 |
getSourceName() | string | 已成功加载后 | 最近成功提交的显示名称。 |
getOptions() | VoxelViewerOptions | 想在原对象上改配置时 | 返回当前 Options 的同一引用;修改后仍调用 setOptions() 提交。 |
getRenderTuning() | VoxelRenderTuning | 想以当前值为基础调参时 | 返回当前对象引用;修改后调用 setRenderTuning()。 |
更新与释放
| 方法 | 示例 | 当前场景效果 | 下一次加载效果 |
|---|---|---|---|
setOptions(options) | controller.setOptions(options) | 背景和地面网格立即刷新;动画时长同步到场景 | 读取动画模式、开关、输入限制等配置 |
setRenderTuning(tuning) | controller.setRenderTuning(tuning) | 立即应用光照、后处理、阴影/描边 | 新场景继承同一套参数 |
setGroundGridVisible(visible) | controller.setGroundGridVisible(false) | 立即切换 XY 工作台网格 | 同时写回 Options |
setGestureLocks(locks) | controller.setGestureLocks(new VoxelGestureLockOptions(true)) | 立即拦截选择的用户输入类别 | 保留为当前锁定策略 |
setGestureLocked(locked) / setGesturesEnabled(enabled) | controller.setGestureLocked(true) | 一键锁定/恢复全部六类输入 | 不影响程序化相机命令 |
setCameraRotation(x, y, z) | controller.setCameraRotation(0.2, 0.8, 0) | 立即更新 X/Y/Z 相机旋转 | 保留到手动手势或重置 |
setCameraTranslation(x, y, z) | controller.setCameraTranslation(0, 1, 0) | 平移相机与焦点,保持缩放距离 | 保留到手动平移或重置 |
setCameraTransform(transform) | 见下方示例 | 同时更新旋转和平移 | 保留到手动手势或重置 |
resetCamera() | controller.resetCamera() | 恢复当前模型自动取景时的初始相机状态 | 无 |
dispose() | controller.dispose() | 取消延迟描边、结束载入动画并清除当前 Scene 引用 | 不可复用;新页面创建新 Controller |
getSceneResult() 和 bindStateListener() 虽然在类上可见,但前者返回内部类型,后者是 Viewer 使用的单槽刷新监听。业务调用会破坏组件刷新,不属于支持 API。
手势锁与程序化相机
import {
VoxelCameraTransform,
VoxelGestureLockOptions
} from 'voxel-kit';
// 仅冻结相机,不冻结体素编辑。
controller.setGestureLocks(new VoxelGestureLockOptions(true, true, true, false, false));
// X/Y/Z 为弧度:俯仰、方位、屏幕滚转。
// XYZ 平移为绝对场景坐标,镜头距离保持不变。
controller.setCameraTransform(new VoxelCameraTransform(0.24, 0.74, 0.06, 0, 0.4, 0));
// 锁定输入也不会阻止此重置。
controller.resetCamera();
VoxelGestureLockOptions 的 rotation、twoFingerRotation、pan、zoom、voxelEdit、boxSelection 分别控制六类手势。rotation 会同时锁定单指和 SELECT_BRUSH 桥接的双指旋转,twoFingerRotation 只锁后者。setGestureLocked(true) 等价于六项均为 true;setGesturesEnabled(false) 是其反向命名。getGestureLocks() 返回当前锁定项的安全副本;getCameraTransform() 返回 Controller 最近管理的相机值副本,但 2.14.3 为保持手势热路径流畅,不在手动旋转、平移或缩放结束时发布实时 Camera 快照。
直接机位控制不公开 ArkGraphics Camera;组件仍自行维护场景代际、动画和资源回收。rotationX 会限制在接近 ±90° 的安全范围;rotationZ 同步参与双指平移、点击射线和屏幕框选坐标,避免滚转后出现编辑命中偏移。
VoxelViewerOptions
载入与交互
| 字段 | 默认值 | 范围/生效时机 | 说明 |
|---|---|---|---|
animationMode | STACK | 下次加载读取 | 见下方六种动画。 |
playLoadAnimation | true | 下次加载读取 | false 时最终模型直接显示。 |
loadAnimationDurationMs | 1500 | 300–5000 ms;当前场景可同步 | 载入动画总时长。 |
showGroundGrid | true | 立即 | 显示模型下方按尺寸适配的 XY 网格。 |
orbitSensitivity | 1 | 0.1–3;立即 | 单指旋转灵敏度。 |
panSensitivity | 1 | 0.1–3;立即 | 双指平移灵敏度。 |
minZoomFactor | 0.08 | 0.01–1 | 最近距离,相对初始相机距离。 |
maxZoomFactor | 5 | 不小于最小值,最大 12 | 最远距离,相对初始相机距离。 |
gestureLocks | 全部 false | 创建 Controller 时读取;运行时请调用 setGestureLocks() | VoxelGestureLockOptions 初始策略。 |
autoRotate | false | 立即 | 自动绕体素 Z 轴旋转;载入动画和用户手势期间内部暂停推进。 |
autoRotateDurationMs | 5000 | 300–60000 ms;立即 | 自动旋转一整圈的时长,也会成为未显式指定 GIF durationMs 时的默认速度。 |
maxJsonBytes | 15 * 1024 * 1024 | 正数 | 仅限制 JSON UTF-8 字节数;不限制 VFP。 |
背景
| 字段 | 默认值 | 说明 |
|---|---|---|
darkBackground | false | 选择浅色或深色主题。 |
backgroundMode | BUILTIN_CUSTOM | BUILTIN、BUILTIN_CUSTOM、BUILDER、EXTERNAL 四种背景责任模式。 |
lightBackgroundTopColor / MiddleColor / BottomColor | #F4F7FB / #FFF8ED / #DCE6EF | 浅色主题三段渐变。 |
darkBackgroundTopColor / MiddleColor / BottomColor | #101827 / #23364A / #090E16 | 深色主题三段渐变。 |
backgroundImage | undefined | 在 BUILTIN_CUSTOM 中以宿主 Resource 替换渐变。 |
backgroundImageFit | ImageFit.Cover | 图片填充模式。 |
backgroundImageOpacity | 1 | 运行时限制 0–1。 |
backgroundImageOverlayColor | #00000000 | 盖在图片上的颜色,可作暗角/品牌染色。 |
backgroundImage 接受 $rawfile()、$r() 等由宿主解析的 ArkUI Resource,不接受文件路径或 URI。清空它会回到六色渐变。
描边资源与加载 UI
| 字段 | 默认值 | 说明 |
|---|---|---|
unitGridTexture | undefined | 在首次加载前设为宿主 HAP 的 $rawfile('voxel/voxel_grid.png')。静态 HAR 无法稳定自取该图像资源;留空仍可加载,但会回退到较慢的旧式独立描边 Geometry(这不是 VFP 的 BORD 区段)。 |
loadOverlayMode | BUILTIN | BUILTIN、BUILTIN_CUSTOM、BUILDER、EXTERNAL。 |
loadOverlayStyle | new VoxelLoadOverlayStyle() | 内置或 Builder 模式的外观与文案。 |
onLoadOverlayStateChanged | 空函数 | 每次 Loading 状态变更都收到 VoxelLoadOverlayState;EXTERNAL 模式由宿主据此显示自己的 UI。 |
VoxelLoadAnimationMode
| 枚举值 | 视觉语义 |
|---|---|
STACK | 逐层堆砌,默认。 |
SOFT | 柔和浮现。 |
RADIAL | 从中心向外扩散。 |
WAVE | 斜向波浪推进。 |
SPIRAL | 螺旋进入。 |
CONVERGE | 从屏幕外沿直线向中心汇聚。 |
动画路径、缓动曲线、批次数和临时 Geometry 是内部实现;Options 只承诺选择模式、是否播放和总时长。
Loading 状态、样式和 Builder
VoxelLoadOverlayState
| 字段 | 含义 |
|---|---|
phase | IDLE、IMPORTING、PREPARING、ANIMATING、ERROR 或 HIDDEN。 |
visible | HAR 认为遮罩是否应显示。 |
message | 当前用户可读状态文本。 |
errorMessage | 失败原因;非 ERROR 时通常为空。 |
这不是字节百分比或 TaskPool 进度 API。不要用阶段数量推算 0–100% 进度条。
VoxelLoadOverlayStyle
| 字段 | 默认值 | 作用 |
|---|---|---|
maskColor | #00000000 | 遮罩颜色。 |
cardColor | #F8FBFFDD | 状态卡片背景。 |
titleColor / errorColor | #425572 / #C2413B | 普通/错误文本颜色。 |
loadingIndicatorColor | #4A7DF3 | 载入指示器颜色。 |
fontSize / errorFontSize | 14 / 12 | 文本字号。 |
borderRadius | 16 | 卡片圆角。 |
horizontalPadding / verticalPadding | 18 / 16 | 卡片内边距。 |
animationTopMargin | 14 | 动画状态内容的上边距。 |
showLoadingIndicator | true | 是否显示内置载入指示器。 |
useControllerStatus | true | 为真时优先使用 Controller 的具体状态文本。 |
idleText | 导入方法提示 | IDLE 文案。 |
loadingText / preparingText / animationText | 默认中文文案 | useControllerStatus = false 时的阶段文案。 |
errorPrefix | 导入失败: | 错误文案前缀。 |
四种 Loading 责任模式
| 模式 | HAR 做什么 | 宿主做什么 |
|---|---|---|
BUILTIN | 遮罩、卡片、状态、错误全内置 | 无。 |
BUILTIN_CUSTOM | 保留内置结构 | 设 loadOverlayStyle 后调用 setOptions()。 |
BUILDER | 管理遮罩可见性和 maskColor | 提供 loadOverlayBuilder(state) 替换卡片内容。 |
EXTERNAL | 不渲染任何 Loading/错误 UI | 在 onLoadOverlayStateChanged 中更新宿主 @State。 |
背景 Builder 状态
VoxelBackgroundState 目前只有 darkBackground: boolean。Builder 应根据它绘制自己的浅/深视觉,并铺满 Viewer 可用区域。设置 backgroundMode = EXTERNAL 时,不传 Builder;由父 Stack 绘制背景,Viewer 背景透明。
VoxelRenderTuning
创建新对象或修改 getRenderTuning() 的对象后,都需调用 setRenderTuning() 才会提交给当前场景。
const tuning = this.controller.getRenderTuning();
tuning.exposure = 0.95;
tuning.keyIntensity = 1.0;
tuning.fillIntensity = 0.14;
tuning.voxelBordersVisible = true;
this.controller.setRenderTuning(tuning);
| 分类 | 字段与默认值 | 调整建议 |
|---|---|---|
| 色调映射 | toneMappingMode = 0;0=ACES、1=ACES_2020、2=FILMIC | 固定映射后再调曝光,避免同时改变两者。 |
| 曝光 | exposure = 0.82 | 整体偏暗先小幅提高它。 |
| 环境 | ambientDiffuse = 0.88、ambientSpecular = 0.48、ambientTemperature = 0 | 主体发灰先检查环境漫反射,冷暖建议在 -1..1 小范围调整。 |
| 主光 | keyIntensity = 0.84、keyAzimuth = 37、keyElevation = 41、keyTemperature = 0 | 决定主要明暗面;方位/仰角单位为度。 |
| 补光 | fillIntensity = 0.10、rimIntensity = 0.18、bottomIntensity = 0.06 | 用于托起阴面与轮廓,避免用过高环境光消除立体感。 |
| Bloom | bloomThresholdHard = 1.20、bloomThresholdSoft = 0.78、bloomScaleFactor = 0.42、bloomScatter = 0.10 | 只用于亮部气氛,不能用它弥补低曝光。 |
| 镜头 | vignetteIntensity = 0、vignetteRoundness = 0.70、colorFringeIntensity = 0 | 默认尽量中性;大值会削弱资产真实颜色。 |
| 阴影 | shadowsEnabled = true、shadowReceiverEnabled = true、shadowResolution = 2048 | 关闭前先明确性能/视觉目标;提高分辨率会增加显存与原生资源开销。 |
| 描边 | voxelBordersVisible = true | 统一控制 PBR 网格与兼容 BORD 描边显示。 |
推荐只一次调整一组:先曝光与主光,再补光与阴影,最后才是 Bloom/暗角。每次调参应至少在浅色、深色与黑色体素资产上做真机检查。