使用Vue3 + AR撸猫,才叫好玩

6,658 阅读8分钟

一起用代码吸猫!本文正在参与【喵星人征文活动】

先来个预告效果图开场

cat (1).gif

前言:浏览苹果官网时,你会看到发现每个设备在介绍页底部有这么一行文字:“用增强现实看看***”。使用苹果设备点击之后就能将该设备投放于用户所在场景视界,在手机摄像头转动的时候,也能看到物体对象不同的角度,感觉就像真的有一台手机放在你的面前。(效果如下图。注意:由于该技术采用苹果自有的arkit技术,安卓手机无法查看)

微信图片_20211105154040.png

聪明的你可能已经想到了,为什么只能用苹果手机才能查看,那有没有一种纯前端实现的通用的web AR技术呢?

纯前端解决方案

纯前端技术的实现可以用下图总结:

image.png

以JSARToolKit为例:

  • 使用WebRTC获取摄像头信息,然后在canvas画布上绘制原图;
  • JSARToolKit计算姿态矩阵,进而渲染虚拟信息

image.png

实现核心步骤

image.png

  • (识别)WebRTC获取摄像头视频流;
  • (跟踪)Tracking.js 、JSFeat 、ConvNetJS 、deeplearn.js 、keras.js ;
  • (渲染)A-Frame、 Three.js、 Pixi.js 、Babylon.js

比较成熟的框架:AR.js

好比每个领域都有对应的主流开发框架,Web AR领域比较成熟框架的就是AR.js,它在增强现实方面主要提供了如下三大功能:

  1. 图像追踪。当相机发现一幅2D图像时,可以在其上方或附近显示某些内容。内容可以是2D图像、gif、3D模型(也可以是动画)和2D视频。案例:艺术品、学习资料(书籍)、传单、广告等等。
  2. 基于位置的AR。这种“增强现实”技术利用了真实世界的位置,在用户的设备上显示增强现实的内容。开发者可以利用该库使用户获得基于现实世界位置的体验。用户可以随意走动(最好是在户外)并通过智能手机看到现实世界中任何地点的 AR 内容。若用户移动和旋转手机,AR内容也会同步做出反应(这样一些AR内容就被“固定”到真实位置了,且会根据它们与用户的距离做出适当的变化)。这样的解决方案让我们做出交互式旅游向导成为可能,比如游客来到一个新的城市,游览名胜古迹、博物馆、餐馆、酒店等等都会更方便。我们也可以改善学习体验,如寻宝游戏、生物或历史学习游戏等,还可以将该技术用于情景艺术(视觉艺术体验与特定的现实世界坐标相结合)。
  3. 标记跟踪。当相机发现一个标记时,可以显示一些内容(这与图像跟踪相同)。标记的稳定性不成问题,受限的是形状、颜色和尺寸。可以应用于需要大量不同标记和不同内容的体验,如:(增强书籍)、传单、广告等。

开始上手体验AR.js

开发调试开启https

由于使用到摄像头敏感权限,调试时必须基于https环境打开才能正常运行。如果是以往,自己手动搭建个https环境调试对于很多新手来说还是比较麻烦耗费时间,好在最新的基于vite+vue3的脚手架搭建的项目,可以轻松用一行命令开启https访问。用脚手架初始化好代码之后,先修改package.json文件,在dev命令中加上--host暴露网络请求地址(默认不开启),如下图:

image.png

接着用下面命令运行即可开启https:

npm run dev -- --https

image.png

先跑跑官方demo,看看效果

学习一门新框架或语言,最好的方式就是先将官方demo跑起来体验看看。

下面是官方代码展示的案例效果(注:该录制动图体积较大,请耐心等待加载)

案例一

案例二

wow~ 是不是感觉还蛮有意思的?接下来正式进入文章的主题,开始撸猫吧🐱

开始

前面有提到,AR.js基于三种方式展示内容,下面将使用基于图像追踪(Image Tracking) 方式实现。顾名思义,图像追踪就是基于一张图片,根据图片的特性点识别图片并跟踪展示AR内容,例如当摄像头捕捉到该图片时,就可以将要展示的内容悬浮于该图片上方展示。

引入依赖库

Ar.js从版本3开始采用了新的架构,使用jsartoolkit5进行跟踪定位,而渲染库有两种方式可选:A-Frame 或 Three.js。A-Frame方式就是通过html标签的方式简化创建场景素材,比如说展示一张图片,可以直接使用 <a-image></a-image>方式展示。

修改index.html文件:

先将vue代码注入注释掉

image.png 然后引入依赖:

<script src='./src/sdk/ar-frame/aframe-master.min.js'></script>
<script src='./src/sdk/ar-frame/aframe-ar-nft.js'></script>

撸猫姿势一:展示猫图片

<body>
    <a-scene embedded arjs>
      <a-assets>
        <img id="my-image" src="./src/assets/cat.jpg">
      </a-assets>
      <a-marker preset="hiro">
        <a-image rotation="90 0 0" src="#my-image"></a-image>
        <!-- <a-box position="0 0.5 0" material="color: green;"></a-box> -->
      </a-marker>
      <a-entity camera></a-entity>
    </a-scene>
</body>

简单解释下上面的代码:

  1. <a-scene>声明一个场景,你可以理解相当于一个body元素,里面嵌入其他标签元素;
  2. <a-marker>标签声明的是标识图片,也就是相机识别到标识图片时,做相应的处理;这里采用插件预设的hiro图片,下面效果动图可以看到
  3. 使用<a-assets>包裹使用到的素材,相当于声明引入素材,接着在<a-marker>中使用

看下效果:

喵

撸猫姿势二:播放视频

除了展示图片,还可以展示视频,先看效果:

cat (1).gif

代码如下:

  <a-scene vr-mode-ui="enabled: false;" renderer='antialias: true; alpha: true; precision: mediump;' embedded
    arjs='trackingMethod: best; sourceType: webcam; debugUIEnabled: false;'>

    <a-assets>
      <video
        src="https://ugcydzd.qq.com/uwMROfz2r57CIaQXGdGnC2ddPkb5Wzumid6GMsG9ELr7HeBy/szg_52471341_50001_d4615c1021084c03ad0df73ce2e898c8.f622.mp4?sdtfrom=v1010&guid=951847595ac28f04306b08161bb6d1f7&vkey=3A19FB37CFE7450C64A889F86411FC6CE939A42CCDAA6B177573BBCB3791A64C441EFF5B3298E3ED4E99FFA22231772796F5E8A1FCC33FE4CAC487680A326980FFCC5C56EB926E9B4D20E8740C913D1F7EBF59387012BEC78D2816B17079152BC19FCEF09976A248C4B24D3A5975B243614000CAA333F06D850034DA861B01DCA1D53B546120B74F%22"
        preload="auto" id="vid" response-type="arraybuffer" loop crossorigin webkit-playsinline muted playsinline>
      </video>
    </a-assets>

    <a-nft videohandler type='nft' url='./src/assets/dataNFT/pinball' smooth="true" smoothCount="10"
      smoothTolerance="0.01" smoothThreshold="5">
      <a-video src="#vid" position='50 150 -100' rotation='90 0 180' width='300' height='175'>
      </a-video>
    </a-nft>
    <a-entity camera></a-entity>
  </a-scene>
  
  
<script>
  window.onload = function () {
    AFRAME.registerComponent('videohandler', {
      init: function () {
        var marker = this.el;

        this.vid = document.querySelector("#vid");

        marker.addEventListener('markerFound', function () {
          // 识别到标识图,开始播放视频
          this.vid.play();
        }.bind(this));

        marker.addEventListener('markerLost', function () {
          // 丢失标识图,停止播放视频
          this.vid.pause();
          this.vid.currentTime = 0;
        }.bind(this));
      }
    });
  };
</script>

🐱:喵~是不是感觉更酷更好玩了?

撸猫姿势三: 配合声网技术,与你家的猫隔空喊话

如果你是一位前端开发者,相信你一定知道阮一峰这个大佬。曾经在他的每周科技周刊看到这么一个有趣的事情:在亚马逊某片雨林里,安装了录音设备,实时将拾取到的鸟叫声传到一个网站,你可以打开该网站听到该片雨林里的实时鸟叫声,简单的说就是该网站可以听到该片雨林的”鸟叫直播 "。(可惜现在一时找不到该网站网址) 而作为工作党,爱猫人士的我们,可能有着上述同样的情感需求:要出差几天,家里的猫一时没法好好照顾,想要实时看到家里的爱猫咋办?

买台监控摄像头呗

当然是打开声网找到解决方案:视频通话 (这里为声网文档点个赞,整个产品的文档分类规划的特别清晰,不像某些云服务产品文档像是垃圾桶里翻东西)

image.png

使用vue3写法改造文档demo

先安装依赖包:

"agora-rtc-sdk-ng": "latest"

app.vue中代码:

<script setup>
import AgoraRTC from "agora-rtc-sdk-ng";
import { ref } from "vue";

const joinBtn = ref(null);
const leaveBtn = ref(null);

let rtc = {
  localAudioTrack: null,
  client: null,
};

let options = {
  appId: "2e76ff53e8c349528b5d05783d53f53c",
  channel: "test",
  token:
    "0062e76ff53e8c349528b5d05783d53f53cIADkwbufdA1BIXWsCZ1oFKLEfyPRrCbL3ECbUg71dsv8HQx+f9gAAAAAEAACwxdSy/6RYQEAAQDK/pFh",
  uid: 123456,
};

rtc.client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });

rtc.client.on("user-published", async (user, mediaType) => {
  await rtc.client.subscribe(user, mediaType);
  console.log("subscribe success");

  if (mediaType === "video") {
    const remoteVideoTrack = user.videoTrack;
    const remotePlayerContainer = document.createElement("div");
    remotePlayerContainer.id = user.uid.toString();
    remotePlayerContainer.textContent = "Remote user " + user.uid.toString();
    remotePlayerContainer.style.width = "640px";
    remotePlayerContainer.style.height = "480px";
    document.body.append(remotePlayerContainer);
    remoteVideoTrack.play(remotePlayerContainer);
  }

  if (mediaType === "audio") {
    const remoteAudioTrack = user.audioTrack;
    remoteAudioTrack.play();
  }

  rtc.client.on("user-unpublished", (user) => {
    const remotePlayerContainer = document.getElementById(user.uid);
    remotePlayerContainer.remove();
  });
});

// 加入通话
const handleJoin = async () => {
  await rtc.client.join(
    options.appId,
    options.channel,
    options.token,
    options.uid
  );
  rtc.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
  rtc.localVideoTrack = await AgoraRTC.createCameraVideoTrack();
  await rtc.client.publish([rtc.localAudioTrack, rtc.localVideoTrack]);
  const localPlayerContainer = document.createElement("div");
  localPlayerContainer.id = options.uid;
  localPlayerContainer.textContent = "Local user " + options.uid;
  localPlayerContainer.style.width = "640px";
  localPlayerContainer.style.height = "480px";
  document.body.append(localPlayerContainer);
  rtc.localVideoTrack.play(localPlayerContainer);
  console.log("publish success!");
};
// 离开通话
const handleLeave = async () => {
  rtc.localAudioTrack.close();
  rtc.localVideoTrack.close();
  rtc.client.remoteUsers.forEach((user) => {
    const playerContainer = document.getElementById(user.uid);
    playerContainer && playerContainer.remove();
  });
  await rtc.client.leave();
};
</script>

<template>
  <div>
    <button ref="joinBtn" @click="handleJoin" type="button" id="join">
      加入
    </button>
    <button ref="leaveBtn" @click="handleLeave" type="button" id="leave">
      离开
    </button>
  </div>
</template>

<style></style>

跑起来效果: image.png

这时就相当于在家安装了一个摄像头,如果我们需要远程查看,就可以通过声网官方提供的一个测试地址加入通话

手机打开上述网址,输入你的项目appId跟token,可以看到成功加入通话:

IMG_8973.PNG

111636875423_.pic_hd.jpg

下方图片是手机摄像头捕捉到的画面,原谅我用猫照片代替😂

让视频画面跑在AR.js画面中

这个由于个人时间关系,暂时就不研究实现。这里提供一个想法就是: 单纯的视频画面看起来有点单调,毕竟有可能猫并不在视频画面中出现,结合撸猫姿势一提到的展示图片,其实我们可以在ar场景中视频区域周围,布置照片墙或其他酷炫一点的subject,这样的话我们打开视频即使看不到猫星人,也可以看看它的照片之类的交互。

结束语

本文借征文活动,简单入手了解了下web AR相关知识,在这几天学习的过程中觉得还是蛮好玩的,此文也当抛砖引玉,希望更多开发者了解AR相关的知识。

AR在体验上真的很酷,未来值得期待。

最近几年苹果一直致力于推进AR技术体验并带来相关落地产品,例如为了配合提升AR体验,带来雷达扫描,空间音频功能。值得一提的是,今年的苹果秋季发布会,苹果的邀请函也是利用到了AR + 空间音频技术,即使你不是果粉,当你实际上手体验的时候,你依然会真正发自内心的感觉:wow~cool。可以点此视频观看了解。

而目前的Web AR技术相比于苹果自有的ARkit技术,在体验上还存在一些差距(如性能问题,识别不稳定),同时缺乏生态圈,希望Web AR技术在未来得到快速发展,毕竟web端跨平台通用特性,让人人的终端都可以跑起来才是实现AR场景大规模应用的前提。

Facebook押注的元宇宙概念中,其实也包含了AR技术,所以在元宇宙世界到来之前,AR技术值得我们每一个前端开发者关注学习。

彩蛋

如果你问我最喜欢什么猫,我会说--“房东的猫”,~哈哈哈🐱~

1511636712878_.pic_hd.jpg

参考资料

AR.js官网

AR.js中文翻译文档

跨平台移动Web AR的关键技术 介绍及应用

声网文档