A-Frame.js 学习文档翻译(一)实体
A-Frame是什么
A-Frame是Mozilla 開源 web
虛擬現實框架,他能夠非常方便的創建VR視口,載入部分格式的模型,設置照相機等,這為對計算機圖形學不是很了解的同學,減輕了好多負擔。我分別用了threeJS和A-Frame.js做了兩個小項目,全英文文檔看的好累,就順便翻譯了部分文檔,之后會分享threeJS與模型導出與加載的一些坑。
A-Frame讓你構建場景,僅僅通過HTML ,然而對你使用JavaScript,three.js,和其他的WebAPI沒有限制,A-Frame使用一個采用的是一個實體-組件-系統的模式,使得他更加 的結構化,可延展,并且他不但是開源的,免費的,并且還是一個有著受歡迎的社區和完善工具與組件的生態系統。
Begin Example
以我的webVR自主裝修館為例,如何構建出圖中模型屋的場景?真的很簡單
<head><title>模板文件</title><meta name="keywords" content=""><meta name="description" content=""><!--引入aframe.js --> <script src="static/js/bundle/aframe.js"></script> </head> <!--場景標簽 他代表了整個場景的開始 是全局根物體,所有的實體(entity)都包含在場景里--> <a-scene><!--<a-assets>使用資源管理系統來緩存資源,為了更好的性能,這個標簽內的資源將會預加載緩存起來--> <a-assets><!--<a-asset-item>加載各種資源 比如3D模型或者材質 --> <a-asset-item id="floor-obj" src="fox.obj"></a-asset-item><!-- 加載圖片 --><img src="static/img/f1.jpg" id="f1-texture" alt=""> <img src="static/img/sky_sphere.jpg" id='sky-box' alt=""><!--加載視頻 --> <video id="video" src="video.mp4"></video></a-assets><!--相機 --> <a-camera fov="80"><a-cursor></a-cursor></a-camera><!--materialchange__floor 組件名,material材質與屬性細節 obj-model模型obj文件 --><a-entity materialchange__floor material="src: #f1-texture; metalness: 0.6;repeat:25;" id="floor" obj-model="obj: #floor-obj;"></a-entity><a-video src="#video"></a-video><!--天空盒 --> <a-sky color="#EEEEFF" material="src: #sky-box"></a-sky> </a-scene>entity-component-system
A-Frame采用實體-組件-系統模式,使用這個框架的時候,我們把燈光,模型,材質等都當做是一個實體,就是我們呈現在視覺上的主要元素,而component,組件類似vue,封裝可重用的代碼,為項目添加功能,從而組裝成一個系統
enrity 實體
A-Frame表現一個實體通過<a-entity>元素,作為定義在entity-component-system中的一個部分,這些實體是一個占位符,讓我們來插入組件,并提供他的外觀,行為和功能;
在A-Frame中,實體們的本質就是附加上位置,旋轉和大小的組件
Example 例子
<a-entity geometry="primitive: box" material="color: red"light="type: point; intensity: 2.0" id="mario"> var el = document.querySelector('#mario');如例所示,我們可以綁定組件給實體,讓他渲染或者做些什么,我們可以通過幾何(geometry)組件和材質(material)組件定義他形狀與外觀,可以使用燈光組件讓他發出燈光;我們可以通過DOM API輕松的得到一個實體,一旦我們拿到了這個實體,我們就能去控制他一些詳細的屬性和方法。
Properties 屬性
components
<a-entity>.components是附加在實體上的一個組件對象,這給我們一個途徑去取得這個實體的組件,包括每一個組件的數據,狀態和方法;
例如,如我我們要去取得threeJS里的照相機或者材質,我們可以這么去做:
var camera = document.querySelector('a-entity[camera]').components.camera.camera; var material = document.querySelector('a-entity[material]').components.material.material;或者一個組件所暴露的API
document.querySelector('a-entity[sound]').components.sound.pause();isPlaying
實體是否處于active或者playing狀態,如果我們pause這個實體,那么isPlaying將處于false狀態
object3D
<a-entity>.object3D is a reference to the entity’s three.js Object3D representation. More specifically, object3D will be a THREE.Group object that may contain different types of THREE.Object3Ds such as cameras, meshes, lights, or sounds:
// Gaining access to the internal three.js scene graph. var groupObject3D = document.querySelector('a-entity').object3D; console.log(groupObject3D.parent); console.log(groupObject3D.children);我們可以獲得不同類型的Object3Ds通過object3DMap,
object3DMap
一個實體的object3DMap 是一個對象,這個對象給了我們一個途徑去獲取不同類型的THREE.object3Ds(例如,相機,材質,燈光,聲音)
例如一個綁定了幾何和燈光組件的實體,他的object3DMap 應該是下面這個樣子
我們可以管理實體的THREE.Object3Ds通過getOrCreateObject3D, setObject3D, and removeObject3D.這些方法
sceneEl
一個實體有對其所屬場景元素的引用
var sceneEl = document.querySelector('a-scene'); var entity = sceneEl.querySelector('a-entity'); console.log(entity.sceneEl === sceneEl); // >> true.Methods 方法
addState (stateName) 添加狀態
addState將會給這個實體添加一個狀態,這個方法可以觸發stateadded 事件,并且我們可以檢查到是否我們處于這個狀態內
entity.addEventListener('stateadded', function (evt) {if (evt.detail.state === 'selected') {console.log('Entity now selected!');} }); entity.addState('selected'); entity.is('selected'); // >> trueemit (name, detail, bubbles) 觸發事件
emit觸發一個在實體上定制的DOM事件,例如,我們能夠觸發一個事件去觸發一個動畫。
// <a-entity> // <a-animation attribute="rotation" begin="rotate" to="0 360 0"></a-animation> // </a-entity> entity.emit('rotate');我們同樣能夠傳遞事件的細節或者數據通過第二個參數
entity.emit('collide', { target: collidingEntity });這個事件是默認冒泡的,我們可以讓他不要冒泡通過設置第三個參數為false
entity.emit('sink', null, false);flushToDOM (recursive) 刷新DOM
flushToDOM 將會手動序列化一個實體組件的數據并且更新DOM,更多詳細內容見 component-to-DOM serialization.
getAttribute (componentName) 獲取屬性
getAttribute 檢索解析組件的屬性,包含混入(mixin)的和默認的
// <a-entity geometry="primitive: box; width: 3"> entity.getAttribute('geometry'); // >> {primitive: "box", depth: 2, height: 2, translate: "0 0 0", width: 3, ...} entity.getAttribute('geometry').primitive; // >> "box" entity.getAttribute('geometry').height; // >> 2 entity.getAttribute('position'); // >> {x: 0, y: 0, z: 0}如果組件名是一個沒有注冊的組件,getAttribute將會正常運行
// <a-entity data-position="0 1 1"> entity.getAttribute('data-position'); // >> "0 1 1"getDOMAttribute (componentName)
getDOMAttribute只會檢索解析顯式定義在DOM的屬性或者通過setAttribute設置的屬性,如果componentName是已經注冊的組件,getDOMAttribute將只會返回定義在HTML的組件數據,以一個數組對象的形式,他是不包括混合值和默認值的
與getAttribute的輸出做一個比較:
// <a-entity geometry="primitive: box; width: 3"> entity.getDOMAttribute('geometry'); // >> { primitive: "box", width: 3 } entity.getDOMAttribute('geometry').primitive; // >> "box" entity.getDOMAttribute('geometry').height; // >> undefined entity.getDOMAttribute('position'); // >> undefinedgetObject3D (type)
getObject3D looks up a child THREE.Object3D referenced by type on object3DMap.
AFRAME.registerComponent('example-mesh', {init: function () {var el = this.el;el.getOrCreateObject3D('mesh', THREE.Mesh);el.getObject3D('mesh'); // Returns THREE.Mesh that was just created.} });getOrCreateObject3D (type, Constructor)
If the entity does not have a THREE.Object3D registered under type, getOrCreateObject3D will register an instantiated THREE.Object3D using the passed Constructor. If the entity does have an THREE.Object3D registered under type, getOrCreateObject3D will act as getObject3D:
AFRAME.registerComponent('example-geometry', {update: function () {var mesh = this.el.getOrCreateObject3D('mesh', THREE.Mesh);mesh.geometry = new THREE.Geometry();} });pause ()
pause()將會停止任何動畫或者組件定義的動態行為,當我們停止一個實體的時候,它將會停止他的動畫,并且調取這個實體上每個組件的Component.pause(),這個組件決定了發生什么當停止的時候,常常我們會移去事件監聽,一個實體被pause后,他的子實體也會被pause()
// <a-entity id="spinning-jumping-ball"> entity.pause();play ()
play()將會開始在動畫或者組件中定義的動態行為,當DOM附加上一個實體的時候,這就好自動調用他,當一個實體play(),這個實體的子實體被調用play()
entity.pause(); entity.play();例如,當播放聲音的時候,這個聲音組件會調用play()
setAttribute (attr, value, componentAttrValue)
如果屬性不是已經注冊的組件或者是單屬性組件,我們將會這樣來設置屬性
entity.setAttribute('visible', false);雖然attr是注冊的組件的名字,它可能需要對值做特殊的解析,例如,這個位置組件是一個單屬性組件,但是他的屬性解析器允許他為一個對象
entity.setAttribute('position', { x: 1, y: 2, z: 3 });設置多屬性組件數據,我們可以將注冊組件的名稱作為attr傳遞,并將屬性對象作為value傳遞:
entity.setAttribute('light', {type: 'spot',distance: 30,intensity: 2.0 });Updating Multi-Property Component Data 更新多屬性組件數據
為了更新多屬性組件的單個屬性,我們可以將注冊組件的名稱作為attr傳遞,屬性名作為第二個參數,并且將屬性值設置為第三個參數:
// All previous properties for the material component (besides the color) will be unaffected. entity.setAttribute('material', 'color', 'crimson');setObject3D (type, obj)
setObject3D will register the passed obj, a THREE.Object3D, as type under the entity’s object3DMap. A-Frame adds obj as a child of the entity’s root object3D.
AFRAME.registerComponent('example-orthogonal-camera', {
update: function () {
}
});
removeAttribute (attr, propertyName)
如果attr是注冊組件的名稱,除了要從DOM中刪除屬性,removeAttribute還將從實體中分離組件,調用組件的刪除生命周期方法。
entity.removeAttribute('goemetry'); // Detach the geometry component. entity.removeAttribute('sound'); // Detach the sound component.如果給定propertyName,removeAttribute將重置propertyName指定的屬性的屬性值為屬性的默認值:
entity.setAttribute('material', 'color', 'blue'); // The color is blue. entity.removeAttribute('material', 'color'); // Reset the color to the default value, white.removeObject3D (type)
removeObject3D removes the object specified by type from the entity’s THREE.Group and thus from the scene. This will update the entity’s object3DMap, setting the value of the type key to null. This is generally called from a component, often within the remove handler:
AFRAME.registerComponent('example-light', {update: function () {this.el.setObject3D('light', new THREE.Light());// Light is now part of the scene.// object3DMap.light is now a THREE.Light() object.},remove: function () {this.el.removeObject3D('light');// Light is now removed from the scene.// object3DMap.light is now null.} });removeState (stateName)
removeState將從實體中彈出一個狀態。這將會觸發stateremoved事件,我們可以檢查它的刪除狀態。
entity.addEventListener('stateremoved', function (evt) {if (evt.detail.state === 'selected') {console.log('Entity no longer selected.');} }); entity.addState('selected'); entity.is('selected'); // >> true entity.removeState('selected'); entity.is('selected'); // >> falseEvents 事件
總結
以上是生活随笔為你收集整理的A-Frame.js 学习文档翻译(一)实体的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用UltraISO为U盘或内存卡制作系
- 下一篇: 【1】ASP.NET异步(1)