跳转到内容

3D内容放置屏幕

相关参考:

把 3D 内容“放到屏幕上”是可以实现的,但更准确地说,这不是单独的一条专用 API,而是通过把对象挂到相机下面来实现。

核心思路如下:

js
const camera = await api.getDefaultCamera();
await api.addChild(camera, obj);

这样对象会跟随相机一起移动和旋转,视觉上就会更接近“固定在屏幕前方”。

更推荐的方案:宿主层叠加 UI

如果你的目标是典型 HUD 或固定 UI,仍然更推荐:

  1. 宿主页面自己做一层 HTML/CSS UI
  2. Kivicube iframe 只负责 3D/AR 内容

这种方式更适合:

  • 标题
  • 按钮
  • 说明文字
  • 引导箭头
  • 响应式布局

原因也很直接:

  • 更容易做多端适配
  • 更容易和宿主页面样式统一
  • 更容易点击、埋点、做动画
  • 不需要反复调 3D 坐标

什么时候适合用 3D 对象贴屏

更适合下面这类内容:

  • 希望它仍然是一个 3D 对象
  • 需要参与场景内的材质、光照或透明效果
  • 想做“漂浮在镜头前方”的 3D 装饰
  • 想让它继续复用已有对象动画或模型资源

基本实现方式

1. 获取相机和目标对象

js
const camera = await api.getDefaultCamera();
const obj = await api.getObject('screen-object');

如果对象是你运行时创建的,也可以直接使用创建返回的句柄:

js
const obj = await api.createImage('/assets/tag.png');

2. 挂到相机下面

js
await api.addChild(camera, obj);

3. 调整对象在相机坐标系下的位置

js
await api.setPosition(obj, 0, 0, -2);
await api.setScale(obj, 0.5, 0.5, 0.5);

这里最关键的是 z

  • z 一般要放在负方向,表示放到镜头前方
  • 数值越接近 0,看起来越贴近屏幕
  • 数值越小,看起来越远

xy 则决定它在屏幕中的左右和上下位置。

例如:

js
// 居中偏下
await api.setPosition(obj, 0, -0.6, -2);

// 左上角附近
await api.setPosition(obj, -1.2, 0.8, -2);

4. 修改渲染状态

js
// 使物体始终最上层显示,取消渲染时的深度测试,以及对深度缓冲区的影响
const recursive = true; // 是否同时设置所有子节点。默认为false
await api.setGLState(obj, "depthTest", false, recursive);
await api.setGLState(obj, "depthWrite", false, recursive);

一个完整示例

js
iframe.addEventListener('ready', async (event) => {
  const { api } = event.detail;

  const camera = await api.getDefaultCamera();
  const image = await api.createImage('/assets/floating-badge.png');

  await api.addChild(camera, image);

  await api.setPosition(image, 1.1, -0.8, -2);
  await api.setScale(image, 0.35, 0.35, 0.35);

  const recursive = true;
  await api.setGLState(obj, "depthTest", false, recursive);
  await api.setGLState(obj, "depthWrite", false, recursive);
});

取消贴屏

如果后面不想继续挂在相机下,可以移除父子关系,再重新挂回其他对象:

js
await api.removeChild(camera, obj);

如果只是想隐藏:

js
await api.setObjectVisible(obj, false);

适配建议

虽然这种方案可以实现“贴屏”,但它仍然是 3D 坐标,不是 CSS 像素坐标。因此:

  • 不同屏幕比例下,位置可能需要微调
  • 不同 FOV 下,视觉位置也会变化
  • 过于靠近镜头时,容易显得过大或裁切异常

更稳妥的方式是:

  • 固定一套基础坐标
  • 在关键机型上做少量微调
  • 把真正的交互按钮仍放在宿主层 HTML 中

什么时候不建议用这种方式

  • 需要精确对齐宿主页面按钮
  • 需要复杂响应式布局
  • 需要大量文字内容
  • 需要稳定的点击热区
  • 需要和页面滚动、弹层、表单联动

这种情况下,HTML/CSS 会比 3D 方案更适合。