前言
在 AR 开发领域,传统方案常面临 "技术栈割裂" 问题 ------3D 渲染需学 Unity/Unreal,AR 空间感知需懂 SLAM 底层,Web 开发者难以快速切入。而 Rokid JSAR 的核心突破,是通过 "空间化 Web 技术" 将 AR 能力封装为 Web 开发者熟悉的 API,其中 "空间对象与交互融合技术" 是支撑上层应用(如本文 AR 钢琴音按钮项目)的核心骨架。
该技术的核心定位是:以 Web 标准 为基础,将 "空间 3D 对象""2D GUI 界面""多模态资源(音频/纹理)" 统一纳入 "空间文档(spatialDocument)" 管理,让开发者用 HTML/CSS/JS + 轻量化 3D 引擎(如 Babylon.js) 即可实现 AR 交互功能。本文将结合 AR 钢琴音按钮项目(点击空间 GUI 按钮触发对应钢琴音,立方体加载自定义纹理),拆解该技术的核心原理、源码调用逻辑与实践要点。

Rokid JSAR 是什么
JSAR 是一款 可嵌入空间的 Web 运行时 ,它支持开发者使用 JavaScript/TypeScript、Web-standard APIs 等熟悉的 Web 技术栈,结合 Babylon.js 等 3D 引擎 ,通过 Visual Studio Code 即可开发 可嵌入空间的空间小程序 (空间组件形式可多样,如 3D 物体、2D 界面或带 GUI 的 3D 物体 ),还能嵌入 Unity 场景运行;其核心目标是 保障空间组件运行时的隔离性 、降低 Web 开发者进入 AR 开发领域的学习成本 、优化空间组件的离线体验与性能以打破对 Web 技术的刻板印象 ,适用于 YodaOS-Master 开发者开发 桌面小摆件(如宠物、地球仪) 、2D+3D 结合场景(如地图助手、商品展示) (尤其适合 有 Web 开发经验者 ),但不适用于开发 独立空间应用、大型游戏及追求封闭体验的项目。
官方文档: http://jsar.netlify.app/manual/latest/introduction

JSAR 基础环境搭建
打开 VS Code 软件,打开插件市场安装项目运行所需要的插件
- 安装 JSAR Devtools 插件: SAR Devtools 是专为 Rokid JSAR 项目设计的 Visual Studio Code 插件,提供全链路开发支持,覆盖从代码编写到真机调试的完整流程,尤其针对 AR 场景的空间化交互与性能优化需求
- 安装 glTF Tools: glTF Tools 是一套处理 glTF/GLB 格式 3D 模型的工具链,支持在 JSAR 开发环境中实现模型预览、优化及简单编辑。

AR 钢琴音按钮**项目源码深度解析**
该项目是一个基于 Rokid JSAR 框架的轻量化 AR 应用,核心功能是在虚拟空间中创建可交互的音乐按钮面板,通过点击不同按钮播放对应音符,同时展示 3D 物体纹理渲染能力。整个项目从文件结构到代码实现,充分体现了"用 Web 技术栈开发 AR 应用"的核心优势,以下结合具体代码进行详细解析。
一、项目结构与依赖管理:Web 工程化的直接复用
项目采用标准 Web 前端工程结构,通过 package.json
和 package-lock.json
管理依赖,核心配置如下:
json
// package.json 核心配置
{
"name": "your-jsar-widget-name",
"main": "main.xsml", // 入口文件为 XSML(Rokid JSAR 场景描述文件)
"devDependencies": {
"@yodaos-jsar/types": "^0.2.0-alpha.5" // JSAR 类型声明,提供 API 类型提示
},
"files": ["main.xsml", "lib/*.ts", "model/welcome.glb"] // 打包包含的核心文件
}
技术特点:
- 依赖管理完全复用 npm 生态,Web 开发者无需学习新的包管理工具
- 通过
@yodaos-jsar/types
获得 TypeScript 类型支持,保持与传统 Web 开发一致的类型安全体验 - 入口文件指定为
main.xsml
,体现 Rokid JSAR 对 HTML 的扩展------在保留 Web 语法的基础上增加空间描述能力
二、场景定义:XSML 对 HTML 的空间化扩展(main.xsml)
main.xsml
是 Rokid JSAR 特有的场景描述文件,融合了 HTML 语法与 3D 空间定义,代码解析如下:
xml
<xsml version="1.0">
<head>
<title>GUI Buttons</title>
<style type="text/scss"> <!-- 支持 SCSS 语法,复用 Web 样式体系 -->
@material litered { <!-- 定义 3D 物体材质,扩展 CSS 语法用于空间物体 -->
diffuse-color: #ffccff;
}
#gui { <!-- 空间 UI 面板的位姿配置 -->
scaling: 1.2 1 1; <!-- 缩放参数(x,y,z) -->
rotation: 0 160 0; <!-- 旋转角度(x,y,z 轴) -->
}
#box1 { <!-- 3D 立方体的空间属性 -->
position: 0.2 0.3 -0.1; <!-- 空间坐标(x,y,z) -->
rotation: 0 160 0;
material: "litered"; <!-- 关联上述定义的材质 -->
}
</style>
<script type="module" src="lib/main.ts"></script> <!-- 引入 TypeScript 逻辑文件 -->
</head>
<space> <!-- 3D 空间容器,定义 AR 场景中的实体 -->
<cube id="box1" size="0.8" width="1.4" depth="0.2"></cube> <!-- 3D 立方体 -->
<plane id="gui"> <!-- 承载 2D UI 的平面 -->
<div id="root" style="padding:10px;gap:20px;"> <!-- 标准 HTML 结构 -->
<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;"> <!-- 文本说明 -->
空间小程序还原最开始的 Web 开发体验,并所见即所得。
</span>
</div>
</plane>
</space>
</xsml>
核心技术解析:
- 语法兼容 :保留
<head>
、<style>
、<script>
等 HTML 核心标签,同时扩展<space>
、<cube>
、<plane>
等 3D 空间标签,让 Web 开发者零成本上手 - 样式扩展 :在 CSS 基础上增加
@material
定义 3D 材质,通过position
、rotation
等属性控制空间位姿,实现"用 CSS 思维管理 3D 物体" - UI 融合 :
<plane>
标签作为"空间画布",内部直接嵌套标准 HTML 元素(<div>
、<span>
),实现 2D Web 界面与 3D 空间的无缝结合------开发者可像写网页一样设计 AR 界面
三、核心逻辑实现:Web API 与 AR 能力的深度结合(main.ts)
main.ts
是项目逻辑核心,通过 TypeScript 实现音频加载、纹理渲染、交互响应等功能,全程复用 Web 原生 API 与 Rokid JSAR 扩展能力:
3.1 音频资源加载与管理:Web 多媒体 API 的直接应用
tsx
// 音频加载函数:通过 Web 原生 API 处理音频资源
async function createAudioPlayer(name: string) {
// 动态导入音频文件(复用 ES Module 特性)
const arrayBuffer = await import(`../audio/${name}`);
// 用 Blob 处理二进制数据(Web 标准 API)
const blob = new Blob([arrayBuffer], { type: 'audio/mpeg' });
// 生成可播放的 URL(Web 原生 URL API)
const objectUrl = URL.createObjectURL(blob);
// 返回带音量控制的播放函数
return (volume?: number) => {
const audio = new Audio(objectUrl); // 原生 Audio 对象
if (volume) {
audio.volume = volume;
}
audio.play(); // 调用原生播放方法
};
}
// 初始化音频映射表(Do/Ri/Mi/Fa 对应不同音频)
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');
})();
技术亮点:
- 完全基于 Web 标准 API(
import()
、Blob
、URL.createObjectURL
、Audio
)实现音频加载与播放,无需学习 AR 专属多媒体接口 - 通过对象映射(
audios
)管理不同音符与音频的对应关系,逻辑清晰,复用前端"资源池"设计思想
3.2 3D 物体纹理渲染:Web 图像处理与 3D 引擎的结合
tsx
// 加载纹理图片(支持本地图片切换)
// import wallPic from '../textures/brickwork.jpeg';
import wallPic from '../textures/123.png';
// import wallPic from '../textures/volin.jpeg';
// 获取 3D 立方体对象(Rokid JSAR 扩展 API)
const wall = spatialDocument.getSpatialObjectById('box1');
// 处理图片并设置为立方体纹理
createImageBitmap(new Blob([wallPic], { type: 'image/jpeg' })).then((bitmap) => {
// 创建离屏画布(Web 原生 API,用于图像处理)
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);
// 创建 Babylon.js 纹理(Web 3D 引擎与 JSAR 结合)
const wallTexture = new BABYLON.RawTexture(
imageData.data,
imageData.width,
imageData.height,
BABYLON.Engine.TEXTUREFORMAT_RGBA,
spatialDocument.scene, // JSAR 提供的场景对象
false,
false,
BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
// 将纹理应用到立方体材质
const wallMaterial = wall.asNativeType<BABYLON.Mesh>().material as BABYLON.StandardMaterial;
wallMaterial.diffuseTexture = wallTexture;
});
核心逻辑:
- 图片处理 :通过 Web 原生
OffscreenCanvas
、CanvasRenderingContext2D
处理图像(绘制矩形、合成图片),复用前端 Canvas 绘图经验 - 3D 纹理转换 :借助 Babylon.js(主流 Web 3D 引擎)将 2D 图像数据转换为 3D 纹理,Rokid JSAR 提供
spatialDocument.scene
作为桥梁,实现"Web 图像处理 → 3D 纹理"的无缝衔接 - 灵活性:通过注释切换不同图片资源,体现 Web 开发中"资源模块化"的优势,便于快速迭代纹理效果
3.3 交互逻辑:DOM 事件系统在 AR 空间的复用
tsx
// 获取承载 UI 的平面对象
const guiPlane = spatialDocument.getSpatialObjectById('gui');
// 获取平面的影子 DOM(类似 Web Component 的 shadowRoot)
const panel = guiPlane.shadowRoot;
// 获取所有音符按钮(标准 DOM 选择器)
const subChildren = panel.querySelectorAll('.sub');
for (let sub of subChildren) {
const subElement = sub as HTMLElement;
// 设置按钮样式(标准 CSS 操作)
subElement.style.backgroundColor = 'rgba(20,33,33,.95)';
subElement.style.height = '200px';
subElement.style.width = '300px';
// ... 省略其他样式设置 ...
// 鼠标进入事件(原生 DOM 事件)
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);
}
});
}
// 启动空间输入事件监听(JSAR 扩展 API)
spatialDocument.watchInputEvent();
关键技术点:
- DOM 操作复用 :通过
querySelectorAll
选择元素、addEventListener
绑定事件、style
属性修改样式,完全复用前端 DOM 操作经验,实现 AR 界面的交互逻辑 - 事件系统桥接 :
spatialDocument.watchInputEvent()
将 AR 空间中的输入(如眼镜凝视、手势点击)映射为标准 DOM 事件(mouseenter
、mouseup
),让开发者无需理解 AR 输入原理,直接使用熟悉的事件模型 - 数据联动 :通过按钮文本(
subElement.textContent
)关联音频映射表,实现"UI 交互 → 业务逻辑(播放音频)"的闭环,逻辑清晰易维护
运行项目
准备所需要的项目和资源文件

通过插件来查看项目实现效果

具体效果如下(点击按钮会发出钢琴声响):



技术价值总结
从 AR 钢琴音按钮项目的实践来看,Rokid JSAR 的 "空间对象与交互融合技术 本质是 "将 AR 开发 Web 化,其核心价值体现在三点:
- 技术栈无门槛:Web 开发者无需学习 Unity/Unreal,用 HTML(XSML)、CSS、JS 即可开发 AR 应用,项目中 GUI 样式、音频加载、DOM 事件均为 Web 原生逻辑;
- 底层能力封装化 :SLAM 空间定位、3D-AR 坐标对齐、空间输入判定等底层工作,全部由
<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0.06);">spatialDocument</font>
等 JSAR API 封装,开发者聚焦上层功能(如 "按钮触发音频""纹理渲染"); - 生态兼容性强:无缝兼容 Babylon.js、Three.js 等轻量化 3D 引擎,以及 Web 原生的资源加载、DOM 交互、音频播放能力,无需重构现有 Web 技术栈。
对于开发者而言,这个技术不仅能快速落地 AR 创意项目(如本文的钢琴音按钮、教育类 AR 笔记、AR 导航),更能基于 Web 生态的灵活性,快速迭代功能(如给项目增加 "多组琴键""空间音效"),真正实现 "AR 开发平民化"。