献给读者,我起这个标题绝对不是想着靠标题给大家吸引进来给我引流加阅读量什么的,我总结看了一遍掘金所有ThreeJS的入门文章,发现大家很多都是写的给自己看的文章,偏向于让所有人都能看懂的部分还是少了。如果说这篇文章确实对您有帮助您可以点赞支持下我产出更多优秀内容。如果说确实存在需要改进的地方您可以在评论区留下宝贵的意见。我一定认真学习,认真改进
封面是杰斯。杰斯发现海克斯宝石的时候。是一种发现的进步。当他真正将海克斯宝石投入民用的时候。是一种进步和发现的喜悦,他也没有辜负皮城进步之名的称号,当之无愧的未来守护者。我也希望读这篇文章的你也能像杰斯一样体验这种进步的喜悦
什么是ThreeJS?
ThreeJS是基于原生WebGL封装运行的三维引擎。在所有WebGL引擎中,ThreeJS是国内文资料最多、使用最广泛的三维引擎。
随着物联网的发展,工业、建筑等各个领域与物联网相关Web项目网页交互界面都会呈现出3D化的趋势。物联网相比较传统互联网更强调的是人与物、物与物的联系,当人与物进行交互的时候,比如你通过网页页面远程控制工厂中的一台机器启动或关停,你可以在网页上通过div元素写一个按钮,然后表示机器设备的开关,当然你也可以把该设备以3D的形式展示在网页上,然后就像玩游戏一样直接点击模型上的开关按钮,这两种方式肯定是3D的方式更为直观,当然开发成本也比较大。
创建一个场景
这一部分将会对Three.JS来做一个简单的介绍,我们将创建一个场景,其中包含一个正在旋转的立方体。
我们首先创建一个HTML文件,这是First Things First。然后,我们去网络上找一个THREE.js的CDN文件 然后将他导入到我们的项目里面来。【有时候可能因为网络不好CDN就加载不出来】。所以我这里将CDN的ThreeJS文件下载了下来帮助大家享用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>这是一个可爱的小方块 嘿嘿</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="../lib/three.js"></script>
<script>
// 具体实现代码
</script>
</body>
</html>
好,以上我们就做到了将ThreeJS导入到我们的这个项目中来的目的了。下面我们来构造场景,相机,渲染器。这样,我们就可以通过摄像机来渲染出场景。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>这是一个可爱的小方块 嘿嘿</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="../lib/three.js"></script>
<script>
// 新建一个场景
var scene=new THREE.Scene()
/**
* 这里是创建了一个相机,PerspectiveCamera表示透视相机。
* 第一个参数是视野角度。视野角度就是无论你在什么时候,你所能在显示器上看到的场景的范围。他的值是一个角度单位
* 第二个参数是长宽比,也就是你用一个物体的宽除以他的高的值。比如说你在一个宽屏电视上播放老电影时。可以看到图像是被压扁的。
* 接下来的两个参数是近截面(near)和远截面(far)。
* 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中。
* 或许现在你不用担心这个值的影响,但未来为了获得更好的渲染性能,
* 你将可以在你的应用程序里去设置它。
* */
var camara=new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
// 新建一个渲染器
var renderer=new THREE.WebGLRenderer();
// 设置渲染器的大小
renderer.setSize(window.innerWidth,window.innerHeight)
</script>
</body>
</html>
效果如下:
可以看到哈,上面都是黑的,因为我们创建了相机还没有使用,并且在这个渲染器里面我们还没有加入任何东西。
好的,现在我们就来创建一个最基础的3D模块,一个cube【立方体】模块,然后让他在页面上得到显示。
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>这是一个可爱的小方块 嘿嘿</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="../lib/three.js"></script>
<script>
// ...这部分代码和上面相同,省略
// 开始设置立方体,设置长宽高,立方体的框架
var geometry=new THREE.BoxGeometry(1,1,1)
// 设置渲染材质,这个变量用来渲染立方体的表面。设置立方体的颜色为绿色。立方体的表面材质
var material=new THREE.MeshBasicMaterial({color:0x00ff00})
// 真正的立方体变量,通过THREE.Mesh来将材质和框架混合到一起
var cube=new THREE.Mesh(geometry,material)
// 将这个立方体添加到场景当中去。但是要记住,如果立方体直接进场景的话,我们的立方体就会和相机进行重叠。这样就不好了。
scene.add(cube)
// 所以我们这里将相机往上面调一点【这里ThreeJS和Unity一样 用的都是左手坐标系】
camara.position.z=5
// 立方体设置结束
// 将刚刚创建好的渲染器加入到body里面去。
document.body.appendChild(renderer.domElement);
// 渲染函数开始
function animate(){
requestAnimationFrame(animate)
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene,camara)
}
animate()
// 渲染函数结束
</script>
</body>
</html>
好了,现在我们将一个立方体加入到了Scene【场景】当中去。那么我们接下来就需要将场景进行渲染了。
那么我们渲染的话,肯定是涉及到了一个点的。就是我们是一直渲染用RequestAnimationFrame还是设立一个SetInterval。然后规定多久多久渲染一次。【我们不可能是将物体【比如说我们上面写的这个cube】放上去之后就不让他动了吧 bro】
通过以上两种方法渲染当然都可以。都是一种实现一直动画的方式。但是我个人这里推荐RAF。
RAF相比于SetInterval在渲染ThreeJS上面有很多优点,比如说当我们切换浏览器的选项卡到另外一个标签页时,RAF他会暂停。因此不回损耗电池的使用寿命,也不会浪费用户宝贵的处理器资源
代码如下:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>这是一个可爱的小方块 嘿嘿</title> <style> body { margin: 0; } canvas { width: 100%; height: 100%; } </style></head><body> <script src="../lib/three.js"></script> <script> // ...以上部分参考上面 // 渲染函数开始 function animate(){ requestAnimationFrame(animate) renderer.render(scene,camara) } animate() // 渲染函数结束 </script></body></html>
运行效果:
\
好的。现在我们有了一个立方体。但是我们这个立方体有其实和没有并没有什么区别。如果说想要让他变得有趣一点,然后让这个RAF像很多在PIXIJS中的动画一样。我们要改变这个cube【立方体】的属性,让他有一种动起来的感觉。所以我们在render方法调用的上方加入以下代码
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
实现效果:
\
这段代码每一帧都会执行,这就让立方体有了一个看起来不错的旋转动画。基本上来说。当程序运行时,如果你想要改变场景中的任何东西。都必须经过这个动画循环。这样你就没有必要写出上百行的animation函数。
通过模块来引入(Import via modules)
虽然通过script标签来引入ThreeJS是一个能够快速起步,快速运行的方式。但是这种方式对于一些具有较长生命周期的项目还是存在一些缺点。比如:
- 你必须手动获得并且在你的项目源码中包含这个库的一个拷贝。
- 更新库的版本是一个手动操作的过程
- 在检查新版本的库时。你的版本差异对比将会被许多行的构建文件给弄乱。
使用像npm这样的依赖包管理工具,你只需要在你的机器上下载并且导入你所需要的版本库就可以很好的避免以上问题。
通过npm来安装
Three.js目前已经作为一个npm模块来进行了发布,详情请参阅:npm。这意味着你只需运行"npm install three"就可以使你的项目包含three.js库。
海克斯科技传送门
参考文献
- ThreeJS中文网:www.webgl3d.cn/Three.js/