A-Frame中文教程

HTML和A-Frame原语(Primitives)

本节将覆盖A-Frame原语元素的基本概念以及它们与实体-组件框架的关系。如果你需要了解具体如何使用HTML和原语,可以参阅: 开发指南中构建一个基本场景一节

HTML

A-Frame基于 HTML DOM,对于自定义元素使用一个polyfill。HTML是Web的基石,提供了最容易访问的计算机语言。无需安装或编译构建,创建HTML只需要使用文本, 然后在浏览器中打开该HTML文件。由于A-Frame基于HTML,因此大多数现有的工具和库的工作框架,包括React,Vue.js,Angular,d3.js,jQuery都能够和A-Frame一起工作。

HTML Scene

如果你没有HTML的基础,可以阅读我们的HTML5免费在线教程

HTML

原语(Primitives)

尽管HTML层看起来很基础,HTML和DOM只是A-Frame的表面抽象层。其内部实现上,A-Frame实际上是一个实体-组件(entity-component)框架,基于three.js并以声明的方式来暴露编程接口。

A-Frame提供一些简单易用的标签元素如 <a-box><a-sky>,这些被称之为 原语(primitives),实际上是实体-组件模式的封装,使其对于初学者容易使用。在文档左侧导航栏的底部,我们可以看到包含所有现成可用的原语的列表。开发人员当然也可以创建他们自己的原语。

实例

下面是一个使用了若干基本A-Frame原语的例子程序,创建网孔模型,渲染360°内容,定制环境,放置相机等:

底层机制

原语主要是为 新手提供一个易用的语法封装层(即语法糖)。我们现在只要记住原语是一个具备如下特征的<a-entity>

原语(Primitives)和Unity中的prefabs类似。实体-组件-系统模式中的一些用词被引用为组合(assemblages)。 它们把核心的实体-组件API抽象为:

在底层实现中,这个 <a-box> 原语为:

<a-box color="red" width="3"></a-box>

表示如下实体组件形式:

<a-entity geometry="primitive: box; width: 3" material="color: red"></a-entity>

<a-box>geometry.primitive 属性被设置为缺省值 box。并且该原语映射HTML width 属性为底层的 geometry.width 属性,同样的HTML color 属性被映射为底层的 material.color 属性。

将组件附加到原语

原语(Primitive)本质上就是一个 <a-entity>。这意味这原语拥有和实体一样的应用程序接口,比如定位(positioning), 旋转(rotating), 缩放(scaling), 和附加组件(attaching components)。

实例

本例中我们将A-Frame社区贡献的物理(physics)组件附加到原语。来自Don McCurdy所写的 aframe-physics-system 并通过HTML属性附加到原语上:

<html>
<head>
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-physics-system@1.4.0/dist/aframe-physics-system.min.js"></script>
</head>
<body>
<a-scene physics>
<a-box position="-1 4 -3" rotation="0 45 0" color="#4CC3D9" dynamic-body></a-box>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" static-body></a-plane>
<a-sky color="#ECECEC"></a-sky>
</a-scene>
</body>
</html>

注册一个原语

我们可以使用 AFRAME.registerPrimitive(name, definition) 方法来注册一个原语(也就是注册一个元素)。其中 definition 参数是一个JavaScript对象,定义了如下属性:

Property Description Example
defaultComponents 指定原语默认组件的对象。键是组件的名称,值是组件的默认数据。 {geometry: {primitive: 'box'}}
mappings 指定HTML属性名和组件属性名称之间映射的对象。每当更新HTML属性(attribute)时,原语将更新相应的组件属性(property)。组件属性通过一个点语法来定义:${componentName}.${propertyName} {depth: 'geometry.depth', height: 'geometry.height', width: 'geometry.width'}

实例

比如,下面是A-Frame中 <a-box> 原语的注册代码:

var extendDeep = AFRAME.utils.extendDeep;
// The mesh mixin provides common material properties for creating mesh-based primitives.
// This makes the material component a default component and maps all the base material properties.
var meshMixin = AFRAME.primitives.getMeshMixin();
AFRAME.registerPrimitive('a-box', extendDeep({}, meshMixin, {
// Preset default components. These components and component properties will be attached to the entity out-of-the-box.
defaultComponents: {
geometry: {primitive: 'box'}
},
// Defined mappings from HTML attributes to component properties (using dots as delimiters).
// If we set `depth="5"` in HTML, then the primitive will automatically set `geometry="depth: 5"`.
mappings: {
depth: 'geometry.depth',
height: 'geometry.height',
width: 'geometry.width'
}
}));

比如,Don McCurdy写的 aframe-extras 软件包中包含了一个 <a-ocean> 原语,该原语封装了其中的 ocean 组件。下面是 <a-ocean> 的定义:

AFRAME.registerPrimitive('a-ocean', {
// Attaches the `ocean` component by default.
// Defaults the ocean to be parallel to the ground.
defaultComponents: {
ocean: {},
rotation: {x: -90, y: 0, z: 0}
},
// Maps HTML attributes to the `ocean` component's properties.
mappings: {
width: 'ocean.width',
depth: 'ocean.depth',
density: 'ocean.density',
color: 'ocean.color',
opacity: 'ocean.opacity'
}
});

通过注册 <a-ocean> 原语,我们将可以像普通HTML标签一样来创建一个海洋对象:

<a-ocean color="aqua" depth="100" width="100"></a-ocean>