【征文计划】JSAR实战:从零开始的空间小程序开发之旅
文章目录
- 什么是JSAR?为什么选它?
- 环境搭建 - 踩坑记录
- 安装Node.js(版本要求18+)
- 安装VS Code和JSAR DevTools插件
- 安装 Visual Studio Code
- 安装JSAR DevTools插件
- 创建项目
- 项目结构解析
- 运行和调试项目
- VS Code 扩展运行
- 常见问题及解决方案
- 场景视图没有3D渲染
- 从vsix安装扩展报错
- Web 浏览器预览
- 深入XSML - 空间标记语言
- XSML基础语法
- space(空间容器)
- mesh(网格引用)
- cube(立方体)
- plane(平面)
- sphere(球体)
- cylinder(圆柱体)
- capsule(胶囊体)
- torus(圆环体)
- bound(边界元素,Bounding Box)
- 打包和部署
- 项目打包
- 包大小优化
- 真机调试
- 总结
什么是JSAR?为什么选它?
JSAR是可嵌入空间的 Web 运行时,它支持开发者使用类似于 Web 的技术来开发可嵌入空间的空间小程序。它可以帮助你将 Web 技术嵌入到某个空间场景中独立运行。
简单理解就是:
- 传统小程序:在手机屏幕上的2D界面
- 空间小程序:在3D空间中的立体应用
选择JSAR的原因很简单:
- 学习成本低:我已经会JavaScript/TypeScript了
- 开发速度快:不用学C#,不用研究复杂的Unity组件系统
- 调试方便:可以在VS Code里直接开发和预览
- 部署简单:最终输出的是Web技术栈,易于分发
简单来说,如果你已经是一个Web开发者,JSAR让你几乎零门槛进入空间计算领域。
环境搭建 - 踩坑记录
安装Node.js(版本要求18+)
前往Node.js官网下载LTS版本。安装完后验证一下:
node -v # 应该显示 v18.x.x 或更高
npm -v # 显示npm版本
安装VS Code和JSAR DevTools插件
安装 Visual Studio Code
如果你已经安装了VS Code,可以跳过这一步。如果没有安装,前往 VS Code官网 下载安装。
注意:确保VS Code版本 >= 1.80.0
安装JSAR DevTools插件
- 下载最新的.vsix安装包:RokidMCreativeLab.vscode-jsar-devtools-0.2.0.vsix
- 打开VS Code
- 按
Ctrl + Shift + P
,输入 “Extensions: Install from VSIX…” - 选择下载的.vsix文件
- 重启VS Code
创建项目
# 初始化项目
npm init @yodaos-jsar/widget# 安装依赖
npm install
脚手架会自动:
- 下载最新的模版项目 M-CreativeLab/template-for-jsar-widget
- 根据你的输入更新package.json
- 创建基本的项目结构
运行成功后,会获得一个 package.json
项目结构解析
初始化完成后,你会得到这样的目录结构:
让我们看看关键文件的内容:
main.xsml(空间标记语言):
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="model" ref="model" selector="__root__" /></space>
</xsml>
lib/main.ts(TypeScript逻辑):
const scene = spaceDocument.scene as BABYLON.Scene;
const animationGroups = scene.animationGroups.filter((ag) => ag.name.endsWith('#model'));if (animationGroups.length >= 1) {animationGroups[0].start(true);
}
运行和调试项目
VS Code 扩展运行
- 打开XSML文件:在VS Code中打开任何
.xsml
文件 - 启动场景视图:点击右上角的场景视图按钮
- 开始调试:场景视图会自动加载你的3D应用
场景视图提供两个实用功能:
- 重置位置:将场景视图重置到原点
- 刷新:重新加载场景视图
修改代码时,场景视图会自动刷新,实现热重载。
常见问题及解决方案
场景视图没有3D渲染
解决方法:
- 打开VS Code设置
- 搜索"扩展"
- 勾选"将扩展应用于所有配置文件"
从vsix安装扩展报错
如果遇到 No view is registered with id: jsar-devtools.sceneObjectsHirarchy
错误,可能是VS Code的旧视图布局中ID冲突。
解决方法:
- 按
Ctrl/Cmd + Shift + P
- 执行
View: Reset View Locations
- 执行
Developer: Reload Window
Web 浏览器预览
JSAR还提供了在线Playground,让你在浏览器中直接测试应用:
https://jsar.netlify.app/playground?url={你的XSML地址}
GitHub项目示例:
https://jsar.netlify.app/playground?url=https://raw.githubusercontent.com/M-CreativeLab/jsar-gallery-rokid-jungle/main/main.xsml
本地项目预览:
- 安装serve工具:
npm install serve -g
- 在项目目录启动HTTP服务:
serve -p 8080 --cors
- 验证服务运行:访问
http://localhost:8080/main.xsml
,应该返回:
- 在Playground中预览:
https://jsar.netlify.app/playground?url=http://localhost:8080/main.xsml
深入XSML - 空间标记语言
XSML基础语法
XSML(eXtended Spatial Markup Language)是JSAR的核心,它扩展了传统的HTML概念到3D空间。
基本结构:
<xsml version="1.0"><head><title>Rokid Jungle</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="model" ref="model" selector="__root__" /></space>
</xsml>
space(空间容器)
- 用途:定义 XSML 的三维空间根节点/容器。
- 子元素:mesh、cube、plane、sphere、cylinder、capsule、torus、bound,以及(未在此文展开的)cone、text、image、video、audio 等。
mesh(网格引用)
用于把 <head>
中 <link>
引入的 3D 模型渲染到空间里。
属性 | 类型 | 说明 |
---|---|---|
id | string | 网格元素的唯一标识符。 |
ref | string | 引用的外部资源 ID,目前仅支持 model。对应 <head><link id="..."> 。 |
selector | string | 在被引用的模型中选择具体节点(选择器字符串)。 |
用法要点:通过 ref 指向已经通过 <link>
引入的模型资源;selector 用于精确到模型中的某个节点。
cube(立方体)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
width | number | 宽度。 |
height | number | 高度。 |
depth | number | 深度。 |
size | number | 统一尺寸的便捷属性(等边立方体)。 |
用法要点:size 与 width/height/depth 建议二选一,避免歧义。
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="robot" ref="robotModel" selector="Root/Armature" /><!-- 基础几何 --><cube id="box" width="2" height="1" depth="3"><bound id="box-bounds" /></cube></space>
</xsml>
plane(平面)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
width | number | 宽度。 |
height | number | 高度。 |
size | number | 统一尺寸的便捷属性(正方形平面)。 |
用法要点:size 与 width/height 建议二选一。
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="robot" ref="robotModel" selector="Root/Armature" /><plane id="floor" width="10" height="10" /></space>
</xsml>
sphere(球体)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
segments | number | 分段数。 |
diameter | number | 球体直径。 |
diameterX | number | X 轴直径(非等向椭球)。 |
diameterY | number | Y 轴直径。 |
diameterZ | number | Z 轴直径。 |
arc | number | 弧度(局部弧面)。 |
slice | number | 切片(局部切分)。 |
用法要点:diameter 与 diameterX/Y/Z 用于不同场景,建议不要混用以避免实现差异。
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="robot" ref="robotModel" selector="Root/Armature" /><sphere id="ball" segments="32" diameter="2" /><sphere id="ellipsoid" diameterX="2" diameterY="1" diameterZ="3" /></space>
</xsml>
cylinder(圆柱体)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
height | number | 高度。 |
diameter | number | 统一直径。 |
diameterTop | number | 顶部直径。 |
diameterBottom | number | 底部直径。 |
tessellation | number | 分段数。 |
用法要点:diameter 与 diameterTop/Bottom 通常二选一;若需要圆台/锥体效果,可使用不同的顶部/底部直径。
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="robot" ref="robotModel" selector="Root/Armature" /><cylinder id="pillar" height="4" diameterTop="1" diameterBottom="1" tessellation="32" /></space>
</xsml>
capsule(胶囊体)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
height | number | 高度。 |
radius | number | 统一半径。 |
radiusTop | number | 顶部半径。 |
radiusBottom | number | 底部半径。 |
用法要点:radius 与 radiusTop/Bottom 通常二选一。
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="robot" ref="robotModel" selector="Root/Armature" /><capsule id="pill" height="3" radius="0.5" /></space>
</xsml>
torus(圆环体)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
diameter | number | 圆环直径(主半径的两倍)。 |
thickness | number | 厚度(管径)。 |
tessellation | number | 分段数。 |
<xsml version="1.0"><head><title>JSAR Widget</title><link id="model" rel="mesh" type="octstream/glb" href="./model/welcome.glb" /><script src="./lib/main.ts"></script></head><space><mesh id="robot" ref="robotModel" selector="Root/Armature" /><torus id="ring" diameter="5" thickness="0.5" tessellation="48" /></space>
</xsml>
bound(边界元素,Bounding Box)
属性 | 类型 | 说明 |
---|---|---|
id | string | 唯一标识符。 |
用法要点:
- 大小不可手动设置,依据层级内的子元素计算边界。
- 其边界通常反映父节点的整体包围盒(而父的尺寸来自其子元素)。
- 内部实现为 Babylon.js 的 TransformNode。
在使用XSML的时候,需要注意:
- 尽量避免同时设置“统一尺寸/直径/半径”和“轴向或端部尺寸”,以减少实现差异带来的歧义。
- mesh 使用前先在
<head>
里通过<link>
引入模型资源;ref 对应 link 的 id,selector 精确到节点。 - 需要调试层级边界时,在目标父节点下添加
<bound>
以可视化/计算包围盒(大小由子元素决定)。
打包和部署
项目打包
开发完成后,需要将空间小程序打包成独立文件:
- 通过VS Code打包:
- 在项目根目录右键
- 选择 “JSAR: Package”
- 自动生成
{name}-{version}.zip
文件
- 命令行打包:
npm run build
包大小优化
当前JSAR要求打包后的应用小于10MB。如果超出限制,可以:
- 模型压缩:使用gltf-transform工具
npm install -g @gltf-transform/cli# 压缩GLTF模型
gltf-transform optimize input.glb output.glb
- 纹理优化:
# 压缩纹理到合适尺寸
gltf-transform resize input.glb output.glb --width 512 --height 512
真机调试
打包完成后,可以通过Rokid设备进行真机测试:
- 将zip文件上传到Rokid开发者平台
- 通过设备扫码安装
- 在AR眼镜中直接体验
总结
JSAR 是一个面向空间小程序的开发框架,让 Web 开发者用熟悉的 JS/TS 直接写 3D 应用。XSML 描述场景,VS Code 场景视图热重载,Playground 一键预览,打包就是一个 zip,分发照着 Web 的节奏走。
体验下来最打动我的是门槛低、技能可复用、原型迭代极快。几分钟就能跑出首帧,模型用 link+selector 引用顺手,bound 自动包围盒省事,配合 gltf-transform 控制体积也轻松。如果你是 Web 开发者想试试空间计算,JSAR 值得投入时间——做个小 demo,就能感受到它的速度与潜力。