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的基础,可以阅读我们的 HTML5 免费在线教程。
原语(Primitives)
尽管HTML层看起来很基础,HTML和DOM只是A-Frame的表面抽象层。其内部实现上,A-Frame实际上是一个实体-组件(entity-component)框架,基于three.js并以声明的方式来暴露编程接口。
A-Frame提供一些简单易用的标签元素如 <a-box>
和 <a-sky>
,这些被称之为 原语(primitives),实际上是实体-组件模式的封装,使其对于初学者容易使用。在文档左侧导航栏的底部,我们可以看到包含所有现成可用的原语的列表。开发人员当然也可以创建他们自己的原语。
实例
下面是一个使用了若干基本A-Frame原语的例子程序,创建网孔模型,渲染360°内容,定制环境,放置相机等:
底层机制
原语主要是为 新手提供一个易用的语法封装层(即语法糖)。我们现在只要记住原语是一个具备如下特征的<a-entity>
:
- 有语义名称(比如:
<a-box>
) - 有默认值预设绑定组件
- 映射或代理HTML属性到组件数据
原语(Primitives)和Unity中的prefabs类似。实体-组件-系统模式中的一些用词被引用为组合(assemblages)。 它们把核心的实体-组件API抽象为:
- 预先组成有用的组件连同规定的默认值
- 用作复杂但常用的实体类型的速写方式(比如:
<a-sky>
) - 为初学者提供一个类似HTML标签的编程接口
在底层实现中,这个 <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/1.1.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> |