Three.js是一個很棒的開源WebGL函式庫,WebGL允許JavaScript操作GPU,在瀏覽器端實現真正意義的3D。但目前這項技術還在發展階段,資料極為匱乏,愛好者學習基本上要透過Demo源碼和Three.js本身的源碼來學習。
0.簡介
嗨,這是我的第一篇關於如何寫出好的程式碼的文章。和許多開發者一樣,我透過實作學習,但同時我也向其他更有經驗的開發者學習。在過去的幾個月中,我在canvas標籤上花了很多時間,我想如果把這段時間學到的關於WebGL和JavaScript的小技巧都寫下來,一定很有意思。有些很具體,有些卻很籠統,希望你們喜歡!
1.盡快寫一個原型
讓我們從簡單的開始。現在你有個絕妙的注意,那麼你應該盡快就程式裡最複雜的部分寫一個原型,看看這項技術是否可以實現你的想法。 WebGL很強大,因為它可以直接操縱顯示卡里的GPU,但也別忘了你需要透過JavaScript才能存取顯示卡,這比顯示卡內部運算的效率可是低多了。事實上,你的天才想法很可能會被這種簡單事情擊敗。
2.使用THREE.JS處理3D
就像我的朋友Hakim一樣,我也完全理解我們正使用的技術的底層細節。理解表面之下的東西是很重要的,但是如果你使用three.js,它為你免於瞭如此多的煩惱。你可以將它用於Canvas,WebGL還有SVG,你也應該找到哪種方式適合你的需求。
3.避免SetInterval
這對所有使用JavaScript創建動畫的人來說,都是很重要的一點。為什麼?假設你設定每20毫秒後執行一次某個函數,而這個函數需要執行超過20毫秒的時間,那麼20ms之後,瀏覽器不會在乎,而是直接開始下一次執行。至少你可以使用SetTimeout來設置,在某個函數執行完之後,再次執行它。
事實上,有一個更新潮卻還是半成品的函數,叫做requestAnimationFrame,它很棒。它很類似於setTimeOut函數,除了在這兩個方面:當標籤頁失去焦點時,它就不再運行了;現在這個函數還是依賴於瀏覽器的,標準以後還有可能變化。如果你想要更多的信息,可以訪問Paul Irish的博客。
4.使用倒序循環
這是個不錯的小技巧,可以讓你的循環更快。使用倒序,而且使用while循環。例如,這個迴圈:
for(var a = 00; a // 做些什麼
}
它的執行效率不如下面這個循環:
// 假設陣列arr存在
var aLength = arr.length;
while(aLength-while(aLength-whi -) {
// 做一些什麼
}
這可能沒幫你省多少開銷,因為執行的效率主要還是依賴於你在循環體裡面乾了什麼。但如果你想程式的不必要開銷減少到最後一個字節,後一個循環肯定贏。
實話說,主要影響程式執行效率的還是陣列快取的長度。你可以(也確實應該)去看看JSPerf去了解這一點,以及其他影響JavaScript效能的因素。
5.使用紋理 在WebGL裡面把物體的任意一個細節都畫出來看上去很誘人,但是,如果有可能的話,你應當注意一下你是否能夠使用紋理,因為它能夠極大地提高性能。在某些特定的情況下,例如陰影或模糊效果,你也許不得不使用紋理,但在其他時候,你也應該時時注意你是否可以使用紋理。
6.使用緩存 這一點我在自己的試驗力試了很多,在幀循環中,你應當避免引用變數、物件或其他任何東西。基於這點原因,很值得把你的模型、頂點全部快取起來,這樣在渲染動畫的時候你就可以快速地存取到它們。
7.停用選取 我愛這一小程式碼,我把它放到任何包含Canvas或WebGL的頁面中。
// 停用滑鼠選取DOM元素
// 停用滑鼠選取DOM元素
document. onselectstart = function() {
return false; };
你也可能只想在Canvas控制項中停用選取。這段是我在那些Canvas佔據了整個螢幕的專案中使用的程式碼。
8.避免在JavaScript中定義CSS 現在,在JavaScript中定義CSS簡直太方便了,尤其是你使用JQuery的時候
// 盡量不要這樣做
$("#someid").css({
position: 'relative',
height: '30px',
width: '300px',
backgroundColor: '#A020F0'
});
是問題這樣做之後,你的JavaScript程式碼中很快就充斥著各種類型的CSS定義,而你同時又使用*.css檔案來定義CSS,潛在的問題很難被發現。更好的方法是:使用class模組化CSS,而且只在JavaScript中定義那些不能預知的CSS類別。
9.在物件中定義回調函數 我愛下面這段程式碼,這絕不是我自己想出來的,但它是如此整潔美觀。如果你有一大堆回呼函數要用,也許會這樣用的:
$("#someid").click(function() {
// 回呼函數
// 傳回false在JQuery中會阻止訊息的傳遞與預設行為的放生
return false;
});
或者,你會回調一個在程式碼其他地方定義的鬆散的函數,例如這樣
$("#someid").click(mySuperFunction);
function mySuperFunction(event) {
///🎜>//這裡做很多事情
return false;
}
這樣做會有一些問題。在第一段程式碼中,你在某個事件上綁定了匿名函數,你很難將該函數再從事件上解除。你當然可以解除某個事件上的所有函數,但你可能在它上面綁定了多個函數,而你只想解除一個。在第二種情況下,你的函數名稱污染了全域變數空間,程式碼的可維護性降低了。所以,考慮這樣做:
$("#someid" ).click(callbacks.mySuperFunction);
// 所有的回呼函數都在callbacks物件中
var callbacks = {
mySuperFunction:function(event) {
// 更工作
return false;
}
}
// 解除某函數的綁定
$("#someid").unbind('click', callbacks.mySuperFunction);
這樣做整潔又乾淨,而且避免了上面提到的兩個問題。
10.鍊式三元運算子 我完全是從Paul Irish的《JQuery,你應該知道的11件事》中學到這個的。這非常好用,你也應該會喜歡。我們常這樣做:
// 根據a的值為numberBasedOnA賦值
// 如果a大於5,則賦值200,否則賦值38
var numberBasedOnA = a > 5 ? 200 : 38;
但如果你想這樣做,例如,當值為多少時如何,當值大於多少時如何,當值更加大的時候如何,懂嗎?在這種情況下,鍊式三元運算子非常好用:
var numberBasedOnA =
a a a a 64; >// 比這樣做更有效率
// when a >=15