带你读《Three. js开发指南: 基于WebGL和HTML5在网页上渲染 3D图形和动画(原书第3版)》之一:使用Three.js创建你的第一个三维场景

简介: 本书将介绍如何直在浏览器中创建漂亮的3D场景和动画,并且充分发挥WebGL和现代浏览器的潜能。首先介绍基本概念和基础组件,然后通过逐渐扩展示例代码逐步深讲解更多高级技术。在本书中读者将学到如何从外部加载3D模型和具有真实效果的材质纹理、学习使用Three.js提供的摄像机组件来实现在3D场景中飞行和走动、如何将HTML5视频和画布作为材质贴在3D模型表面。此外还将学习变形动画和骨骼动画,甚至还会涉及在场景中使用物理模拟的方法,例如重力、碰撞检测等等。

Web开发技术丛书
点击查看第二章
点击查看第三章
Three. js开发指南:
基于WebGL和HTML5在网页上渲染
3D图形和动画(原书第3版)
Learn Three.js: Programming 3D animations and visualizations for the web with HTML5 and WebGL, Third Edition

image.png

[美] 乔斯·德克森(Jos Dirksen)著
周翀 张薇  译

第1章

使用Three.js创建你的第一个三维场景
现代浏览器直接通过JavaScript就可以实现非常强大的功能。使用HTML5的标签可以很容易地添加语音和视频,而且在HTML5提供的画布上可以添加具有交互功能的组件。现在,现代浏览器也开始支持WebGL。通过WebGL可以直接使用显卡资源来创建高性能的二维和三维图形,但是直接使用WebGL编程来从JavaScript创建三维动画场景十分复杂而且还容易出问题。使用Three.js库可以简化这个过程。Three.js带来的好处有以下几点:

  • 创建简单和复杂的三维几何图形。
  • 创建虚拟现实(VR)和增强现实(AR)场景。
  • 在三维场景下创建动画和移动物体。
  • 为物体添加纹理和材质。
  • 使用各种光源来装饰场景。
  • 加载三维模型软件所创建的物体。
  • 为三维场景添加高级的后期处理效果。
  • 使用自定义的着色器。
  • 创建点云(即粒子系统)。

通过几行简单的JavaScript代码,你可以创建从简单三维模型到类似图1.1(在浏览器中访问http://www.vill.ee/eye )所示的具有真实感的场景。
本章将会通过示例来阐述Three.js的工作原理,但是不会对其中的技术细节进行深入探究,这些细节我们将会在后面的章节中介绍。本章主要涵盖以下几方面:

  • 使用Three.js所需的工具。
  • 下载本书所需的源码和示例。
  • 创建第一个Three.js场景。
  • 使用材质、光源和动画来完善第一个场景。
  • 引入辅助库以统计和控制场景。

image.png

首先将会对Three. js进行简单的介绍,然后再讲解第一个示例及其代码。在开始之前我们先来看下当前主流浏览器对WebGL的支持情况,几乎所有浏览器的桌面版和移动版均支持WebGL,唯一的例外是移动版迷你Opera浏览器(Opera Mini),因为这个浏览器有一种特殊的工作模式,可以在Opera服务器端进行页面渲染,而Opera服务器往往禁止运行JavaScript。不过从8.0版开始,Opera Mini的默认工作模式已改为使用iOS Safari引擎渲染页面,从而也可以很好地支持JavaScript和WebGL。但是新版Opera Mini仍然可以被设置为不支持JavaScript的“迷你模式”(mini mode)。
除了IE的一些低版本浏览器,基本所有的现代浏览器都支持Three.js。如果想在低版本的IE浏览器上运行Three.js,你还需要做额外的操作。对于IE10和更低的版本,你可以安装iewebgl插件,下载地址为https://github.com/iewebgl/iewebgl
使用WebGL能够创建出具有交互性的3D模型,而且这些模型在电脑和手机设备上都能够很好地运行。

本书主要使用Three.js提供的基于WebGL的渲染器。但是Three.js也提供了基于CSS 3D的渲染器,使用其API能够很容易地创建出三维场景,而且这个渲染器的优点在于几乎所有手机和电脑上的浏览器都支持CSS 3D,并且可以在三维空间内渲染HTML元素。第7章会进一步介绍如何使用CSS 3D。
通过本章的学习,你可以直接创建第一个三维场景,而且这个场景可以在上述的所有浏览器中运行。目前我们不会介绍太多Three.js的复杂特性,但是在本章结束的时候你能够创建出如图1.2所示的场景。

image.png

通过创建这个场景,你可以学到Three.js的基础知识,并可以创建第一个动画。在开始实现这个示例之前,我们会先介绍几个工具,这些工具可以帮助你更方便地使用Three.js。我们还会介绍如何下载本书所用到的示例。

1.1 准备工作

Three.js是一个JavaScript库,所以你只需要一个文本编辑器和支持Three.js的浏览器就可以使用Three.js来创建WebGL应用。这里推荐如下几款JavaScript文本编辑器:

  • Visual Studio Code:Visual Studio Code是微软公司面向所有常见操作系统推出的一款免费编辑器。该编辑器能够基于源程序里的类型和函数声明以及导入库,提供效果良好的语法高亮和代码补全功能。同时它还具有简洁明了的用户界面,以及对JavaScript的完美支持。下载地址为https:/ / code. visualstudio. com /。
  • WebStorm: WebStorm是JetBrains公司旗下的一款JavaScript编辑工具。它支持代码补全、自动部署和代码调试功能。除此之外,WebStorm还支持GitHub和其他各种版本控制器。读者可从http://www.jetbrains.com/webstorm/ 下载一个试用版本。
  • Notepad++:Notepad++是Windows操作系统下的通用文本编辑器,它支持各种编程语言语法高亮度显示,而且可以很容易地对JavaScript进行布局和格式化。Notepad++的下载地址为http://notepad-plus-plus.org/
  • Sublime Text: Sublime Text是一款对JavaScript支持非常好的文本编辑器。除此之外,Sublime Text 的一大亮点是支持多重选择—同时选择多个区域,然后同时进行编辑。这些功能提供了一个很好的JavaScript编程环境。Sublime Text是一个收费闭源软件,下载地址为http://www.sublimetext.com/

除此之外,还有很多可以编写JavaScript进而创建Three.js应用的开源和商用编辑器。还有一款基于云的代码编辑平台Cloud9,网址是http://c9.io , 该平台可以连接GitHub账号,由此可以直接获取本书相关的代码和示例。
除了使用这些文本编辑器来运行本书相关的代码和示例,Three.js自身也提供了在线场景编辑器,访问地址为http://threejs.org/editor 。使用该编辑器,可以用图形化方法创建Three.js场景。
虽然现代浏览器基本都支持WebGL并能运行Three.js应用,但是本书所采用的是Chrome浏览器。因为Chrome是对WebGL支持最好的浏览器,并且拥有强大的JavaScript代码调试功能。如图1.3所示,使用调试器的断点和控制台功能可以快速地定位问题。在本书中,还会进一步介绍各种调试的方法和技巧。

image.png

Three.js就介绍到此,下面就开始获取源码并创建我们的第一个场景。

1.2 获取源码

本书所有的源码都可以从GitHub(https://github.com/ )获取。GitHub是基于Git的在线代码仓库,你可以使用它来存储、访问源码和进行版本控制。获取GitHub上源码的方式有以下两种:

  • 通过Git获取代码仓库
  • 下载并解压缩档案文件

接下来会详细讲解这两种方式。

1.2.1 通过Git获取代码仓库

Git是开源、分布式的版本控制系统,本书的示例都是基于Git进行创建和版本管理的,GitHub仓库的访问地址为https://github.com/josdirksen/learning-threejs
如果你已经在操作系统中安装了Git的客户端,那么就可以使用git命令来克隆示例的代码仓库。如果你还没有安装,可以访问http://git-scm.com 下载,或者使用GitHub公司自己为Mac或Windows系统提供的客户端。在安装完Git客户端后,打开控制台并在你想要存储代码的目录中运行如下的命令:
image.png

如图1.4所示,代码就开始下载了。

image.png

下载完毕后,在learning-threejs-third文件夹中会看到本书所用的所有的示例。

1.2.2 下载并解压缩档案文件

如果你不想使用Git的方式从GitHub上获取源码,那么还可以在GitHub上下载档案文件。在浏览器上访问https://github.com/josdirksen/learning-threejs-third ,点击右侧的Clone or download按钮。如图1.5所示。
解压文件到指定的目录,这样就可以获取所有的示例了。

image.png

1.2.3 测试示例

现在你已经下载或者克隆了示例源码,下面我们就来测试示例是否能够正常工作,进而了解工程的目录结构。本书的示例是按照章节进行组织的。如果要运行本书的示例,你可以使用浏览器打开HTML文件,或者安装本地Web服务器。第一种方法对于简单的示例是可行的,但是如果示例中需要下载外部资源时,比如模型或者纹理图像,那么仅仅使用浏览器打开HTML文件是行不通的。这个时候,我们就需要本地Web服务器来确保外部资源正确加载。接下来我们会介绍几种安装本地服务器的方式,如果你无法安装本地服务器但使用Chrome或Firefox浏览器,那么我们也会介绍如何禁用安全性检测来运行示例。
接下来,我们将会介绍几种安装本地服务器的方式,依据系统的配置,你可以选择最合适的方式。
1.适用于Unix/Mac系统的基于Python的Web服务器
大部分的Unix/Linux/Mac系统默认安装了Python,在示例源码目录中运行如下的命令就可以将本地Web服务器启动起来了。
image.png

在你下载了源码的目录中执行上述命令。
2.基于NPM的Web服务器
如果你已经在使用Node.js了,那么你肯定已经安装了NPM。使用NPM,有两个方式可以快速地搭建本地Web服务器:第一种方式是使用http-server模块,如下所示:
image.png

第二种方式是使用simple-http-server,如下所示:
image.png

第二种方式的缺点在于无法自动地显示目录列表,而第一种方式是可以的。
3. Mac/Windows上的轻量级服务器—Mongoose
如果你还没有安装Python或者NPM,那么还有一个简单、轻量级的Web服务器—Mongoose。首先,从https://code.google.com/p/mongoose/downloads/list 下载你的系统所支持的二进制安装文件。如果你使用的是Windows系统,那么将下载好的二进制文件复制到示例所在的目录,双击即可启动一个运行于该目录下的Web服务器。
对于其他的操作系统,则须将下载的二进制文件复制到指定的目录中,但是启动的方式不是双击,而是通过命令行的方式,如图1.6所示。

image.png

在这两种情况下都会在8080端口启动一个本地Web服务器。本书的示例目录如图1.7所示。

image.png

点击各章节的目录就可以获取相应章节的示例。在本书讲解提到某个示例时会指出示例的名称和所在的文件夹,这样你就可以找到该示例的源代码以便测试运行或自行研究。
4.禁用Firefox和Chrome的安全性检测
如果你使用的是Chrome浏览器,有种方式可以禁用安全性设置,这样就可以在没有Web服务器的情况下查看示例。需要注意的是,应尽量避免用下面的方法访问真正的网站,因为这样做会使浏览器向各种恶意代码敞开大门。用下面的命令可以启动Chrome浏览器同时禁用所有安全特性。

  • 对于Windows操作系统:

  image.png

  • 对于Linux操作系统:

  image.png

  • 对于Mac OS操作系统:

  image.png

通过这种方式启动Chrome浏览器就可以直接运行本地文件系统中的示例。
对于Firefox浏览器来说,还需要其他的配置。打开Firefox浏览器并在地址栏内输入about:config会看到图1.8所示的页面。

image.png

在该页面中点击“I抣l be careful, I promise!”按钮,然后就会列出所有用于调整Firefox的属性。在搜索框中输入security.fileuri.strict_origin_policy,并将其值修改为false。如图1.9所示。

image.png

这时候就可以使用Firefox浏览器直接运行本书的示例了。
到现在为止,你应该已经安装了Web服务器或者禁用了浏览器的安全性设置,那么就开始创建第一个三维场景吧。

1.3 搭建HTML框架

首先我们将会创建空的HTML框架,后面的示例将在这个框架的基础上完成。具体如下所示:

image.png

你应该已经发现了,这个框架是个仅包含一些基本元素的HTML网页。在

标签中列出了示例所使用的外部JavaScript库,在这里至少要包含Three.js库。此外,这里还包含一个控制器库TrackballControls.js。有了它便可以利用鼠标任意移动摄像机,以便从不同角度观察场景。在标签中最后一个被包含的JavaScript文件是本章的示例程序,文件名为01-01.js。最后,在标签中我们还添加了几行CSS代码,这些CSS代码用于移除Three.js场景网页中的滚动条。在标签中我们只添加了一个
元素,当我们写Three.js代码时,会把Three.js渲染器的输出指向这个元素。在框架网页的最后还有少量JavaScript代码。这些代码将在网页加载完成后被自动调用,我们利用这个机会调用init()函数。init()函数也在01-01.js文件中定义,它将为Three.js场景做必要的初始化设置。不过在本章中,init()函数暂时仅仅向控制台窗口打印当前Three.js的版本信息。

image.png

在浏览器中打开本章示例代码文件并观察控制台窗口,可以看到如图1.10所示的内容。

image.png

元素中包含Three.js的源代码。Three.js有两个不同的版本:
  • three.min.js:这个版本的JS库一般应用于网上部署Three.js时。该版本是使用UglifyJS压缩过的,它的大小是普通Three.js版本的四分之一。本书示例所使用的是2018年7月发布的Three.js r95版本。
  • three.js:这个是普通的Three.js库。为了便于进行代码调试和理解Three.js的源码,本书的示例使用的都是这个库。

接下来,我们将会创建第一个三维对象并将其渲染到已经定义好的

元素中。

1.4 渲染并查看三维对象

在这一步,我们将会创建第一个场景并添加几个物体和摄像机。我们的第一个示例将会包含表1.1所列对象。

image.png

下面将会通过代码示例(带注释的代码在文件chapter-01/is/01-02.js中)来解释如何创建场景并渲染三维对象:

image.png
image.png

在浏览器中将示例打开,看到的结果和我们的目标,即本章开始时所展示的那张渲染图接近,但效果还有些差距。目前的效果如图1.1所示。

image.png

接下来将会对代码进行分析,这样我们就可以了解代码是如何工作的:
image.png

在代码中,首先定义了场景(scene)、摄像机(camera)和渲染器(renderer)对象。场景是一个容器,主要用于保存、跟踪所要渲染的物体和使用的光源。如果没有THREE.Scene对象,那么Three.js就无法渲染任何物体,在第2章还会对THREE.Scene进行详细介绍。示例中所要渲染的方块和球体稍后将会添加到场景对象中。
在示例中我们还定义了摄像机对象,摄像机决定了能够在场景看到什么。在第2章,你还会进一步了解摄像机对象能够接受的参数。接下来,我们定义了渲染器对象,该对象会基于摄像机的角度来计算场景对象在浏览器中会渲染成什么样子。最后WebGLRenderer将会使用电脑显卡来渲染场景。
如果你已经看了Three.js的源码和文档(网址为http://threejs.org ),你会发现除了基于WebGL的渲染器外,还有其他的渲染器,比如基于HTML canvas的渲染器、基于CSS的渲染器,甚至还有基于SVG的渲染器。尽管它们也能够渲染简单的场景,但是不推荐使用,因为它们已经停止更新、十分耗CPU的资源,而且也缺乏对一些功能的支持,比如材质和阴影。
在示例中,我们调用setClearColor方法将场景的背景颜色设置为接近黑色(new THREE. Color(0X00000000)),并通过setSize方法设置场景的大小。使用window.innerWidth和window.innerHeight可将整个页面窗口指定为渲染区域。
到目前为止,我们已经创建了空白的场景、渲染器和摄像机,但是还没有渲染任何东西。接下来将会在代码中添加轴和平面:
image.png

如代码所示,我们创建了坐标轴(axes)对象并设置轴线的粗细值为20,最后调用scene.add方法将轴添加到场景中。接下来要创建平面(plane),平面的创建分为两步来完成。首先,使用THREE.Plane Geometry(60,20)来定义平面的大小,在示例中将宽度设置为60,高度设置为20。除了设置高度和宽度,我们还需要设置平面的外观(比如颜色和透明度),在Three.js中通过创建材质对象来设置平面的外观。在本例中,我们将会创建颜色为0xAAAAAA的基本材质(THREE.MeshBasicMaterial)。然后,将大小和外观组合进Mesh对象并赋值给平面变量。在将平面添加到场景之前,还需要设置平面的位置:先将平面围绕x轴旋转90度,然后使用position属性来定义其在场景中的位置。如果你对Mesh对象感兴趣,那么可以查看第2章中的示例06-mesh-properties.html,该示例详细介绍了旋转和定位。最后,我们将平面添加到场景中。
使用同样的方式将方块和球体添加到平面中,但是需要将线框(wireframe)属性设置为true,这样物体就不会被渲染为实体物体。接下来就是示例的最后一部分:
image.png

现在,所有物体都已经添加到场景中的合适位置。在之前我们提到过,摄像机将决定哪些东西会被渲染到场景中。在这段代码中,我们使用x、y、z的位置属性来设置摄像机的位置。为了确保所要渲染的物体能够被摄像机拍摄到,我们使用lookAt方法指向场景的中心,默认状态下摄像机是指向(0,0,0)位置的。最后需要做的就是将渲染的结果添加到HTML框架的

元素中。我们使用JavaScript来选择需要正确输出的元素并使用appendChild方法将结果添加到div元素中。最后告诉渲染器使用指定的摄像机来渲染场景。
接下来,我们还会使用光照、阴影、材质和动画来美化这个场景。

1.5 添加材质、光源和阴影效果

在Three.js中添加材质和光源是非常简单的,做法和前一节讲的基本一样。首先我们在场景中添加一个光源(完整代码请参见示例js/03-03.js)。代码如下所示:
image.png

通过THREE.SpotLight定义光源并从其位置(spotLight.position.set(-40,60,-10))照射场景。通过将castShadow属性设置为true,THREE.js的阴影功能被启用。此外,上面的代码还通过设置shadow.mapSize、shadow.camera.far和shadow.camera.near三个参数来控制阴影的精细程度。有关光源属性的更多细节将在第3章详细介绍。如果这时候渲染场景,那么你看到的结果和没有添加光源时是没有区别的。这是因为不同的材质对光源的反应是不一样的。我们使用的基本材质(THREE.MeshBasicMaterial)不会对光源有任何反应,基本材质只会使用指定的颜色来渲染物体。所以,我们需要改变平面、球体和立方体的材质:
image.png

如代码所示,我们将场景中物体的材质改为MeshLambertMaterial。Three.js中的材质MeshPhysicalMaterial和MeshStandardMaterial(以及被弃用的MeshPhongMaterical)在渲染时会对光源产生反应。
渲染的结果如图1.12所示,但是这还不是我们想要的结果。

image.png

虽然立方体和球体已经好看了很多,但是还缺少阴影的效果。
由于渲染阴影需要耗费大量的计算资源,所以默认情况下Three.js中是不会渲染阴影的。为了渲染阴影效果,我们需要对代码做如下修改:
image.png

首先通过设置shadowMapEnabled属性为“true”来告诉渲染器需要阴影效果。这时候如果查看修改的效果,那么你将会发现还是没有任何区别,因为你还需要明确地指定哪个物体投射阴影、哪个物体接受阴影。在示例中,我们通过将相应的属性设置为“true”来指定球体和立方体在地面上投射阴影。代码如下所示:
image.png

接下来我们还需要定义能够产生阴影的光源。因为并不是所有的光源都能够产生阴影,但是通过THREE.SpotLight定义的光源是能够产生阴影的。我们只要将属性castShadow设置为true就可以将阴影渲染出来了,代码如下所示:
image.png

这样,场景中就有了光源产生的阴影,效果如图1.13所示。
仔细观察01-03.js的源代码会发现,这段程序还创建了一个拥有不同物体的场景。若将那些名为createXXX的函数的注释去掉,并且删除前面已经创建的立方体和球,场景中便会出现一些更复杂的物体。这些物体将展示出如图1.13所示的更复杂的阴影。

image.png

最后一个将要添加到场景中的效果是简单动画。在第9章中,你将会学习使用更高级的动画。

1.6 让你的场景动起来

如果希望我们的场景动起来,那么首先需要解决的问题是如何在特定的时间间隔重新渲染场景。在HTML5和相关的JavaScript API出现之前,是通过使用setInterval(function,interval)方法来实现的。比如,通过setInterval()方法指定某个函数每100毫秒调用一次。但是这个方法的缺点在于它不管浏览器当前正在发生什么(比如正浏览其他网页),它都会每隔几毫秒执行一次。除此之外,setInterval()方法并没与屏幕的刷新同步。这将会导致较高的CPU使用率和性能不良。

1.6.1 引入requestAnimationFrame()方法

幸运的是,现代浏览器通过requestAnimationFrame函数为稳定而连续的渲染场景提供了良好的解决方案。通过这个函数,你可以向浏览器提供一个回调函数。你无须定义回调间隔,浏览器将自行决定最佳回调时机。你需要做的是在这个回调函数里完成一帧绘制操作,然后将剩下的工作交给浏览器,它负责使场景绘制尽量高效和平顺地进行。这个功能使用起来也非常简单(完整源码在04-04.js文件中),你只需要创建负责绘制场景的回调函数:
image.png

在renderScene()方法中,requestAnimationFrame()方法又一次被调用了,这样做的目的是保证动画能够持续运行。接下来我们还需要对代码做的修改是:在场景创建完毕后,不再调用renderer.render()方法,而是调用renderScene()来启动动画,代码如下:
image.png

这时候如果运行代码,效果和之前的示例相比没有任何区别,这是因为我们还没有为物体添加任何动画效果。在添加动画之前,我们先来介绍一个辅助库,这个库也是Three.js作者开发的,主要用于检测动画运行时的帧数。在动画运行时,该库可以在一个图片中显示画面每秒传输帧数。
为了能够显示帧数,首先我们需要在HTML的

标签中引入这个辅助库:
image.png

然后初始化帧数统计模块并将它添加到页面上。
image.png

上面的函数初始化帧数统计模块,并用输入的type参数来设置将要显示的统计内容。它可以是:每秒渲染的帧数、每渲染一帧所花费的时间或者内存占用量。最后,在前面介绍过的init函数末尾调用上述函数来初始化统计模块。
image.png

由于initStats函数并不是本章示例所特有的操作,因此它的实现代码并不在本章的示例代码中,而是像其他有用的辅助函数一样保存在辅助函数库util.js文件中。
辅助函数库在HTML页面代码的开始部分被引用。
image.png

示例代码为统计帧数显示所做的最后一件事,是在renderScene函数中每渲染完一帧后,调用stats.update函数更新统计。
image.png

添加完上述代码之后再次运行示例,统计图形将会显示在浏览器左上方,如图1.15所示。

image.png

1.6.2 旋转立方体

引入requestAnimationFrame()方法并配置完统计对象之后,接下来就该添加动画代码了。在本节中,我们将扩展renderScene()方法来实现红色立方体围绕轴进行旋转。代码如下所示:
image.png

看起来是不是很简单?我们所做的只是在每次调用renderScene()时使得每个坐标轴的rotation属性增加0.02,其效果就是立方体将围绕它的每个轴进行缓慢的旋转。在下一节中我们将让蓝色球体弹跳起来,这个实现起来也不是特别难。

1.6.3 弹跳球

为了让小球弹跳起来,只需要在renderScene()方法中添加如下代码即可:
image.png

旋转立方体时我们修改的是rotation属性;而让小球弹跳起来,我们所要修改的是球体在场景中的位置(position)属性。我们的目的是让小球依照一条好看的、光滑的曲线从一个地方跳到另一个地方,如图1.16所示。

image.png

为了实现这个效果,我们需要同时改变球体在x轴和y轴的位置。Math.cos()和Math.sin()方法使用step变量就可以创建出球体的运行轨迹。在这里不具体展开解释它们是怎么工作的,现在你只需要知道step+=0.04定义了球体弹跳的速度就可以,在第8章中还会详细介绍这些方法是如何用于实现动画的。图1.17展示的就是球体在弹跳中的效果。

image.png

在结束本章之前,我还想在场景中引入几个辅助库。可能你已经发现,在创建类似三维场景和动画时,我们需要尝试很多次才能够确定最合适的速度和颜色。如果有一个GUI(可视化图形界面)允许我们在运行期间修改这些属性,那么事情就会变得很简单。幸运的是,这样的GUI是存在的。

1.7 使用dat.GUI简化试验流程

Google员工创建了名为dat.GUI的库(相关文档见http://code.google.com/p/dat-gui/),使用这个库可以很容易地创建出能够改变代码变量的界面组件。在本章最后,将会使用data.GUI库为我们的示例添加用户操作界面,使得我们可以:

  • 控制小球弹跳的速度;
  • 控制立方体的旋转。

就像引入统计对象一样,首先我们需要在HTML的

标签中添加这个库,代码如下所示:
image.png

接下来我们需要定义一个JavaScript对象,该对象将保存希望通过dat.GUI改变的属性。在JavaScript代码中添加如下的JavaScript对象:
image.png

在这个JavaScript对象中,我们定义了两个属性—this.rotationSpeed 和this.bouncing Speed,以及它们的默认值。接下来需要将这个JavaScript对象传递给data.GUI对象,并设置这两个属性的取值范围,如下所示:
image.png

立方体旋转速度(rotationSpeed)和球体弹跳速度(bouncingSpeed)的取值范围为0~0.5。现在需要做的就是在renderScene()中直接引用这两个属性,这样当我们在dat.GUI中修改这两个属性的值时,就可以影响相应物体的旋转速度和弹跳速度。代码如下所示:
image.png

现在运行这个示例(05-control-gui.html)时,你就会看到一个可以控制弹跳速度和旋转速度的用户界面。如图1.18所示。

image.png

读者应该还记得在本章开头时创建的框架页面代码中,我们引用了TrackballControl.js文件。该文件用于实现利用鼠标移动摄像机,以便以不同角度观察场景。这一点将在第9章详细介绍。该文件同样需要初始化。由于它需要响应文档对象模型(DOM)元素的事件,它的初始化代码必须出现在下面代码中的appendChild函数调用之后。
image.png

initTrackballControls函数也定义于util.js文件中,它的具体实现将在本书后面章节中详细介绍。最后,与帧数统计模块相似,TrackballControl.js库也需要在render函数渲染完一帧后更新。
image.png

至此本章的代码便已完成。再次打开05-control-gui.html文件时,可以通过按下鼠标左键并移动鼠标来转动摄像机,以便从不同角度观察场景。此外,按S键可以拉近或拉远摄像机,按D键可以平移摄像机。如图1.19所示。
后续章节中的所有实践都将使用这个库来移动摄像机。
在运行这个示例并改变浏览器大小的时候,你可能已经发现场景是不会随着浏览器大小的改变而自动做出调整的。那么在接下来的小节中,我们会添加本章的最后一个特性来解决这一问题。

image.png

1.8 场景对浏览器的自适应

当浏览器大小改变时改变摄像机是很容易实现的。首先我们需要做的就是为浏览器注册一个事件监听器,如下所示:
image.png

这样,每当浏览器尺寸改变时onResize()方法就会被执行。在onRaise()方法中需要更新摄像机和渲染器,代码如下:
image.png

对于摄像机,需要更新它的aspect属性,这个属性表示屏幕的长宽比;对于渲染器,需要改变它的尺寸。最后我们需要将变量camera、renderer和scene的定义移到init()方法的外面,这样其他的方法(如onResize()方法)也可以访问它们。代码如下所示:
image.png
image.png

运行示例06-screen-size-change.html并改变浏览器的大小,就可以看到实际的效果。

1.9 总结

本章到此结束。在这一章里你学到了如下内容:如何搭建开发环境,如何获取本书相关的源码和示例;使用Three.js渲染场景时,首先需要做的是创建THREE.Scene对象,添加摄像机、光源和需要渲染的物体;如何给场景添加阴影和动画效果;添加辅助库dat.GUI和stats.js创建用户控制界面和快速获取场景渲染时的帧数。
在下一章中我们将会进一步扩展这个示例,你将会学到更多Three.js中非常重要的场景构建模块。

相关文章
|
1月前
|
数据采集 Web App开发 JavaScript
JavaScript爬虫进阶攻略:从网页采集到数据可视化
JavaScript爬虫进阶攻略:从网页采集到数据可视化
|
1月前
|
JavaScript 前端开发 开发者
编程笔记 html5&css&js 071 JavaScript Symbol 数据类型
编程笔记 html5&css&js 071 JavaScript Symbol 数据类型
|
1月前
|
JavaScript
JS+CSS3点击粒子烟花动画js特效
JS+CSS3点击粒子烟花动画js特效
12 0
JS+CSS3点击粒子烟花动画js特效
|
1月前
|
数据采集 JSON JavaScript
如何处理动态网页(例如使用 JavaScript 生成的内容)?
如何处理动态网页(例如使用 JavaScript 生成的内容)?
14 0
|
1月前
|
搜索推荐 前端开发 JavaScript
打造个性化的个人网页:从HTML到个人品牌
打造个性化的个人网页:从HTML到个人品牌
20 0
|
1月前
|
前端开发 JavaScript UED
前端开发的魔法:CSS动画与JavaScript的完美结合
本文将探讨如何利用CSS动画和JavaScript的结合,为前端页面增添生动的效果。我们将通过实例展示如何使用这两种技术为网页元素创建吸引人的动画效果,并讨论它们的优缺点和适用场景。
27 0
|
1月前
|
Web App开发 前端开发 JavaScript
大话 JavaScript 动画
大话 JavaScript 动画
18 1
|
1月前
|
JavaScript 前端开发 UED
JS自动跳转手机移动网页
JS自动跳转手机移动网页
454 0
|
1月前
|
JavaScript 前端开发
HTML网页自动刷新_kaic
HTML网页自动刷新_kaic
|
1月前
|
JavaScript 前端开发
编程笔记 html5&css&js 079 JavaScript 循环语句
编程笔记 html5&css&js 079 JavaScript 循环语句