翻译作者: 在上一篇文章中,我们讨论了A-Frame的基本概念。 为了继续这个周期,我想开一堂课来说明A-Frame的主要功能,但我意识到最好从官方网站翻译该文章,我认为这是写得很好的,重复这样的文章根本没有意义。
让我们在A-Frame中创建一个基本场景,以了解该框架的工作原理。 我们需要对HTML有初步了解。 在本课程中,我们将学习:
- 如何使用原语添加3D对象;
- 如何借助运动,旋转和缩放在3维空间中变换对象;
- 如何添加环境;
- 如何添加纹理;
- 如何通过事件和动画添加基本的交互性
- 如何添加文字。
您可以在此处使用代码让我们从HTML开始
<html> <head> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> </head> <body> <a-scene> </a-scene> </body> </html>
我们通过添加到<head>部分的<script>标签连接A形框架。 库代码在CDN上。
必须在 <a-scene> 之前添加 A-Frame连接,因为A-Frame会注册必须在<a-scene>添加到DOM之前定义的自定义HTML元素,否则场景将保持空白。
接下来,我们将<a-scene>标记添加到<body>文档的正文中。 <a-scene>是控制场景的元素。 通过将元素添加到<a-scene>,我们将它们添加到实际的3D场景中。 <a-scene>负责您所需的一切:在HTC Vive,Oculus Rift,Samsung GearVR等平台上安装WebGL,<canvas>,相机,光源,渲染器(抽屉)以及与WebVR支持相关的所有内容, Oculus Go和Google Cardboards。
新增物件
使用<a-scene>,我们使用标准A-Frame原语(例如<a-box>)添加3D对象。 我们可以像使用常规HTML元素一样使用<a-box>,向其中添加属性以进行自定义。 以下是A框架中可用的其他一些标准原语:<a-cylinder>,<a-plane>,<a-sphere>。
在下面的代码示例中,我们将添加颜色<a-box>。 可以在
此处找到<a-box>的更多属性。

应该注意的是,A-Frame中的原语只是某些组件的包装。 这很方便,但是您需要了解在<a-box>下的是<a-entity>,其中包含几何和材料成分:
<a-entity id="box" geometry="primitive: box" material="color: red"></a-entity>
无论如何,由于摄像机和添加到场景中的多维数据集位于同一点
0,0,0 ,因此,除非更改其位置,否则我们将无法看到该多维数据集。 要做到这一点很简单:您只需要更改position属性即可在空间中移动多维数据集。
以3D形式转换对象
让我们先谈谈3D空间。 A框架使用右手坐标系。 摄像头的默认方向是:X轴正向右侧,Y轴正向上,Z轴正从屏幕向我们返回:

由于WebVR API返回以米为单位的位置和姿势数据,因此A帧以米为单位测量距离(而不是像React360中的像素)。 设计VR场景时,考虑对象的实际大小非常重要。 在我们的计算机屏幕上,一个10米高的立方体看起来很正常,但是当浸入虚拟现实中时,它将太大。
A帧旋转单位是度(不是Three.js中的弧度),因此当它们到达Three.js时将自动转换为弧度。 右手法则用于确定旋转的正方向。 将右手的手指指向任何轴的正方向,然后将手指弯曲的方向指向正旋转方向。
要移动,旋转或缩放立方体,我们可以分别更改
position ,
rotation和
scale分量(由<a-box>标记的属性表示)。 让我们开始应用旋转和缩放:
<a-scene> <a-box color="red" rotation="0 45 45" scale="2 2 2"></a-box> </a-scene>
这应该以给定的角度旋转立方体,并在所有轴上拉伸两次。
祖先和后代的转变
A框架中
的场景图是使用HTML实现的。 这种结构的每个元素可以有几个后代,只有一个祖先。 这种结构中的任何后代都继承其祖先的变换属性(位置,旋转,比例)。
例如,我们可以添加一个球体作为立方体的后代:
<a-scene> <a-box position="0 2 0" rotation="0 45 45" scale="2 4 2"> <a-sphere position="1 0 3"></a-sphere> </a-box> </a-scene>
球在场景中的位置将是
1 2 3 ,而不是
1 0 3 ,因为默认情况下,球在其祖先的坐标中,即立方体为
0 2 0 。 在这种情况下,该点将成为坐标为
1 0 3的球的参考点。 旋转和比例尺也是如此。 如果更改了多维数据集的任何属性,则此更改将自动影响所有后代(在我们的示例中是作用域)。
如果将圆柱体添加为球体的后代,则将基于其祖先(立方体和球体)的变换来计算圆柱体的变换。
我们将立方体放在镜头前
现在,让我们的立方体对摄像机可见。 我们可以在Z轴上向负方向(即远离我们)移动立方体5米。 我们也将其沿Y轴升高两米,所有这些都可以通过更改position属性来完成:
<a-scene> <a-box color="red" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> </a-scene>
现在我们看到他! 雨湖!

管理学
对于平板显示器(笔记本电脑,计算机),默认情况下,通过拖动鼠标和WASD或键盘上的箭头来控制摄像机。 在手机中,加速度计负责这一点。 尽管A-Frame是WebVR的框架,但它支持这些控制方案,因此无需虚拟现实头盔即可观看场景。

如果您使用虚拟现实头盔,则将使用控制器和头盔进行控制。 要从头盔的浏览器进入虚拟现实,您需要单击带有虚拟现实头盔图像的图标,该图标位于右下角。 如果您使用具有6个自由度的头盔,并且您拥有真实的空间,则可以在创建的场景中实际走动。
添加环境
使用A-Frame,开发人员可以创建和共享易于在其项目中使用的组件。 迭戈·戈伯恩(Diego Gobern)创建
的环境组件可生成各种环境,而所有这些只需一行代码即可实现! 环境组件是为我们的BP应用程序创建可视平台的一种简便的方法。 它允许您创建许多环境,这些环境可以通过大量参数进行自定义。
首先,您需要将脚本连接到A-Frame之后的部分:
<head> <script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script> <script src="https://unpkg.com/aframe-environment-component/dist/aframe-environment-component.min.js"></script> </head>
之后,已经在场景中,您需要添加带有环境属性和指定设置的<a-entity>标签,让它成为具有200棵树的森林(forest):
<a-scene> <a-box color="red" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> <a-entity environment="preset: forest; dressingAmount: 200"></a-entity> </a-scene>
注意 :请记住,当使用弱电烙铁时,这样的场景会变慢。 例如,这可能发生在Oculus Go等移动设备上。 因此,如果您支持移动设备,请注意生成的对象的数量。
应用纹理
就像使用常规标记一样,我们可以使用src属性使用图像,视频或画布将纹理应用于立方体。 我们还需要删除color =“ red”,因为使用纹理时颜色仍然不会显示。
<a-scene> <a-box src="https://i.imgur.com/mYmmbrp.jpg" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> <a-sky color="#222"></a-sky> </a-scene>
现在我们应该已经看到我们的多维数据集已经在线加载了纹理。

我们使用文件上传系统
为了提高A-Frame应用程序的性能,建议您使用
文件上传管理系统 。 该系统允许浏览器缓存不同的文件(图像,视频,3D模型)。 A-Frame负责确保在渲染之前下载所有这些文件。
如果我们在<a-assets>中编写标签,则A-Frame将不会像通常的HTML那样显示它,它将处理源并将其发送到Three.js。 重要的是要注意,一旦上传图像,我们就可以在任何地方使用它,例如作为纹理。 A-Frame还可以解决跨域以及与通过网络传输文件相关的其他可能的问题。
要使用文件上传控制系统添加纹理,您需要:
- 在<a-scene>标记内添加<a-assets >标记(到第一级)
- 添加<img>标签 ,src属性应包含图像文件链接(以及通常的HTML)
- 您需要为img标签设置id属性。 理想情况下,它应该描述纹理本身(例如,id =“ boxTexture”)
- 为应包含该对象的对象添加src属性。 例如,对于<a-box src =“#boxTexture”>
<a-scene> <a-assets> <img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg"> </a-assets> <a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> <a-sky color="#222"></a-sky> </a-scene>
创建一个任意环境
我们已经讨论了上面的环境组件。 它是自动生成的。 但是,如果我们需要建立自己的环境:添加云,地球和其他物体怎么办? 我建议进一步讨论。
为场景添加背景图像。
为了在A帧中为场景添加背景图像,有一个特殊的
<a-sky>元素。 <a-sky>允许您同时添加纯色和360图像或视频。 例如,要添加深灰色背景,您需要编写以下代码:
<a-scene> <a-box color="red" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> <a-sky color="#222"></a-sky> </a-scene>
或者我们可以使用360度照片:
<a-scene> <a-assets> <img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg"> <img id="skyTexture" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/sechelt.jpg"> </a-assets> <a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> <a-sky src="#skyTexture"></a-sky> </a-scene>
加地
要添加地面,我们将使用<a-plane>元素。 默认情况下,A框架中的平面与XY轴平行。 为了使平面平行于地球,我们需要旋转平面,使其平行于XZ轴。 这可以通过沿X轴旋转-90°平面来完成。
<a-plane src="#groundTexture" rotation="-90 0 0" width="30" height="30" repeat="10 10"></a-plane>
在光下工作
要更改场景的照明,我们可以添加或重新配置
<a-light>元素。 默认情况下,我们没有任何光源,但是A框架本身会添加环境光和定向光。 如果A-Frame没有添加这些光源,则场景将是全黑的。 如果我们添加自己的光源,默认情况下将删除A-Frame添加的那些光源。
我们将添加一个漫射光源,该光源具有蓝绿色调(与天空协调)。 散射光应该落在场景的所有元素上(当然,如果它们具有材质,但是默认情况下是这样)。
我们还将添加一个点光源。 点光源就像灯泡。 这种光源的照明效果将完全取决于到物体的距离。
<a-scene> <a-assets> <img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg"> <img id="skyTexture" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/sechelt.jpg"> <img id="groundTexture" src="https://cdn.aframe.io/a-painter/images/floor.jpg"> </a-assets> <a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2"></a-box> <a-sky src="#skyTexture"></a-sky> <a-light type="ambient" color="#445451"></a-light> <a-light type="point" intensity="2" position="2 4 4"></a-light> </a-scene>
添加动画
我们有机会使用内置
动画系统A-Frame添加动画。 动画会随着时间改变某些值(组件属性)。 我们只需要添加<a-animation>元素作为某个对象的后代,例如<a-box>。 让我们尝试对立方体进行动画处理,以使其上下移动。
<a-scene> <a-assets> <img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg"> </a-assets> <a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2"> <a-animation attribute="position" to="0 2.2 -5" direction="alternate" dur="2000" repeat="indefinite"></a-animation> </a-box> </a-scene>
我们说<a-animation>:
- 设置位置属性的动画。
- 设置为0 2.2 -5的动画,该动画比原始位置高20厘米。
- 在每个循环上更改动画的方向。
- 动画循环将花费2秒(2000毫秒)。
- 无休止地重复动画。

其他细节
<a-animation>使用A帧渲染周期,因此对象属性的每次更改每帧发生一次。 如果您需要更多控制权并希望手动更改值,则可以编写一个带有tick回调和一个库(例如Tween.js)的A-Frame组件(顺便说一下,可通过AFRAME.TWEEN链接使用该库)。 为了获得最佳性能,应在A-Frame级别上执行逐帧操作,如果A-Frame
已具有它 ,则无需创建自己的
requestAnimationFrame函数。
增加互动
让我们添加与多维数据集交互的功能:当我们查看它时,我们将增加它的大小,单击它时,它将绕其轴滚动。
假设大多数开发人员没有带控制器的VR头盔,我们将集中精力使用基本组件在计算机和移动设备上输入-
光标 。 光标提供了通过移动设备向导和鼠标单击计算机上的对象来“单击”对象的功能。 但是您需要了解,光标只是交互的一种方式,如果我们有真正的VR控制器,一切都会有所不同。
要将光标附加到相机,我们需要将其作为后代添加到相机元素(<a-camera>)。
由于我们尚未识别相机,因此A-Frame会自动执行此操作。 但是由于我们需要向摄像机添加光标,因此我们将手动定义<a-camera>并在其中添加<a-cursor>:
<a-scene> <a-assets> <img id="boxTexture" src="https://i.imgur.com/mYmmbrp.jpg"> </a-assets> <a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2"> <a-animation attribute="position" to="0 2.2 -5" direction="alternate" dur="2000" repeat="indefinite"></a-animation> </a-box> <a-camera> <a-cursor></a-cursor> </a-camera> </a-scene>
如果查看
游标的
文档 ,我们会看到它处理悬停事件,例如mouseenter,mouseleave以及click事件。
事件监听器组件
处理光标事件的一种方法是
通过JavaScript添加事件侦听器,就像通常的DOM元素一样。 如果不确定JavaScript的知识,可以跳过本节,直到下一节。
在
JavaScript中,我们通过querySelector并使用
addEventListener和setAttribute获取元素,以在悬停时增加多维数据集的大小。 注意:A-Frame修改了setAttribute,以便它可以一次与多个组件一起使用。 我们可以添加{x,y,z}作为第二个参数。
<script> var boxEl = document.querySelector('a-box'); boxEl.addEventListener('mouseenter', function () { boxEl.setAttribute('scale', {x: 2, y: 2, z: 2}); }); </script>
但是更快的方法是将逻辑封装在A-Frame组件内。 此方法不需要等待场景加载,我们不需要使用选择器,因为组件为我们提供了上下文:
<script> AFRAME.registerComponent('scale-on-mouseenter', { schema: { to: {default: '2.5 2.5 2.5'} }, init: function () { var data = this.data; this.el.addEventListener('mouseenter', function () { this.setAttribute('scale', data.to); }); } }); </script>
我们可以通过HTML属性添加此组件:
<script> AFRAME.registerComponent('scale-on-mouseenter', { </script> <a-scene> <a-box src="#boxTexture" position="0 2 -5" rotation="0 45 45" scale="2 2 2" scale-on-mouseenter="to: 2.2 2.2 2.2"> <a-animation attribute="position" to="0 2.2 -5" direction="alternate" dur="2000" repeat="indefinite"></a-animation> </a-box> </a-scene>
活动动画
<a-animation>具有在对象产生事件时开始和结束动画的能力。 可以通过指定事件的名称通过begin属性来完成。
我们可以为光标组件添加两个动画
-mouseenter和
onemouseleave事件以调整立方体的大小,并通过click事件将立方体绕Y轴旋转:
<a-box color="#FFF" width="4" height="10" depth="2" position="-10 2 -5" rotation="0 0 45" scale="2 0.5 3" src="#texture"> <a-animation attribute="position" to="0 2.2 -5" direction="alternate" dur="2000" repeat="indefinite"></a-animation> <a-animation attribute="scale" begin="mouseenter" dur="300" to="2.3 2.3 2.3"></a-animation> <a-animation attribute="scale" begin="mouseleave" dur="300" to="2 2 2"></a-animation> <a-animation attribute="rotation" begin="click" dur="2000" to="360 405 45"></a-animation> </a-box>
添加音频
音频对于完全融入虚拟现实非常重要。 即使仅在背景中添加白噪声也可能需要一些时间。 我们建议为每个场景使用声音。 添加声音的一种方法:将<audio>元素添加到<a-assets>和autoplay属性:
<a-scene> <a-assets> <audio src="https://cdn.aframe.io/basic-guide/audio/backgroundnoise.wav" autoplay preload></audio> </a-assets> </a-scene>
或者我们可以使用<a-sound>元素添加空间音频。 当我们靠近声源时,此组件会使声音变大。 我们可以使用position属性来定位<a-sound>:
<a-scene> <a-sound src="https://cdn.aframe.io/basic-guide/audio/backgroundnoise.wav" autoplay="true" position="-3 1 -4"></a-sound> </a-scene>
新增文字
A框架具有文本组件。 有几种显示方法,每种方法都有其优点和缺点。 A-Frame通过三bmfont文本实现了SDF实现,这非常有效。
在本课程中,我们建议使用最简单的文本形式<a-text>:
<a-text value="Hello, A-Frame!" color="#BBB" position="-0.9 0.2 -3" scale="1.5 1.5 1.5"></a-text>
还有其他添加文本的方法:
- 文字几何由Kevin Ngo制作。 这是3D文本,需要更多资源进行渲染。
- Mayo Tobit制造的HTML Shader-将文本渲染为纹理。 它的样式很容易,但计算时间很长。
结论
您可以在
此处使用代码。 您可以在
此处实时观看现场。
来自第一封信的作者:谢谢大家的关注!
在下一篇文章中,我将尝试谈谈我在A-Frame上创建游戏的经验:在开发过程中等待着我的所有微妙和困难。