【征文计划】Rokid JSAR 实践指南:打造沉浸式 "声动空间盒" 交互体验

【征文计划】Rokid JSAR 实践指南:打造沉浸式 "声动空间盒" 交互体验

概述

本文基于 Rokid JSAR 框架,从开发者视角完整复现一个具备听觉与视觉交互的空间应用 "声动空间盒"。项目通过 多音阶音频播放、3D 立方体纹理渲染、GUI 按钮交互 等模块,实现了在三维空间中可视化、可点击、可听见的沉浸式体验。开发过程中结合 Babylon.js 渲染管线与 JSAR 空间文档结构,展示了如何以 Web 前端思维快速构建 AR 场景内容,让"空间小程序"真正还原 Web 开发的所见即所得理念。

项目概述:声动空间盒交互体验

1、素材图片准备

2、音频准备

音频模块:多音阶播放逻辑设计

createAudioPlayer 函数:通过导入音频文件获 arrayBuffer、封装为 audio/mpeg 格式 Blob、生成临时 URL,返回可创建 Audio 实例播放、且支持 volume 参数调音量的播放函数

预加载处理:用立即执行异步函数,提前加载 Do、Ri、Mi、Fa音频文件并存储于 audios 对象,供后续点击按钮直接调用

js 复制代码
async function createAudioPlayer(name: string) {
  const arrayBuffer = await import(`../audio/${name}`);
  const blob = new Blob([arrayBuffer], { type: 'audio/mpeg' });
  const objectUrl = URL.createObjectURL(blob);
  return (volume?: number) => {
    const audio = new Audio(objectUrl);
    if (volume) {
      audio.volume = volume;
    }
    audio.play();
  };
}

const audios = {} as Record<string, (volume?: number) => void>;
(async function() {
  audios['Do'] = await createAudioPlayer('40.mp3');
  audios['Ri'] = await createAudioPlayer('42.mp3');
  audios['Mi'] = await createAudioPlayer('44.mp3');
  audios['Fa'] = await createAudioPlayer('45.mp3');
})();
纹理定制:立方体表面视觉增强

获取 ID 为 box1 的 3D 立方体;加载砖块纹理图 brickwork.jpeg 转为位图,通过离屏画布先绘黄色矩形再叠加砖块图,提取像素数据生成 Babylon 纹理 wallTexture(配置格式、采样模式等),最后将其设为立方体材质的漫反射纹理,完成外观定制。

js 复制代码
const wall = spatialDocument.getSpatialObjectById('box1');
createImageBitmap(new Blob([wallPic], { type: 'image/jpeg' })).then((bitmap) => {
  const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
  const ctx = canvas.getContext('2d');

  ctx.fillStyle = 'yellow';
  ctx.fillRect(0, 0, 200, 100);

  ctx.drawImage(bitmap, 0, 0);
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const wallTexture = new BABYLON.RawTexture(
    imageData.data,
    imageData.width,
    imageData.height,
    BABYLON.Engine.TEXTUREFORMAT_RGBA,
    spatialDocument.scene,
    false,
    false,
    BABYLON.Texture.TRILINEAR_SAMPLINGMODE);

  const wallMaterial = wall.asNativeType<BABYLON.Mesh>().material as BABYLON.StandardMaterial;
  wallMaterial.diffuseTexture = wallTexture;
});
界面交互:3D GUI 按钮与事件绑定

获取 ID 为 gui 的 3D 平面对象,其 shadowRoot 作为 GUI 容器;选中所有 sub 类元素对应 DoRi 等,设置尺寸背景色等样式形成按钮;绑定事件:鼠标进入变深紫、离开恢复深灰、点击时暂变深色并按文本从 audios 取对应函数播放音频音量 1.0;调用 spatialDocumentwatchInputEvent 监听空间输入,确保 3D 场景鼠标交互生效

js 复制代码
const guiPlane = spatialDocument.getSpatialObjectById('gui');
const panel = guiPlane.shadowRoot;

const subChildren = panel.querySelectorAll('.sub');
for (let sub of subChildren) {
  const subElement = sub as HTMLElement;
  subElement.style.backgroundColor = 'rgba(20,33,33,.95)';
  subElement.style.height = '200px';
  subElement.style.width = '300px';
  subElement.style.marginLeft = '50px';
  subElement.style.fontSize = '80px';
  subElement.style.color = '#fff';
  subElement.style.textAlign = 'center';
  subElement.style.border = '15px solid yellow';
  subElement.style.borderRadius = '50px';
  subElement.style.paddingTop = '20px';

  subElement.addEventListener('mouseenter', () => {
    subElement.style.backgroundColor = 'rgba(100,0,120,.95)';
  });
  subElement.addEventListener('mouseleave', () => {
    subElement.style.backgroundColor = 'rgba(60,33,33,.95)';
  });
  subElement.addEventListener('mouseup', () => {
    subElement.style.backgroundColor = 'rgba(30,33,33,.95)';
    const playAudio = audios[subElement.textContent];
    if (playAudio) {
      playAudio(1.0);
    }
  });
}
spatialDocument.watchInputEvent();

场景容器:3D 可视化空间渲染核心

立方体元素:空间物体与样式绑定

cube 标签创建一个 3D 立方体,id=box1 与头部样式中的 #box1 关联,会自动应用样式中定义的位置、旋转和材质;size=0.8 是基础尺寸,width=1.4 即 X 轴长度、depth=0.2 即 Z 轴厚度,额外调整立方体的长宽厚,最终呈现一个扁长形的粉紫色立方体。

js 复制代码
<space>
  <!-- 立方体:ID为box1,对应style中#box1的配置 -->
  <cube id="box1" size="0.8" width="1.4" depth="0.2"></cube>
  <!-- 其他3D元素... -->
</space>

平面元素:GUI 面板与布局结构

plane 标签创建的元素 id=gui,与头部样式中的 #gui 关联,会应用缩放和旋转配置,成为 3D 空间中承载 GUI 的 "面板";内部的 div id=root 是 GUI 的容器,用内联样式(padding:10px、gap:20px)控制内部元素的间距;两个 span 分别承载:4 个带 class="sub" 的音阶文本;白色大字体的说明文字,直接点明项目核心 ,还原 Web 开发体验,所见即所得

js 复制代码
<plane id="gui">
  <!-- 平面内部的GUI容器:用div组织内容,设置内边距和间距 -->
  <div id="root" style="padding:10px;gap:20px;">
    <!-- 第一行:4个音阶按钮(class="sub",后续脚本会绑定点击事件) -->
    <span>
      <span class="sub">Do</span>
      <span class="sub">Ri</span>
      <span class="sub">Mi</span>
      <span class="sub">Fa</span>
    </span>
    <!-- 第二行:说明文字 -->
    <span style="color:white;font-size:70px;line-height:1.3;">
      空间小程序还原最开始的 Web 开发体验,并所见即所得。
    </span>
  </div>
</plane>

效果展示:3D 场景视觉与交互呈现

呈现出一个 3D 面板,面板上有 Do、Ri、Mi、Fa等带样式的按钮,下方配有文字空间小程序,还原最开始的 Web 开发体验,并非所想即所得。整体营造出在 3D 空间中展示交互界面与相关说明的效果,似乎是在演示空间小程序里类似 Web 开发相关的交互与呈现

AR 调试:本地服务器与浏览器运行

1、web浏览器查看(用 serve 工具启动一个本地服务器,将端口指定为 8080,并开启跨域资源共享(CORS)功能,方便在开发中处理跨域请求)

bash 复制代码
serve -p 8080 --cors

2、浏览器看到项目目录即为服务器启动成功

3、浏览器访问如下地址

bash 复制代码
https://m-creativelab.github.io/jsar-dom/?url= http://localhost:8080   

总结

本项目以 Rokid JSAR 框架为核心,完整展示了从 空间文档结构构建、音频逻辑编程、纹理渲染到 GUI 交互绑定 的全链路开发流程。通过 Web 前端的直观方式,开发者不仅能快速实现 AR 空间中的多模态交互,还能以熟悉的 DOM 思维探索空间计算的无限可能。"声动空间盒" 不仅是一场技术实验,更是 Web 技术与空间计算融合的实践样本,它让开发者在三维世界中看得见代码的节奏,听得见交互的回响。

相关推荐
BBB努力学习程序设计3 小时前
CSS Sprite技术:用“雪碧图”提升网站性能的魔法
前端·html
BBB努力学习程序设计3 小时前
CSS3渐变:用代码描绘色彩的流动之美
前端·html
冰暮流星3 小时前
css之动画
前端·css
jump6804 小时前
axios
前端
spionbo4 小时前
前端解构赋值避坑指南基础到高阶深度解析技巧
前端
用户4099322502124 小时前
Vue响应式声明的API差异、底层原理与常见陷阱你都搞懂了吗
前端·ai编程·trae
开发者小天4 小时前
React中的componentWillUnmount 使用
前端·javascript·vue.js·react.js
永远的个初学者4 小时前
图片优化 上传图片压缩 npm包支持vue(react)框架开源插件 支持在线与本地
前端·vue.js·react.js
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ4 小时前
npm i / npm install 卡死不动解决方法
前端·npm·node.js
Kratzdisteln4 小时前
【Cursor _RubicsCube Diary 1】Node.js;npm;Vite
前端·npm·node.js