利用A-Frame和Vue.js一步步打造360全景看房 (二)

in WebXR with 0 comments, 6406 views

全景原理

想象下全景的效果,我们需要从周身360度观察整个场景。在虚拟的三维世界中,我们完全可以打造这么个场景,常见的一种做法就是:

经过这几步,我们得到的下面的效果

1566056399085.gif

这种做法和世界地图如出一辙,事实也确实如此。地球也是一个圆球,表面是无法展开铺平的平面。而绘制的世界地图是平面地图,聪明的前辈提出了投影的概念来表达这种对应关系.投影方式有很多,这里我们提到的一种叫墨卡托投影

我们知道,有光就有影。继续想象下,地球是透明的,在地球内部有个光源,而在地球四周围着一个圆柱,地球上的五大洲投影在这个圆柱上,然后我们将其展示得到了世界地图。地图上有很多网格线就成了我们熟悉的经纬线,和地球表面一一对应。

大概是这个样子:

413px-Usgs_map_mercator.svg.png

我们回过头来观察下之前的全景图:

qj_01_1.jpg

它和世界地图一样,只是我们这里需要反过来去得到一个球体表面,当然这个工作A-Frame会帮我们去完成。 然后在这个球体内部去观察(架设一部相机),就会发现你已经置身于一个360度全景的场景之中。

实体组件系统

上一篇中提到了A-Frame中采用的实体组件系统,这里我们专门展开。 实体-组件-系统架构(ECS)是一种常用于游戏的架构模式,大名鼎鼎的unity3d就是使用的这种架构。它遵循组合优于继承原则,实体<a-entity>是容器,可以容纳不同的组件来体现不同的外观以及不同的行为和功能,最终构成一个个拥有不同特性的实体对象。A-Frame提供了很多默认的实体a-skya-sence等等,这些实体同时也是一个个HTML标签,也就是DOM元素,所以我们可以很方便的利用类似document.querySelector('a-entity')语句来获取这些实体。

组件的写法和VUE中的写法很相似,定义有数据、事件、方法等。在HTML以标签的属性HTML attribute来体现:

<!-- `position` is the name of the position component. -->
<!-- `1 2 3` is the data of the position component. -->
<a-entity position="1 2 3"></a-entity>

注册一个组件:

// Registering component in foo-component.js
AFRAME.registerComponent('foo', {
  schema: {},
  init: function () {},
  update: function () {},
  tick: function () {},
  remove: function () {},
  pause: function () {},
  play: function () {}
});

使用一个组件

<!-- Usage of `foo` component. -->
<html>
  <head>
    <script src="aframe.min.js"></script>
    <script src="foo-component.js"></script>
  </head>
  <body>
    <a-scene>
      <a-entity foo></a-entity>
    </a-scene>
  </body>
</html>

开始编写关键代码

// Panorama.vue 页面
<template>
  <div class="page-panorama">
    <a-scene>
      <a-assets>
        <img id="sky" src="../assets/images/qj_01.jpg" alt="">
      </a-assets>
      <a-camera id="camera" position="0 1.6 0" fov="80" ref="camera"></a-camera>
      <a-sky src="#sky" ref="sky" radius="15"></a-sky>
    </a-scene>
  </div>
</template>

<script>
import 'aframe';
export default {
  name: 'Panorama'
}
</script>

a-assets是A-Frame内部的一套资源管理系统,存放场景中用到的各种资源,这里我们只用到了一幅全景图片qj_01.jpga-camera是我们架设的相机,它的位置position是坐标0 1.6 0,单位和Three.js中一样都是, a-sky是A-Frame自带的实体,本质上是一个巨大的球体,贴图在内表面,正好符合我们的需求。

demo.gif

demo传送

参考

墨卡托投影法

A-Frame文档

Responses ${replyToWho} / Cancel Reply