2D变3D,小程序酷炫玩法在等你!
随着小程序的广泛应用,不少商家都希望通过小程序实现线上与线下营销活动联动。例如用户购买游戏实体卡,使用小程序扫描并形成 3D 立体效果,增强实体卡的营销价值。
然而实现这样流畅又酷炫的 AR 效果并不容易,不仅需要对三维效果、关键点、边缘等部分进行不断调优,同时还需要保证整体流畅的性能表现。不过开发者也无需过分担心,现在通过 小程序 XR-Frame 框架 即可轻松实现,我们一起来看看吧👇
开发思路分析
以上述实体卡为例,用户体验的流程主要是:
打开摄像头,识别实体卡
识别成功后,自动渲染成 AR 效果
AR 效果不局限于图片,支持视频流
用户移动实体卡时,AR 效果自动跟随
为了实现这样的效果,开发者先完成 AR 效果渲染,再进行图像识别即可:
实现基础的 AR 效果
根据项目情况去调整 AR 效果图片及尺寸
在图片渲染的基础上,增加视频流渲染
完成 AR 效果渲染后,增加图像识别能力,实现实体卡内容与 3D 电子内容匹配
实现基础 AR 效果
由于上述实体卡需要用到 2DMarker 场景,开发者在引入 XR-Frame 框架、创建场景 xr-scene 后,可以直接使用框架提供的各种标签,简单便捷,开箱即用:
给 <xr-scene> 设置 ar-system="modes:Marker",开启 marker 能力
<xr-ar-tracker> 设置对应的类型 mode="Marker",并且设置 src,用于识别和追踪,src 为目标图片地址,即上述项目中实体卡对应的电子版内容
设置 <xr-camera> 的相关属性 is-ar-camera 和 background="ar",开启 AR 能力
在 <xr-ar-tracker> 中使用 <xr-mesh> 进行简单的贴图渲染
👉 点击查看代码
// app.json"lazyCodeLoading":"requiredComponents"// index.json{"component": true,"renderer": "xr-frame","usingComponents": {}}// index.wxml<xr-scene ar-system="modes:Marker"><xr-node><xr-ar-tracker mode="Marker" src="{{markerImage}}"><xr-mesh geometry="plane" uniforms="u_baseColorFactor:0.6 0.8 0.6 1"/></xr-ar-tracker><xr-camera clear-color="0.925 0.925 0.925 1" background="ar" is-ar-camera></xr-camera></xr-node></xr-scene>
完成上述开发过程后,开发者用手机摄像头对准预设的目标物,自动渲染出一个正方形;移动卡片,正方形也会跟着移动,完成基础的 AR 效果。
调整图片及尺寸
我们希望 3D 效果显示对应的图片内容,而不是一个简单的正方形。因此开发者需要将正方形添加图片纹理,替换成目标图片。这里也可以开箱即用地调用 XR-Frame 框架提供的标签 <xr-asset-load> 即可实现。
👉 点击查看代码
<xr-scene ar-system="modes:Marker"><xr-assets><xr-asset-load type="texture" asset-id="photo" src="https://vip.image.video.qpic.cn/vupload/20230411/05.png" /></xr-assets><xr-node><xr-ar-tracker mode="Marker" src="{{markerImg}}"><xr-mesh geometry="plane" uniforms="u_baseColorMap: photo"/></xr-ar-tracker><xr-camera position="0.8 2.2 -5" clear-color="0.925 0.925 0.925 1" background="ar" is-ar-camera></xr-camera></xr-node></xr-scene>
替换图片后,我们发现显示的 AR 效果仍然是正方形,不能与实体卡尺寸匹配,那么我们可以用 <xr-mesh> 的 scale 进行尺寸调整。
👉 点击查看代码
<xr-mesh scale="1 1 1.5" geometry="plane"uniforms="u_baseColorMap: photo" />
视频流渲染
项目目标不仅是平面图的三维展示,更希望能够出现视频流的 AR 效果。那么应用 XR-Frame 框架提供的视频纹理 VideoTexture 资源即可实现:
设置 type="video-texture",并设定相关参数
在 js 中获取视频纹理对象,控制视频播放与暂停
👉 点击查看代码
// 设置 type="video-texture",并设定相关参数即可<xr-asset-load type="video-texture" asset-id="ar-video" options="abortAudio:false" src="{{video}}" /><xr-asset-material asset-id="video-mat" effect="simple" uniforms="u_baseColorMap: video-ar-video" />// 控制视频播放与暂停videoCtx = xrScene.assets.getAsset('video-texture', 'ar-video');// 播放await videoCtx.play();// 停止videoCtx.stop();// 在基础库v2.33.0及以上,提供了暂停/唤醒方法和播放状态const xrSystem = wx.getXrFrameSystem();if (videoCtx.state === xrSystem.EVideoState.Playing) {videoCtx.pause();} else if (videoCtx.state === xrSystem.EVideoState.Paused) {videoCtx.resume();}
图片识别
通过上述操作,我们已经完成整个 AR 渲染的过程。接下来就需要进行图片识别操作,识别哪张实体卡对应哪个电子内容,仅需 3 步即可实现:
借助 XR-Frame 框架的 tick 事件监听每一帧的变化,实现前端获取屏幕画面
在绑定的 handleTick 事件中,调用 分享系统,将当前帧的画面转为 base64 格式
将 base 64 数据传输给后台,后台接口在图片库中进行比对计算,返回最相似的图片给前端进行追踪渲染
👉 点击查看代码
// 绑定 tick 事件监听帧变化<xr-scene bind:tick="handleTick">......</xr-scene>// 帧画面转成 base64 格式const base64 = xrScene.share.captureToDataURL({ quality: 0.5 });
通过以上操作,小程序够识别图片并且生成 AR 效果,但是在不同光线、角度、背景下,扫描实体卡可能会出现扫描失败 / 扫描错误的情况。
因此我们增加拍摄引导框,对屏幕画面按照引导框进行裁剪,再调用接口进行检索,优化图片识别率。这里使用 canvas 能力即可解决。
👉 点击查看代码
const renderWidth = clipWidth * dpi / 2;const renderHeight = clipHeight * dpi / 2;wx.createSelectorQuery().select('#myCanvas').fields({ node: true, size: true }).exec((res) => {const canvas = res[0].node;// 渲染上下文const ctx = canvas.getContext('2d');// 初始化画布大小canvas.width = renderWidth;canvas.height = renderHeight;ctx.clearRect(0, 0, renderWidth, renderHeight);// 图片对象const image = canvas.createImage();// 图片加载完成回调image.onload = () => {// 将图片绘制到 canvas 上ctx.drawImage(image,clipLeft * dpi / 2, clipTop * dpi / 2, renderWidth, renderHeight,0, 0, renderWidth, renderHeight,);const newBase64 = canvas.toDataURL('image/jpeg');};// 设置图片srcimage.src = base64;});
通过 小程序 XR-Frame 框架,我们能够实现扫描实体卡出现流畅的 AR 视频流效果,开发门槛更低,性能表现更好。欢迎各位开发者接入使用!
如有更多关于小程序的问题,可在 小程序交流专区 发帖互动,技术专员将为大家解答及进行深度交流。
原创|腾讯前端工程师 teeniechen、manmanyu