玩转小程序AR-实战篇

作者:深红日期:2025/12/5

背景

某天需求方扔了个链接:【原神官方】AR 立牌,询问小程序是否能够实现类似的AR效果。

作为打工的人的我,于是被迫补起:早已过了风口(bushi)的AR知识。

调研

实体 AR 立牌

巨资在闲鱼淘了个多莉的角色立牌,实际体验了下完整的交互流程,AR的氛围感还是不错的。

AR在线制作平台

KIVICUBE 提供了可视化的3D场景搭建和动画编排系统:零基础也可创造和发布酷炫的AR作品。

官方同时提供了大量创意模版供大家一键使用

技术方案

在微信小程序的技术体系下,官方提供了两种解决方案:

小程序也在基础库 2.20.0 版本开始提供了开发 AR 功能的能力,即 VisionKit。VisionKit 包含了 AR 在内的视觉算法

xr-frame是一套小程序官方提供的XR/3D应用解决方案,基于混合方案实现,性能逼近原生、效果好、易用、强扩展、渐进式、遵循小程序开发标准

简单来说:

  • VisionKit 是底层视觉引擎,提供能力但需要自己拼装。
  • XR-FRAME 是完整开发框架,整合了渲染、交互与视觉能力,适合快速实现产品化的 AR 效果。

虽然理论上我们完全可以基于 VisionKit 并结合 Three.js 或自研的 WebGL 渲染逻辑来实现 AR 效果,但这种方案开发成本较高:

开发者需要自行处理相机帧与渲染管线的衔接、追踪状态管理、姿态矩阵更新等底层逻辑,整体工程量大且维护复杂。(Kivicube 正是使用此方案,确保自研的 AR 可视化搭建平台的产物能兼容各大平台:微信小程序、原生网页H5)

而 XR-FRAME 在此基础上进一步封装了完整的 3D 渲染与交互体系,提供了大量开箱即用的能力,让开发者可以像写前端组件一样,以声明式方式快速构建 AR 场景,而不必深入到底层渲染细节。

因此最后决定:先用 XR-FRAME 快速交付第一版 MVP 小程序

XR-FRAME 指南

由于是小程序开发,所以学习 XR-FRAME 的前提,需要有小程序基础知识

而官方的两个在线文档,内容还是略显单薄,强烈建议直接参考官方 《xr-frame系统的示例集》源码进行实战学习

本教程配套代码:xr-frame-tutorial

XR 组件 模版代码

创建 XR 组件

1{
2  "component": true,
3  "usingComponents": {},
4  "renderer": "xr-frame"
5}
6
1<xr-scene>
2  <xr-camera clear-color="0.4 0.8 0.6 1" />
3</xr-scene>
4

使用 XR 组件

1{
2  "usingComponents": {
3    "demo1": "../../components/demo1"
4  },
5  "disableScroll": true, 
6  "renderer": "webview"
7}
8
1<view>
2  <demo1
3    disable-scroll
4    id="main-frame"
5    width="{{renderWidth}}"
6    height="{{renderHeight}}"
7    style="width:{{width}}px;height:{{height}}px;top:{{top}}px;left:{{left}}px;"
8  />
9</view>
10
1Page({
2  data: {
3    left: 0,
4    top: 0,
5    width: 0,
6    height: 0,
7    renderWidth: 0,
8    renderHeight: 0,
9  },
10  onLoad(options) {
11    const info = wx.getSystemInfoSync()
12    const width = info.windowWidth
13    const height = info.windowHeight
14    const dpi = info.pixelRatio
15
16    this.setData({
17      width, 
18      height,
19      renderWidth: width * dpi,
20      renderHeight: height * dpi
21    });
22  },
23})
24

渲染 XR 组件

渲染效果:绿色背景的画布 Canvas

3D 渲染

源码示例: 3D 渲染

最基础的 3D 渲染 思维导图

添加物体

添加一个 立方体 (Cube)物体

1<xr-scene>
2  <xr-mesh node-id="cube" geometry="cube" />
3  <!-- 设置 target 指向 cube,让相机始终看向这个立方体--> 
4  <xr-camera clear-color="0.4 0.8 0.6 1" position="1 3 4" target="cube" camera-orbit-control />
5</xr-scene>
6

物体黑色是因为在我们没有给xr-mesh指定材质时,用的是基于PBR效果的默认材质,需要光照

临时解决方案: 创建一个不需要光照的材质,并且使用这个材质

1<xr-scene>
2  <xr-asset-material asset-id="simple" effect="simple" uniforms="u_baseColorFactor:0.8 0.4 0.4 1" />
3  <xr-mesh node-id="cube" geometry="cube" material="simple" />
4  <xr-camera clear-color="0.4 0.8 0.6 1" position="1 3 4" target="cube" camera-orbit-control />
5</xr-scene>
6

添加光照

1<xr-scene>
2  <xr-mesh node-id="cube" geometry="cube" uniforms="u_baseColorFactor:0.8 0.4 0.4 1" />
3  <!-- 一个环境光 -->
4  <xr-light type="ambient" color="1 1 1" intensity="1" />
5  <!-- 一个主平行光 -->
6  <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" cast-shadow /> 
7  <xr-camera clear-color="0.4 0.8 0.6 1" position="1 3 4" target="cube" camera-orbit-control />
8</xr-scene>
9

添加纹理

纹理 Texture 是 GPU 中的图像,供着色器采样使用。在框架中其一般被作为材质的一部分uniforms使用

1<xr-scene>
2  <xr-assets bind:progress="handleAssetsProgress" bind:loaded="handleAssetsLoaded">
3    <!-- 加载纹理 -->
4    <xr-asset-load type="texture" asset-id="waifu" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/waifu.png" />
5    <!-- 材质中使用纹理 -->
6    <xr-asset-material asset-id="mat" uniforms="u_baseColorMap: waifu" />
7  </xr-assets>
8
9  <!-- 使用材质 -->
10  <xr-mesh node-id="cube" geometry="cube" material="mat" cast-shadow />
11  
12  <!-- 一个环境光 -->
13  <xr-light type="ambient" color="1 1 1" intensity="1" />
14  <!-- 一个主平行光 -->
15  <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" cast-shadow /> 
16  <xr-camera clear-color="0.4 0.8 0.6 1" position="1 3 4" target="cube" camera-orbit-control />
17</xr-scene>
18

我们继续新加一个 平面 (Plane) 物体

1<xr-assets bind:progress="handleAssetsProgress" bind:loaded="handleAssetsLoaded">
2    <xr-asset-load type="texture" asset-id="deepred" src="https://avatars.githubusercontent.com/u/13102815" />
3    <xr-asset-material asset-id="mat2" uniforms="u_baseColorMap: deepred" />
4</xr-assets>
5
6<xr-mesh node-id="plane" geometry="plane" material="mat2" position="0 1 0" />
7

添加动画

1{
2  "setting": {
3    "ignoreDevUnusedFiles": false,
4    "ignoreUploadUnusedFiles": false
5  }
6}
7

添加一个无限旋转的动画

  • keyframe 中定义了帧动画具体的行为,本质上类似于 CSS 中的 keyframes
  • animation 中定义了帧动画的播放配置,本质上类似于 CSS 中的 animation

注意:旋转的值是弧度!!!

360度等于2π弧度,约等于 2 * 3.14

1{
2  "keyframe": {
3    "logo": {
4      "0": {
5        "rotation": [0, 0, 0]
6      },
7      "100": {
8         // 注意是弧度,360度等于2π,约等于6.28
9        "rotation": [6.28, 0, 0]
10      }
11    }
12  },
13  "animation": {
14    "logo": {
15      "keyframe": "logo",
16      "duration": 4,
17      "ease": "linear",
18      "loop": -1
19    }
20  }
21}
22
1<!-- 加载动画资源 -->
2<xr-asset-load asset-id="anim" type="keyframe" src="/assets/animation.json"/>
3
4<xr-mesh node-id="plane" geometry="plane" material="mat2" position="0 1 0" anim-keyframe="anim" anim-autoplay="clip:logo" />
5

添加 3D 模型

支持 GLTF 格式模型

1<!-- 加载 GLTF 模型 -->
2<xr-asset-load type="gltf" asset-id="miku" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/miku.glb" />
3
4<!-- 渲染 GLTF 组件 -->
5<xr-gltf model="miku" position="-0.15 0.75 1" scale="0.07 0.07 0.07" rotation="0 180 0" anim-autoplay />
6

AR 系统

AR 能力,需要调用摄像头权限

微信开发者工具无法模拟,请使用真机预览模式

Plane 识别

源码示例: Plane 模式

Plane 模式是 AR 中的平面检测与追踪功能

常见的交互流程:

  1. 扫描阶段
  • 用户移动手机摄像头
  • AR 系统分析画面,识别水平或垂直的平面
  • 常见平面:地板、桌面、墙壁、床面等
  1. 检测阶段
  • 找到平面后,显示视觉指示器(视频中的蓝色圆环)
  • 指示器跟随检测到的平面移动
  1. 放置阶段
  • 用户点击屏幕
  • 虚拟物体被"放置"到现实世界的平面上
1<!-- AR system 系统开启 Plane 模式 -->
2<xr-scene ar-system="modes:Plane" bind:ready="handleReady">
3  <xr-assets bind:loaded="handleAssetsLoaded">
4    <xr-asset-load type="gltf" asset-id="anchor" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/ar-plane-marker.glb" />
5    <xr-asset-load type="gltf" asset-id="miku" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/miku.glb" />
6    <xr-asset-load type="texture" asset-id="deepred" src="https://avatars.githubusercontent.com/u/13102815" />
7    <xr-asset-material asset-id="mat" uniforms="u_baseColorMap: deepred" />
8  </xr-assets>
9  <xr-light type="ambient" color="1 1 1" intensity="1" />
10  <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" cast-shadow />
11  <!-- AR 追踪器 对应也要开启 Plane 模式 -->
12  <xr-ar-tracker mode="Plane">
13    <!-- 找到平面后,显示视觉指示器 -->
14    <xr-gltf model="anchor"></xr-gltf>
15  </xr-ar-tracker>
16  <!-- 首先隐藏虚拟物体 -->
17  <xr-node node-id="setitem" visible="false">
18    <xr-gltf model="miku" anim-autoplay scale="0.07 0.07 0.07" rotation="0 180 0" />
19    <xr-mesh node-id="plane" geometry="plane" material="mat" scale="0.3 0.3 0.3" />
20  </xr-node>
21   <!-- camera  background 设置成 ar -->
22  <xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera />
23</xr-scene>
24
1Component({
2  methods: {
3    handleAssetsLoaded: function ({ detail }) {
4      wx.showToast({ title: '点击屏幕放置模型' });
5      this.scene.event.add('touchstart', () => {
6        // 虚拟物体被"放置"到现实世界的平面
7        this.scene.ar.placeHere('setitem', true);
8      });
9    },
10    handleReady: function ({ detail }) {
11      this.scene = detail.value;
12    },
13  }
14})
15

Marker 识别

源码示例: Marker 模式

Marker 模式,能够识别预先设定的目标物体(定义为 Marker,包括2D平面物体和3D物体),进行视觉跟踪与定位,通过在目标物体周围渲染虚拟物体,从而实现AR功能。

模型与现实物体保持空间位置关系(即:3D 层级 效果)。

Marker 分类

  1. 2D Marker,仅适用于平面类物体,用户上传一张平面物体的俯视图像作为目标物体,算法运行时识别该平面物品,并渲染出相关虚拟物体。2D Marker可以理解为特殊的 3D Marker。
  2. 3D Marker,相比于2D Marker,能够识别3D物体,不局限于平面物体,具有更广的使用范围,算法运行前,需要手动制作3D Marker的识别目标文件(.map文件),然后算法运行时载入该文件用于识别
1<xr-scene ar-system="modes:Marker" bind:ready="handleReady">
2  <xr-assets bind:loaded="handleAssetsLoaded">
3    <xr-asset-load type="video-texture" asset-id="hikari" options="loop:true" src="https://assets.xxxx.com/resources/cdn/20250925/1c85f5b5ecde29ea.mp4" />
4    <xr-asset-load type="texture" asset-id="deepred2" src="https://assets.xxxx.com/resources/cdn/20250925/c737cf37d083d543.png" />
5    <xr-asset-material asset-id="mat" effect="simple" uniforms="u_baseColorMap: video-hikari" />
6    <xr-asset-material asset-id="mat3" effect="simple" uniforms="u_baseColorMap: deepred2" />
7  </xr-assets>
8  <xr-node wx:if="{{loaded}}">
9    <xr-ar-tracker mode="Marker" bind:ar-tracker-switch="handleTrackerSwitch" src="https://assets.xxxx.com/resources/cdn/20250925/fe8dad0e9800ef81.jpg">
10      <xr-mesh node-id="mesh-plane" geometry="plane" material="mat" scale="1.7778 1 1" position="0 0.1 0" />
11      <xr-mesh node-id="plane" geometry="plane" material="mat3" position="0.1 0.8 0.1" scale="0.12 0.12 0.12" />
12    </xr-ar-tracker>
13  </xr-node>
14  <xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera />
15</xr-scene>
16
1Component({
2  methods: {
3    handleReady: function ({ detail }) {
4      this.scene = detail.value;
5    },
6    handleAssetsLoaded: function ({ detail }) {
7      this.setData({ loaded: true });
8    },
9    handleTrackerSwitch: function ({ detail }) {
10      // 获取追踪状态
11      const active = detail.value;
12      const video = this.scene.assets.getAsset('video-texture', 'hikari');
13      // 识别到物体,播放视频
14      // 识别中,暂停视频
15      active ? video.play() : video.stop();
16    }
17  }
18})
19

OSD 识别

源码示例: OSD 模式

OSD(One-shot Detection)Marker 识别模式,可以看成是一种特殊的 Marker 模式 :在摄像头画面上“贴图叠加”的模式,主要以 屏幕坐标系(2D) 为主,不真正感知空间深度

1<xr-scene ar-system="modes:OSD" bind:ready="handleReady">
2  <xr-assets bind:loaded="handleAssetsLoaded">
3    <xr-asset-material asset-id="mat" effect="simple" states="alphaMode:BLEND" />
4    <xr-asset-material asset-id="text-simple" effect="simple" />
5  </xr-assets>
6  <xr-node>
7    <xr-ar-tracker mode="OSD" src="https://assets.xxxx.com/resources/cdn/20250925/fe8dad0e9800ef81.jpg">
8      <xr-node rotation="0 180 0">
9        <xr-mesh node-id="text-wrap" geometry="plane" material="mat" position="0 1 0" scale="1 1 0.5" rotation="90 0 0" uniforms="u_baseColorFactor:0.875 0.616 0.624 1" />
10        <xr-text node-id="text-name" position="-0.25 1.05 0" scale="0.1 0.1 0.1" material="text-simple" value="美食家蜜蜂" />
11      </xr-node>
12    </xr-ar-tracker>
13  </xr-node>
14  <xr-camera clear-color="0.4 0.8 0.6 1" background="ar" is-ar-camera />
15</xr-scene>
16

人脸识别

源码示例: 人脸识别

1<!-- AR system 系统开启 Face 模式 同时开启前置摄像头 -->
2<xr-scene ar-system="modes:Face;camera:Front">
3  <xr-assets>
4    <xr-asset-load type="gltf" asset-id="mask" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/jokers_mask_persona5.glb" />
5  </xr-assets>
6  <!-- AR 追踪器 对应也要开启 Face 模式 -->
7  <!-- auto-sync 是一个数字数组,用于将对应顺序的子节点绑定到某个特征点上 -->
8  <xr-ar-tracker mode="Face" auto-sync="43">
9    <!-- 包含识别成功后需要展示的场景 -->
10    <xr-gltf model="mask" rotation="0 180 0" scale="0.5 0.5 0.5" />
11  </xr-ar-tracker>
12  <xr-light type="ambient" color="1 1 1" intensity="1" />
13  <xr-light type="directional" rotation="40 70 0" color="1 1 1" intensity="3" />
14  <!-- AR 相机 -->
15  <xr-camera background="ar" is-ar-camera />
16</xr-scene>
17

除了人脸识别(Face),还有 人体识别(Body),人手识别(Hand),可以参考官方文档学习

总结

到这里,我们已经把 XR-FRAME 的基础能力都过了一遍:从创建场景、添加物体、设置光照,到加载模型和动画,再到四种 AR 识别模式(Plane、Marker、OSD、Face)。理论上,你已经可以做出一个简单的 AR 效果了。

但理论和实际总是有差距的。在下一篇实战篇中,我会分享更高阶的知识点和实际项目中的经验:

  • Shader 着色器:实现自定义视觉效果,让 AR 场景更炫酷
  • 同层渲染:XR 组件和小程序原生组件互相通信,实现复杂的 UI 交互
  • 企业级方案:性能优化、状态管理、多设备兼容等实战经验

玩转小程序AR-实战篇》 是转载文章,点击查看原文


相关推荐


LLM 扫盲:什么是 Tokens?
mCell2025/12/2

同步至个人网站:LLM扫盲: 什么是tokens LLM 基础:什么是 Tokens? GPT 5.1 发布已经有一段时间了,LLM(大语言模型)的能力边界再一次被拓宽。对于应用开发者而言,虽然模型越来越智能,但 API 的计费逻辑和底层限制依然没有变:Token 始终是那个核心计量单位。 很多人对 Token 有误解,认为它等同于字符(Character)或单词(Word)。这种误解往往导致两个问题:一是预估 API 成本时出现较大偏差,二是无法精确控制 Prompt 的上下文长度,导致模型


Vue3 如何实现图片懒加载?其实一个 Intersection Observer 就搞定了
刘大华2025/11/30

大家好,在当今图片密集的网络环境中,优化图片加载已成为前端开发的重要任务。今天我们分享一下怎么使用 Vue3 实现图片的懒加载功能。 什么是图片懒加载? 假如你打开一个有大量图片的页面,如果所有图片同时加载,会导致页面卡顿、流量浪费,特别是对于那些需要滚动才能看到的图片。 懒加载技术就是解决这个问题的方案,只有当图片进入或即将进入可视区域的时候,才加载它们。 效果预览: 完整示例代码可在文末获取 实现原理 我们的Vue3懒加载实现基于以下核心技术: 1. Intersection Observ


把常用 Prompt 做成 Skill 之后,我和 Claude Code 的配合效率直接翻了 3 倍
技术探索家2025/11/27

一个真实故事 去年10月,我手里有个React项目要重构,2000多行的上帝类,看着就头疼。每次让Claude Code帮我优化代码,我都要重复交代一遍: "记得用TypeScript严格模式" "API调用要加错误处理" "组件要符合单一职责原则" 复制粘贴这些要求,少说也得两三分钟。更烦的是,聊了十几轮之后,Claude Code经常会"忘记"我最初的要求,又开始写出不符合规范的代码。 直到我在文档里翻到了Skill功能。 试了一周后,我把那些重复的要求全封装成了几个skill文件。现在


基于华为开发者空间从0实现一个MCP Server
高校俱乐部2025/11/25

1 概述 1.1 案例介绍 MCP (Model Context Protocol) 是一个开放协议,用于标准化应用程序如何向 LLM 提供上下文。可以将 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供标准化方式一样,MCP 为 AI 模型连接不同的数据源和工具提供了标准化的方式。 MCP 的核心遵循客户端-服务器架构,其中主机应用程序可以连接到多个服务器: {{{width="60%" height="auto"}}} - MCP 主机:


【Spring】Cookie和Session是什么
d***9352025/11/23

文章目录 回顾 Cookie理解 SessionCookie 和 Session 的区别 回顾 Cookie HTTP 协议自身是属于“无状态”协议 无状态:默认情况下,HTTP 协议的客户端和服务器之间的这次通信和下次通信之间没有直接的联系 但是在实际开发中,我们很多时候是需要知道请求之间的关联关系的 例如登录网站成功后,第二次访问的时候服务器就能知道该请求是否是已经登录过了 上述图片中的“令牌”通常就存储在 Cookie 字段中 比如去医院挂号: 看病之前先挂


Lua 的 dofile 函数
IMPYLH2025/11/21

Lua 的 dofile 函数 是用于加载并执行外部 Lua 脚本文件的核心函数之一。它的主要功能和工作原理如下: 基本功能 读取指定的 Lua 文件编译文件内容为字节码执行编译后的代码返回该文件中最后一个表达式的值 语法格式 dofile(filename) 其中 filename 是要加载的 Lua 文件路径(相对路径或绝对路径) 典型应用场景 模块化开发时加载子模块游戏开发中加载场景或关卡配置动态加载用户自定义脚本测试环境快速重载修改后的代码 与 require 的区别


Gemini 3 Pro 来了!一句话生成完整网站,AI编程能力断层领先
wwwzhouhui2025/11/19

前言 在AI大模型快速迭代的今天,各家厂商疯狂堆参数、拼算力,动不动就是参数翻倍,但日常用起来的感觉却大同小异。就在大家对"GPT-4.5级"、"性能提升30%"这些宣传话术感到麻木的时候,Google在2025年11月18日悄悄扔出了一个重磅炸弹——Gemini 3.0。 Gemini 3 Pro 是 Google DeepMind 推出的新一代旗舰模型,被官方定义为"世界上多模态理解能力最强的模型"。它不是简单的微调升级,而是从零开始在自家TPU芯片上训练的全新模型,采用稀疏混合专家架构(M


使用 Cursor & Claude 操作 Figma 画图
Keely402852025/11/18

版权声明:本文为博主原创文章,未经博主允许不得转载。 文章底部留言可联系作者。 一、背景 现在各种AI工具的普及让人眼花缭乱,大家都在拥抱AI,之前朋友推荐某音的一个小视频看到可以使用Cursor操作Figma自动画图感觉非常神奇,正好我 Claude和Cursor 都在使用,对有意思的工具做了一些尝试,现在总结下经验希望可以帮助大家。 二、Cursor 如何操作 Figma 1. 安装 Cursor Cursor 可以点击官网下载选择合适版本进行使用。新账号试用过后需要付费使用,具体使用方法


我在高职教STM32(新12)——STM32中断概览
南耿先生2025/11/17

新学期,又要给学生上 STM32 嵌入式课程了。这课上了多年了,一直用的都是标准库来开发,已经驾轻就熟了。人就是这样,有了自己熟悉的舒适圈,就很难做出改变,老师上课也是如此,排斥新课和不熟悉的内容。显然,STM32 的开发,HAL 库已是主流,自己其实也在使用,只不过更换库就意味着教学内容有很大变化,自己也就迟迟没有迈出调整这一步。现在,是时候做出变化了,笔者计划保持教学项目不变(图 1 所示),逐步将源码替换成 HAL 库。虽然不能一步到位,但会在备课期间逐步替换,自己就当再学习和巩固一遍。


openGauss实战:Python开发与AI向量数据库应用
倔强的石头_2025/11/16

引言 经过前两篇文章的铺垫,我们已经掌握了openGauss的部署安装和使用Data Studio进行可视化管理。现在,我们来到了本系列文章的终章,将目光聚焦于开发者最关心的环节——如何在应用程序中与openGauss进行交互,并探索其在AI领域的应用潜力。 本文将以目前最流行的编程语言之一Python为例,详细演示如何连接openGauss数据库,并围绕两个典型的业务场景——“用户管理系统”和“订单支付流程”,构建完整的CRUD(创建、读取、更新、删除)与事务处理代码示例。更进一步,我们将结合

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读