[XR-Frame]微信小程序XR-Frame中AR部分的简单使用
前言
工作中需要写一个微信小程序,利用XR-Frame框架展示模型,由于先前没有接触过threejs,知识储备匮乏,只能通过官方文档进行学习,记录学习历程
项目初始化
mockdata
先准备好测试用的虚拟数据
export const mockData = [
{
id: "miku",
image: "/assets/tencent.jpg",
model:
"https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/miku.glb",
scale: [0.08, 0.08, 0.08],
rotation: [0, 180, 0],
position: [0, 0, 0],
},
{
id: "lifangti",
image: "/assets/lanqiu.jpg",
model: "/assets/box.glb",
scale: [0.6, 0.6, 0.6],
rotation: [0, 0, 0],
position: [0, 0, 0],
},
{
id: "helmet",
image: "/assets/beizi.jpg",
model:
"https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/damage-helmet/index.glb",
scale: [0.3, 0.3, 0.3],
rotation: [0, 0, 180],
position: [0, 0, 0],
},
];
app.json
在创建项目时,一定要记得在app.json
加上一行配置:"lazyCodeLoading": "requiredComponents"
,非常容易忽视。
TS类型提示
如果使用了TS,那么会发现新创建的项目中所有的api都是没有类型提示的,但是在微信官方的demo中却有,只需要将官方demo中的类型声明文件复制到我们自己的项目中即可。
component.json
在组件中,也要设置renderer
为xr-frame
。
组件使用
此处文档中在使用组件xr-start
时,传入了width
和height
,区别于style
中的width
和height
,作为props
的宽高决定了渲染的宽高,可以理解为分辨率,此处的宽高越大,渲染出来的精细度越高,反之,越低就越糊。
编写组件
wxml
文档中已经明确指出,模板中只能存在一个<xr-scene></xr-scene>
标签。
像光源、摄像机等基础概念文档中已有描述,在此不再赘述。
Element 与 Component
XR-Frame中有很多的元素Element,Element下面会挂载很多的Component,具体功能的实现都是靠Component
创建Element:
const xrFrameSystem = wx.getXrFrameSystem();
scene.createElement(xrFrameSystem.XRNode);
xrFrameSystem.XRNode
中的XRNode就是一个元素,所有以XR开头的都是元素,例如XRARTracker
、XRGLTF
等
创建一个Element后,会有默认挂载的Component,可以通过API文档查询到
Class: XRGLTF | 微信开放文档 (qq.com)
增加、删除Component:
Element.addComponent(xrFrameSystem.xxx,{...options})
Element.removeComponent(xrFrameSystem.xxx)
动态载入资源
scene.assets.loadAsset({
type: "gltf",
assetId: i.id,
src: i.model,
options: {},
});
多个ARTracker
通过ARTracker可以识别图像,demo中通过在wxml中添加标签的方式添加ARTracker,优点是方便易懂,但是不能动态添加,往往我们需要根据后端返回的数据,动态添加ARTracker
想要在xr-frame
中添加元素,必须要用到**shadow-node
**
<xr-scene ar-system="modes:Marker" bind:ready="handleReady">
<xr-light type="ambient" color="1 1 1" intensity="1" />
<xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" cast-shadow />
<xr-shadow id="shadow-node" />
<xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera />
</xr-scene>
先在页面中准备好一个shadow-node
,设置好id
,然后通过js获取
const xrFrameSystem = wx.getXrFrameSystem();
const shadow = scene.getElementById("shadow-node");
然后通过循环创建ARTracker,并添加到shadow-node
下即可
const arTracker = scene.createElement(xrFrameSystem.XRARTracker, {
mode: "Marker",
src: i.image, //i为mockdata中的一项,这里绑定了识别图像为i.image
});
shadow.addChild(arTracker);
绑定了识别图像后,还需要绑定识别成功后显示的模型,我这里使用xr-node
作为模型挂载的节点,大家可以吧xr-node
理解成div
const node = scene.createElement(xrFrameSystem.XRNode);
arTracker.addChild(node);
const nodeComp = node.getComponent(xrFrameSystem.Transform);
//下面是给node加上node-id,并设置模型的比例,位置,旋转
nodeComp.setData({ nodeId: i.id });
nodeComp.scale.setArray(i.scale);
nodeComp.position.setArray(i.position);
nodeComp.rotation.setArray(i.rotation);
const gltfElement = scene.createElement(xrFrameSystem.XRGLTF);
node.addChild(gltfElement);
const gltfComp = gltfElement.getComponent(xrFrameSystem.GLTF);
gltfComp.setData({
model: scene.assets.getAsset("gltf", i.id),
});
gltfElement
.getComponent(xrFrameSystem.Animator)
.setData({ autoPlay: {} });
到这里需要识别的图像和识别成功后对应展示的模型已经绑定好了,笔者这里还有额外的需求,即点击对应模型,弹出模型展示页,因此需要增加和模型的交互。这里有一个大坑。
添加模型交互
要给模型添加交互,需要先给模型加上体积,并绑定事件
gltfElement.addComponent(xrFrameSystem.CubeShape, {
autoFit: true,
});
gltfComp.el.event.add("touch-shape", () => {
this.triggerEvent("onModelTapped", i.id);
});
放置模型
原理大同小异,也是通过shadow-node
添加元素即可。记得添加node
时要先将visible
设置为false
const xrFrameSystem = wx.getXrFrameSystem();
const shadow = scene.getElementById("shadow-node");
const node = (this.data.node = scene.createElement(xrFrameSystem.XRNode, {
visible: "false", //默认为false,并且只能为字符串。
}));
shadow.addChild(node);
const gltfElement = scene.createElement(xrFrameSystem.XRGLTF);
node.addChild(gltfElement);
const gltfComp = gltfElement.getComponent(xrFrameSystem.GLTF);
gltfComp.setData({ model: loadedAsset });
gltfElement.getComponent(xrFrameSystem.Animator).setData({ autoPlay: {} });
点击放置时,会触发placeHere
方法,后面的true
就是将上面的visible: "false"
中的visible
设置为了true
this.data.scene.event.add("touchstart", () => {
this.data.scene.ar.placeHere(this.data.node, true);
});
node-id在哪设置
找了好大一圈才知道,nodeId是要在xrFrameSystem.Transform
这个Component中设置的。
通过这个组件设置的值可以在文档中查到,但是非常难找到
后记
微信的这个框架目前还处于beta状态,网上相关的资料也少,文档的描述个人感觉还是比较难懂的,希望笔者的文章能给大家带来一点帮助。