三、核心概念:ECS 架构
A‑Frame 的核心是其内部的实体-组件-系统(ECS)架构。理解 ECS 是掌握 A‑Frame 的关键。
3.1 什么是 ECS
在 ECS 架构中,一个对象不再由一个巨大的类来定义,而是由多个可以自由组合的小型“零件”拼装而成。
Entities(实体):简单的容器对象,是空盒子,本身不做任何事情。
Components(组件):可复用的数据模块,可以附加到实体上,为实体提供外观、行为或功能。
Systems(系统):为组件提供全局服务和管理,处理跨实体的逻辑。
A‑Frame 将 ECS 模式提升到了一个新高度,使其基于 DOM 且是声明式的。这种架构具有以下优势:
通过混合和匹配可重用部件,定义对象时具有更大的灵活性
消除了具有复杂交织功能的长继承链问题
通过解耦、封装、模块化和可重用性促进清洁设计
构建 VR 应用在复杂性方面最具可扩展性的方式
3.2 Entity(实体)
在 A‑Frame 中,使用 元素来定义实体。实体是场景中所有对象的基础,它是一个通用的、可扩展的容器。
空实体:
<!-- 一个空的实体,它本身不可见也不可交互 -->
<a-entity></a-entity>
实体的固有属性:每个实体天生都具有位置(position)、旋转(rotation)和缩放(scale)属性:
<!-- 一个设置了位置和旋转的实体 -->
<a-entity position="0 1 -3" rotation="0 45 0" scale="1 1 1"></a-entity>
组件化实体:实体的真正威力来自于可以通过 HTML 属性向其附加组件:
<!-- 实体 + 组件 = 有外观和行为的对象 -->
<a-entity geometry="primitive: box; width: 1; height: 1; depth: 1"
material="color: red; roughness: 0.2"
position="0 1 -3">
</a-entity>
关键理解:组件是附加在实体上的可复用模块,为实体提供外观、行为和/或功能。组件就像插头,实体就像插座。
3.3 Component(组件)
组件是 ECS 架构中的核心要素。在 A‑Frame 中,组件通过 HTML 属性附加到实体上,组件的值决定了实体的具体表现。
单属性组件:如果组件只有一个属性,其值看起来像普通的 HTML 属性:
<!-- position 是组件名,1 2 3 是组件数据 -->
<a-entity position="1 2 3"></a-entity>
多属性组件:如果组件有多个属性,值的格式类似于内联 CSS 样式:
<!-- light 是组件名,包含 type、color 等属性 -->
<a-entity light="type: point; color: crimson; intensity: 1.5"></a-entity>
原语(Primitives)的本质:A‑Frame 提供的 等标签本质上是预置了特定组件的“快捷方式”。 实际上是一个已经附加了 geometry="primitive: box" 和基础 material 组件的 。
3.4 System(系统)
系统为特定类别的组件提供全局范围的服务和管理。系统通常是可选的,但可以用来分离逻辑和数据——系统处理逻辑,组件充当数据容器。
四、核心组件详解
4.1 几何体(geometry)组件
geometry 组件定义了实体的形状:
<!-- 盒子(立方体) -->
<a-entity geometry="primitive: box; width: 2; height: 1; depth: 1"></a-entity>
<!-- 球体 -->
<a-entity geometry="primitive: sphere; radius: 1.5"></a-entity>
<!-- 圆柱体 -->
<a-entity geometry="primitive: cylinder; radius: 0.8; height: 2"></a-entity>
<!-- 环面结(复杂形状) -->
<a-entity geometry="primitive: torusKnot; radius: 1; radiusTubular: 0.2"></a-entity>
<!-- 平面 -->
<a-entity geometry="primitive: plane; width: 4; height: 4"></a-entity>

4.2 材质(material)组件
material 组件定义了物体表面的外观:
<!-- 基础颜色材质 -->
<a-entity geometry="primitive: sphere" material="color: #FF5500"></a-entity>
<!-- 带粗糙度和金属度的材质(PBR 材质) -->
<a-entity geometry="primitive: box"
material="color: steelblue; roughness: 0.3; metalness: 0.7"></a-entity>
<!-- 使用图片纹理 -->
<a-entity geometry="primitive: plane"
material="src: url(texture.jpg); repeat: 2 2"></a-entity>
<!-- 使用视频纹理(用于在物体表面播放视频) -->
<a-entity geometry="primitive: sphere"
material="src: url(video.mp4); color: white"></a-entity>
<!-- 线框材质(只显示边框) -->
<a-entity material="wireframe: true; color: red"></a-entity>

4.3 相机(camera)组件
相机决定了用户观察场景的视角:
<!-- 默认相机(A‑Frame 自动添加) -->
<a-camera></a-camera>
<!-- 自定义位置的相机 -->
<a-camera position="0 2 5"></a-camera>
<!-- 禁用键盘移动 -->
<a-camera wasd-controls="enabled: false"></a-camera>
<!-- 高视野相机 -->
<a-camera fov="90"></a-camera>

4.4 光源(light)组件
光源系统模拟现实世界的光照效果,让物体产生明暗和阴影:
<!-- 环境光:均匀照亮,无方向 -->
<a-light type="ambient" color="#404040" intensity="0.5"></a-light>
<!-- 平行光:模拟太阳,从固定方向照射 -->
<a-light type="directional" color="white" intensity="1" position="5 10 3"></a-light>
<!-- 点光源:从一点向四周发光,类似灯泡 -->
<a-light type="point" color="red" intensity="0.8" position="2 1 3"></a-light>
<!-- 聚光灯:产生光束效果,可用于手电筒 -->
<a-light type="spot" color="blue" intensity="1" position="0 5 0" target="0 0 -5"></a-light>
4.5 天空盒(sky)组件
天空盒是 3D 世界的背景,可以是纯色、全景图片或 360° 视频:
<!-- 纯色背景 -->
<a-sky color="#DDDDDD"></a-sky>
<!-- 全景图片作为天球背景 -->
<a-sky src="panorama.jpg"></a-sky>
<!-- 带旋转的天空盒 -->
<a-sky src="sky.jpg" rotation="0 -45 0"></a-sky>
4.6 动画(animation)组件
animation 组件可以为实体的属性创建动画效果:
<!-- 持续旋转的立方体 -->
<a-box position="0 1 -3" color="#FF0000"
animation="property: rotation; to: 0 360 0; loop: true; dur: 4000">
</a-box>
<!-- 带缓动效果的缩放动画 -->
<a-box position="2 1 -3" color="#00FF00"
animation="property: scale; from: 1 1 1; to: 1.5 1.5 1.5;
dir: alternate; loop: true; dur: 1000; easing: easeInOutQuad">
</a-box>
<!-- 位置移动动画 -->
<a-box position="-2 1 -3" color="#0000FF"
animation="property: position; to: -2 2 -3; dir: alternate; loop: true; dur: 2000">
</a-box>
4.7 音效(sound)组件
sound 组件为实体添加音频能力:
<!-- 点击时播放音效 -->
<a-box sound="on: click; src: url(click.mp3)"></a-box>
<!-- 循环播放的背景音乐 -->
<a-box sound="src: url(bgm.mp3); autoplay: true; loop: true"></a-box>