前言

  昨天打算开始重新写我的封装脚本了,将一些函数命名修改,加入更多的功能。
  为了更好地使用Three.js,这次我决定使用require.js进行脚本引入。
  我希望通过require.js实现js动态记载,在加载控制器的时候可以根据加载的控制器动态加载脚本,这就不需要将无关的脚本加载进来。
  在决定使用require之前,我也研究了webpack的方案,但是想到上面的问题,webpack绝对会打包到一起的,这就与我的出发点冲突了,所以决定弃用webpack。

坑爹的开始

  决定好要用require.js之后,就找了相关的资料查阅。
  官网地址
  菜鸟教程(一)
  菜鸟教程(二)

  看完这三个教程之后,我对require有了全面的认识。
  require的好处就是可以异步加载js文件,避免浏览器假死(因为加载js而不加载页面)

  既然如此,那我就根据教程的方法设置requirejs.config就好了。
  然而坑爹的地方开始了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

requirejs.config({
paths: {
"three": ["https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min"], "OrbitControls": ["OrbitControls"]
},
shim: {
// three: {exports: 'THREE'},
OrbitControls: { deps: ["three"] }
}
})

require(["three", 'OrbitControls'], function (THREE) {
// require(["three"],function(THREE){

//案例代码来自于官方入门Demo
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

camera.position.z = 5;

//require(['OrbitControls'], function () {
var controls = new THREE.OrbitControls(camera);
//})

var animate = function () {
requestAnimationFrame(animate);

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;

renderer.render(scene, camera);
};

animate();

});

  这种方法无论怎么弄,都会说orbitControl的THREE没有定义。
  我一直以为是我没有正确使用require shim所以才导致问题的。
  我在网上搜索了大量关于require的教程,找到了jq插件的加载方法。
  然而坑爹的地方是,jq的插件可以用这样的方法加载,而Three.js的orbit插件却会报错。

  到这里我已经花了大半天的时间研究了,然而一直没有起色。
  后来我去官网认真地看了一遍require的用法,发现模块化需要define才能用
  然后我在orbit脚本中加入define的语句包含起来之后就可以了。

1
2
3
4
5
define(['three'], function(THREE) {

//orbit 相关的脚本

})

  这样的操作,不会吧!
  每个脚本都要处理一下,工作量挺大的,因此我决定一定要知道解决方案。
  然而我还是思维局限了,其实问题不在require而是在Three.js。

坑爹的尾声

  后面我搜索了和three.js相关的require问题之后,找到了github 的issue
  github地址
  我终于得到石锤,不是require的问题而是Three.js自身的问题。
  解决方案也在里面。

1
2
3
4
define('three', ['https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js'], function ( THREE ) {
window.THREE = THREE;
return THREE;
});

  在requirejs.config之后加入上面的代码就可以了,无需对各个脚本进行单独的操作。

坑爹地结束

  解决了问题总归是兴奋的,但是当我真正用起来才发现,这里实现了异步加载js,而不是动态加载js。
  搞了半天结果发现跑题了…….

  我上网搜了一下异步加载的处理方案,发现jquery就有$.getScript的方案,用起来方便得多。
  到头来我连require.js也摈弃了,毕竟纯Three.js的三维页面并没有太多网页页面内容,require.js isn’t require.