THREE.JS入门教程(5)你应当知道的十件事


Posted in Javascript onJanuary 24, 2013

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 = 0; a < arr.length; a++) { 
// 做一些什么 
}

它的执行效率不如下面这个循环:
// 假设数组arr存在 
var aLength = arr.length; 
while(aLength--) { 
// 做一些什么 
}

这可能没帮你省多少开销,因为执行的效率主要还是依赖于你在循环体里面干了什么。但如果你想程序的不必要开销减少到最后一个字节,后一个循环肯定赢。

实话说,主要影响程序执行效率的还是数组缓存的长度。你可以(也确实应该)去看看JSPerf去了解这一点,以及其他影响JavaScript性能的因素。
5.使用纹理
在WebGL里面把物体的任意一个细节都画出来看上去很诱人,但是,如果有可能的话,你应当注意一下你是否能够使用纹理,因为它能够极大地提高性能。在某些特定的情况下,比如阴影或者模糊效果,你也许不得不使用纹理,但在其他时候,你也应该时时关注你是否可以使用纹理。
6.使用缓存
这一点我在自己的试验力试了很多,在帧循环中,你应当避免引用变量、对象或者其他任何东西。基于这点原因,很值得把你的模型、顶点全部缓存起来,这样在渲染动画的时候你就可以快速地访问到它们。
7.禁用选中
我爱这一小段代码,我把它放到任何包含Canvas或WebGL的页面中。

// 禁用鼠标选中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 < 5 ? 200 : 
a < 7 ? 38 : 
a < 11 ? 15 : 
a < 15 ? 49 : 
64; 
// 比这样做更有效率 
// when a >=15
Javascript 相关文章推荐
JS获取页面input控件中所有text控件并追加样式属性
Feb 25 Javascript
jQuery插件ajaxFileUpload使用实例解析
Oct 19 Javascript
JS中split()用法(将字符串按指定符号分割成数组)
Oct 24 Javascript
JS冒泡事件与事件捕获实例详解
Nov 25 Javascript
详解JavaScript对象的深浅复制
Mar 30 Javascript
JS实现动态给标签控件添加事件的方法示例
May 13 Javascript
深入理解vue.js中$watch的oldvalue与newValue
Aug 07 Javascript
JavaScript ES6中的简写语法总结与使用技巧
Dec 30 Javascript
实例详解vue中的$root和$parent
Apr 29 Javascript
vue-loader中引入模板预处理器的实现
Sep 04 Javascript
解决vue项目router切换太慢问题
Jul 19 Javascript
vue 路由缓存 路由嵌套 路由守卫 监听物理返回操作
Aug 06 Javascript
THREE.JS入门教程(4)创建粒子系统
Jan 24 #Javascript
THREE.JS入门教程(3)着色器-下
Jan 24 #Javascript
THREE.JS入门教程(2)着色器-上
Jan 24 #Javascript
THREE.JS入门教程(1)THREE.JS使用前了解
Jan 24 #Javascript
(跨浏览器基础事件/浏览器检测/判断浏览器)经验代码分享
Jan 24 #Javascript
jQuery ajax(复习)—Baidu ajax request分离版
Jan 24 #Javascript
javascript游戏开发之《三国志曹操传》零部件开发(五)可移动地图的实现
Jan 23 #Javascript
You might like
php-fpm超时时间设置request_terminate_timeout资源问题分析
2019/09/27 PHP
PHP7 整型处理机制修改
2021/03/09 PHP
Chrome中模态对话框showModalDialog返回值问题的解决方法
2010/05/25 Javascript
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
2010/08/13 Javascript
JQuery1.4+ Ajax IE8 内存泄漏问题
2010/10/15 Javascript
文字不间断滚动(上下左右)实例代码
2013/04/21 Javascript
$.getJSON在IE下失效的原因分析及解决方法
2013/06/16 Javascript
Jquery判断radio、selelct、checkbox是否选中及获取选中值方法总结
2015/04/15 Javascript
JS实现光滑展开合拢的菜单效果代码
2015/09/16 Javascript
js使用cookie记录用户名的方法
2015/11/26 Javascript
JavaScript数组的一些奇葩行为
2016/01/25 Javascript
jquery自定义表单验证插件
2016/10/12 Javascript
浅析如何利用angular结合translate为项目实现国际化
2016/12/08 Javascript
JS中利用localStorage防止页面动态添加数据刷新后数据丢失
2017/03/10 Javascript
Vue.js鼠标悬浮更换图片功能
2017/05/17 Javascript
jQuery插件ImgAreaSelect实现头像上传预览和裁剪功能实例讲解一
2017/05/26 jQuery
基于webpack 实用配置方法总结
2017/09/28 Javascript
JS常见DOM节点操作示例【创建 ,插入,删除,复制,查找】
2018/05/14 Javascript
vue router 通过路由来实现切换头部标题功能
2019/04/24 Javascript
用js简单提供增删改查接口
2019/05/12 Javascript
vue-router之实现导航切换过渡动画效果
2019/10/31 Javascript
JavaScript计算出两个数的差值
2020/03/19 Javascript
[02:39]我与DAC之Newbee.Moogy:从论坛到TI
2018/03/26 DOTA
[03:33]TI9战队采访 - Infamous
2019/08/20 DOTA
[01:32:22]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第一场 2月5日
2021/03/11 DOTA
Python判断值是否在list或set中的性能对比分析
2016/04/16 Python
Python处理PDF及生成多层PDF实例代码
2017/04/24 Python
Python实现翻转数组功能示例
2018/01/12 Python
Python 查找字符在字符串中的位置实例
2018/05/02 Python
django 中的聚合函数,分组函数,F 查询,Q查询
2019/07/25 Python
Python求解正态分布置信区间教程
2019/11/20 Python
Python中全局变量和局部变量的理解与区别
2021/02/07 Python
For Art’s Sake官网:手工制作的奢华眼镜
2018/12/15 全球购物
Java语言程序设计测试题判断题部分
2013/01/06 面试题
专升本学生毕业自我鉴定
2014/10/04 职场文书
庆祝教师节主持词
2015/07/06 职场文书