最近幾年,虛擬現實VR的概念火了一把,各類VR概念的遊戲、設備、視頻受到人們的普遍關注。筆者在逛商場的時候也常常會看到有VR設備體驗的地方讓遊人體驗一把,各類酷炫的頭盔和酷炫的設備着實抓人眼球。可是做爲一個前端工做者,咱們確定也但願在咱們的網頁裏也能看到這麼酷炫的效果,不經意間在網上發現了一個網頁虛擬現實框架A-Frame,分享一下筆者的使用心得。html
A-Frame是Mozilla發佈的一個全新的開源框架,旨在幫助開發者開發在瀏覽器中運行的高性能響應式的VR體驗。只須要在頁面中引入aFrame.min.js
就可以集成支持VR頁面所須要的組件了。前端
咱們可使用傳統的JavaScript DOM API來操縱A-Frame場景來添加邏輯,行爲和功能。同時,A-Frame是基於DOM的,如今一些流行的框架可以基於A-Frame工做,好比React、Vue、jQuery和Angular。git
A-Frame是一個基於three.js的實體組件系統。在A-Frame裏一切都是實體,咱們插入組件,能夠隨意撰寫外觀,行爲和功能集成。github
A-Frame配備了多個組件,但因爲A-Frame在其核心部分是徹底可擴展的,社區已經爲生態系統填充了許多組件,如物理,粒子系統,音頻可視化和Leap Motion控件。這個生態系統是A-Frame的命脈。開發人員能夠構建一個組件併發布它,而後其餘人可使用該組件並直接從HTML使用,甚至沒必要知道任何JavaScript。數組
可視化編輯器用於檢查和編輯A框架場景的可視化工具。與瀏覽器的DOM檢查器相似,您能夠進入任何A-Frame場景,本地或Web上,而後點擊ctrl+alt+i
鍵盤。 這將打開視覺檢查器,咱們能夠在其中進行更改。能夠在視覺上移動和放置物體,用組件的屬性隨意的挪動物體,或者圍繞相機平移以查看場景的不一樣視圖。瀏覽器
介紹了這麼多,讓咱們來看一下A-Frame是如何來構造組件的。bash
一個場景是由a-scene建立的,是全景渲染的根對象,全部的元素都須要放在a-scene這個組件裏。它會處理3D所需的全部設置:設置WebGL、畫布、相機、燈光、渲染器、渲染循環以及開啓及時的WebVR支持。併發
每個場景都須要一個背景,a-sky
標籤用來設置場景的背景,能夠直接放置src爲全景圖片,或者直接渲染color值。app
<a-scene>
<a-sky color="#ccc" src="images/panorama.jpg"></a-sky>
</a-scene>
複製代碼
若是直接渲染了color值,那麼整個背景就會變成該顏色;若是設置全景圖片,能夠左右移動來查看。效果連接戳這裏。框架
咱們經過a-box
標籤來生成一個長方體,有一下幾個重要的屬性:
<a-scene>
<a-sky color="#f0f0f0"></a-sky>
<a-box color="red" depth="1" height="1" width="1" position="0 2 -5" rotation="0 45 45" scale="1 1 1">
</a-box>
</a-scene>
複製代碼
最後生成一個長1高1深1顏色爲紅色的長方體:
可是若是僅僅是紅色的外觀那麼就太單調了。A-Frame容許咱們給組件設置紋理圖片,雖然能夠直接給組件設置src屬性,不過不推薦這種作法,推薦經過資源管理系統a-assets
。 通常在遊戲等視覺體驗豐富的場景中,因爲有着大量的圖片、模型、聲音等資源,都會對這些資源進行一個預加載處理,確保在渲染的時候不會出現缺失的現象。 咱們把這些資源放到a-assets
也是爲了進行預加載。咱們能夠存放如下資源:
<a-asset-item>
:其餘資產,如3D模型和材料<audio>
:聲音文件<img>
:圖像紋理<video>
:視頻紋理咱們經過給資源標誌一個惟一的id,而後在組件的src中引用這個id來進行調用。
<a-box src="#boxTexture" depth="1" height="1" width="1" position="0 2 -5" rotation="0 45 45" scale="1 1 1">
</a-box>
複製代碼
這樣咱們的長方體就變成了一個帶有圖案紋理的長方體。
咱們能夠經過使用a-light來改變場景的亮度。默認狀況下,若是咱們沒有指定任何指示燈,A-Frame將添加環境光和定向光。若是A-Frame沒有爲咱們添加燈,場景將是黑色的。一旦咱們添加了咱們本身的燈,默認的照明設置將被刪除,並替換爲咱們的設置。 咱們還會添加一個點光源,點光源就像燈泡; 咱們能夠將它們放在場景周圍,點光源對實體的影響取決於它與實體的距離。
<! - 紅色定向燈從左上方閃爍。 - >
<a-light color="red" position="-1 1 0"></a-light>
<! - 藍點光,5米空中。 - >
<a-light tpye="point" color="blue" position="0 5 0"></a-light>
<! - 昏暗環境照明。 - >
<a-light type="ambient" color="yellow"></a-light>
複製代碼
咱們給環境一個黃色照明的光源,最後的效果是這樣的。
咱們可使用A-Frame的內置動畫系統<a-animation>
向盒子添加動畫。咱們能夠將<a-animation>
元素做爲實體的子代。讓咱們把盒子上下襬動來給場景添加一些動做。
<a-box src="#boxTexture" depth="1" height="1" width="1" position="0 2 -5" rotation="0 45 45" scale="1 1 1">
<!-- 在box裏面添加animation元素 -->
<a-animation attribute="position" to="0 1 -5" direction="alternate" dur="2000" repeat="indefinite">
</a-animation>
</a-box>
複製代碼
一些屬性說明:
在A-Frame中還能夠添加文本組件<a-text>
。
<a-text value="Hello, A-Frame!" color="#0abef0" position="-0.9 0.2 -3" scale="1.5 1.5 1.5">
</a-text>
複製代碼
最後添加文字的效果,效果連接戳這裏。
圓筒原型是多功能的,可用於建立不一樣種類的形狀:
<!-- 基本圓筒。 -- > <a-cylinder color="crimson" height="3" radius="1.5"></a-cylinder> <!-- 六角形。 -- > <a-cylinder color="cyan" segments-radial="8"></a-cylinder> <!-- 吃豆人。 -- > <a-cylinder color="yellow" theta-start="50" theta-length="280" side="double"></a-cylinder > <!-- 綠色管道。 -->
<a-cylinder color="green" open-ended="true"></a-cylinder>
複製代碼
用於創造一個椎體。
<a-cone position="0 0 -20" rotation="35 45 30" height="10" radius-top="2" radius-bottom="10" color="#F3BA8D"></a-cone>
複製代碼
在A-Frame中也有DOM元素,經過querySelector()和querySelectorAll()方法來提供元素的遍歷,查詢,查找和選擇。這個很像jQuery中的選擇器。
若是咱們想抓住一個元素,咱們使用querySelector()返回那一個元素。好比咱們來抓住場景元素:
var scene = document.querySelector('a-scene');
console.log(scene);
複製代碼
若是元素具備ID,則可使用ID選擇器(即,#)。咱們來抓住一個有一個ID的紅色框。以前咱們在整個文檔上作了一個查詢選擇器。在這裏,咱們將在場景範圍內作一個查詢選擇器。使用查詢選擇器,咱們能夠將查詢的範圍限制在任何元素內:
var scene = document.querySelector('a-scene');
console.log(scene.querySelector('#mybox'));
複製代碼
若是咱們要抓取一組元素,咱們使用querySelector()哪一個返回一個元素數組。咱們能夠查詢元素名稱、類名、屬性名:
// 查詢元素名稱
console.log(document.querySelectorAll('a-box'));
// 查詢類名
console.log(document.querySelectorAll('.mybox'));
// [
// <a-entity light="type:ambient"></a-entity>
// <a-entity light="type:directional"></a-entity>
//]
// 查詢屬性名
console.log(document.querySelectorAll('[light]'));
複製代碼
若是咱們抓住了一組使用的實體querySelectorAll(),咱們能夠循環使用它們for。咱們圍繞場景中的每一個元素循環遍歷。
var els = document.querySelectorAll('a-box');
for(var i = 0; i < els.length; i++){
console.log(els[i]);
}
複製代碼
要建立一個實體,咱們可使用document.createElement。這將給咱們一個空白的實體:
var el = document .createElement('a-entity');
複製代碼
可是,在將實體附加到咱們的場景以前,該實體將不會被初始化或者成爲場景的一部分。
要向DOM添加實體,咱們可使用.appendChild(element)。具體來講,咱們想把它添加到咱們的場景中。咱們抓住現場,建立實體,並將實體附加到咱們的場景。
var sceneEl = document .querySelector('a-scene');
var entityEl = document .createElement('a-entity');
sceneEl.appendChild(entityEl);
複製代碼
請注意,這appendChild()方法是瀏覽器中的異步操做。在實體完成附加到DOM以前,咱們不能對實體執行許多操做(如調用.getAttribute())。若是咱們須要查詢剛被追加的實體上的一個屬性,咱們能夠監聽loaded該實體上的事件,或者將邏輯放在A-Frame組件中,以便一旦它被準備好就執行:
要從DOM中移除實體,所以從場景中刪除一個實體,咱們removeChild(element)從父元素調用。若是咱們有一個實體,咱們必需要用它的parent(parentNode)去除實體。
entityEl.parentNode.removeChild(entityEl);
複製代碼
要更新組件,咱們可使用setAttribute()方法。更新組件須要幾種形式。若是組件是單屬性組件,則setAttribute其行爲與一般狀況相同:
entity.setAttribute('visible',false);
複製代碼
可是若是是單屬性,它能夠處理該值的特殊解析。例如,position組件是單屬性組件,但其屬性類型解析器容許它佔用一個對象:
entity.setAttribute('position',{x:1,y:2,z:3});
複製代碼
要設置或替換多屬性組件的組件數據,咱們能夠傳遞註冊組件的屬性名稱,並將屬性對象傳遞爲value:
entity.setAttribute('light', {
type: 'spot',
distance: 30,
intensity: 2.0
});
複製代碼
從DOM中刪除屬性或者分離組件,調用組件的remove生命週期方法。
entity.removeAttribute('goemetry'); //分離幾何組件。
entity.removeAttribute('sound'); //分離聲音組件。
複製代碼