JavaScript 3D动画库three.js入门篇
JavaScript 3D动画库three.js入门篇
什么是three.js?你将它理解成three+js,three表示3D的意思,js表示JavaScript的意思,合起来,three.js就是使用JavaScript来写3D程序的意思。three.js是WebGL的一个运行在浏览器上的开源框架,它省去了很多麻烦的细节,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。
JavaScript 3D动画库three.js入门篇
什么是three.js?你将它理解成three+js,three表示3D的意思,js表示JavaScript的意思,合起来,three.js就是使用JavaScript来写3D程序的意思。three.js是WebGL的一个运行在浏览器上的开源框架,它省去了很多麻烦的细节,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。
Three.js官网: Three.js – JavaScript 3D Library 或 https://github.com/mrdoob/three.js
three.js官网中文文档three.js docs
Threejs中文网Three.js中文网
three.js库目录结构详解
如果你直接想使用其中的three.js编辑器,或运行示例文件夹下的例子,请认真仔细的阅读这一部分。如果你想尽快感性认识一下three.js库创建3D动画的乐趣,也可以先跳过这一部分,先看第二部分,回头再看这部分。
下载解压后的目录结构如下图:
请留意Build文件夹中包含的文件,这是three.js最终被引用的文件。three.js 是没有压缩的js文件,three.min.js已经压缩,使用这两者之一即可。three.module.js是从r106版本开始出现的模块方式。
three.js-master目录结构示意图:
特别提示:现在先介绍一下这个下载包的使用,如果你直接想使用其中的three.js编辑器,或运行示例文件夹下的例子,在未按如下步骤配置前,你看不到效果,这是对初学者最易掉进的坑。
在CMD(Windows操作系统中可用的命令行解释器应用程序)中使用npm -v命令进行npm的版本号的查看,若提示:'npm' 不是内部或外部命令,也不是可运行的程序或批处理文件。说明未安装,npm是nodejs的一个子内容,所以要使用npm,安装nodejs即可。
打开CMD(Windows操作系统中可用的命令行解释器应用程序),把当前目录切换到你下载后解压放置three.js-master目录(文件夹)下,我这里是:D:\three.js-master
再运行npm install http-server -g 安装一个简单的HTTP服务器 (其中g代表全局范围内安装http服务器,以便它可以在任何地方从命令行运行)
接着运行http-server . -p 8000 启动HTTP服务器 (其.代表当前路径,8000是使用端口)
【http-server的使用官网介绍见http-server - npm】
参见下图:
然后可以在浏览器地址栏打开 http://127.0.0.1:8000
参见下图:
若显示如上图,这就OK了!
之后,只要先启动你刚才设置的本地HTTP服务器,再在浏览器地址栏打开 http://127.0.0.1:8000[/路径[/文件名]]就可以了,如:http://127.0.0.1:8000 或http://127.0.0.1:8000/editor
打开three.js编辑器,界面如下图:
使用该编辑器,可以用图形化方法创建Three.js场景。在编辑器里面可以通过鼠标拖动几何体、光源、照相机的位置移动,three.js可视化编辑工具的出现也是为了方便开发,但编辑工具作用只是辅助工作如确定参数,并不能做所有的工作。
单击File→Import可以导入3d模型,这里我选择了一个obj文件,参见下图:
鼠标滚轮控制远近大小,按住左键拖动鼠标旋转模型,按住右键拖动鼠标平移模型。单击Add菜单,在这个菜单下可以看到DirectionalLight(平行光),PointLight(点光),SpotLight(聚光灯)等多种选项。在此就不多介绍了。
使用three.js库来创建3D动画
要使用Three.js,可以通过script 标签引入Three.js,也可以通过 NPM 安装Three.js(这种方式是从r106版本开始出现的)。
通过script标签来引入three.js,又有两种方式:
一是使用CDN(Content Delivery Network,即内容分发网络),如:
<script src="https://cdn.bootcss.com/three.js/91/three.min.js"></script>
这种方式需要联网才有效。
二是将从Three.js的官方网站下载three.js或three.min.js文件(在下载包的Build文件夹中)复制到适当位置,这儿以存放到HTML文件所在的文件夹的子文件夹js中,如:<script src="js/three.min.js"></script>
这种方式不需要联网。
通过script标签来引入three.js比较简单,适合简单的练习,快速体验。下面给出通过script标签引入three.js的例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My First three.js app</title>
<script src="js/three.min.js"></script>
<style>
body{margin:0;}
canvas{width:100%;height:100%;}
</style>
</head>
<body>
<script>
// 场景
var scene = new THREE.Scene();
// 摄像机
var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,000);
// 渲染器
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;
// 动画
var animate = function(){
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene,camera); //渲染
};
animate();
</script>
</body>
</html>
保存文件名为:three.js例1.html,用浏览器运行之,运行效果如下图:
写three.js的页面基本结构如下:
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title></title>
<!—引入three.js或three.min.js,后者是压缩的,路径根据实际情况写 -->
<script> src="路径/three.js" </script>
</head>
<body>
<script>
//此处放置脚本
</script>
</body>
</html>
下面给出一个例子,此例通过script标签和CDN来引入three.min.js,实现一个旋转的球源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My First three.js app2</title>
<style>
*{
margin:0;
padding:0;
}
canvas{
width:100%;
height: 100%;
}
</style>
<script src='https://cdn.bootcss.com/three.js/91/three.min.js'></script>
</head>
<body>
<script>
//创建场景
var scene=new THREE.Scene();
//创建透视投影相机,视角45度,画幅比例 宽比高,近平面距离0.1,远平面1000
var camera=new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);
//创建渲染器
var renderer=new THREE.WebGLRenderer();
//渲染器canvas宽高设为与窗口一致
renderer.setSize(window.innerWidth,window.innerHeight);
//将渲染器对应的dom元素添加到body中
document.body.appendChild(renderer.domElement);
//定义一个几何体
var geometry=new THREE.SphereGeometry(3,30,30);
//定义一种材质,显示为线框
var material = new THREE.MeshBasicMaterial({color:0xB3DD,wireframe:true});
//网孔(Mesh)是用来承载几何模型的一个对象,可以把材料应用到它上面
var ball=new THREE.Mesh(geometry, material);
//把几何模型添加到场景中,对象被添加到原点(0,0,0)坐标。
scene.add(ball);
//移动相机位置
camera.position.z = 8;
function render() {
//渲染循环,以每秒60次的频率来绘制场景
requestAnimationFrame( render );
//设置球体绕y轴旋转
ball.rotation.y += 0.005;
renderer.render( scene, camera );
}
render();
</script>
</body>
</html>
保存文件名为:three.js例2.html,用浏览器运行之,运行效果如下图:
下面简要介绍Three.js中的一些概念
要在屏幕上展示3D图形,思路大体上都是这样的:
1、构建一个三维空间
Three中称之为场景(Scene),场景是所有物体的容器,也对应着我们创建的三维世界。
2、选择一个观察点,并确定观察方向/角度等。
Three中称之为相机(Camera)
3、在场景中添加供观察的物体
Three中的物体有很多种,包括Mesh,Line,Points等,它们都继承自Object3D类。
4、将观察到的场景渲染(Renderer)到屏幕上的指定区域
Three中使用Renderer完成这一工作。
为了观察这个世界,描述空间中的位置,需要使用三维坐标系,有两种表示方式:
Three中采用常见的右手坐标系定位。
Three中的相机有两种,分别是正投影相机THREE.OrthographicCamera和透视投影相机THREE.PerspectiveCamera,正交投影与透视投影的区别如下图所示,左图是正交投影,物体发出的光平行地投射到屏幕上,远近的方块都是一样大的;右图是透视投影,近大远小,符合我们平时看东西的感觉。
正交投影相机
图中的”视点”对应着Three中的Camera。
这里补充一个视景体的概念:视景体是一个几何体,只有视景体内的物体才会被我们看到,视景体之外的物体将被裁剪掉。这是为了去除不必要的运算。
正交投影相机的视景体是一个长方体,OrthographicCamera的构造函数是这样的:
OrthographicCamera( left, right, top, bottom, near, far )
Camera本身可以看作是一个点,left则表示左平面在左右方向上与Camera的距离。另外几个参数同理。于是六个参数分别定义了视景体六个面的位置。
可以近似地认为,视景体里的物体平行投影到近平面上,然后近平面上的图像被渲染到屏幕上。
透视投影相机
透视投影相机的视景体是个四棱台,它的构造函数是这样的:
PerspectiveCamera( fov, aspect, near, far )
fov对应着图中的视角,是上下两面的夹角。aspect是近平面的宽高比。在加上近平面距离near,远平面距离far,就可以唯一确定这个视景体了。
透视投影相机很符合我们通常的看东西的感觉,因此大多数情况下我们都是用透视投影相机展示3D效果。
Three中供显示的物体(Objects)有很多,它们都继承自Object3D类,这里我们主要看一下Mesh和Points两种。
1)Mesh(网格)
计算机的世界里,一条弧线是由有限个点构成的有限条线段连接得到的。线段很多时,看起来就是一条平滑的弧线了。
计算机中的三维模型也是类似的,普遍的做法是用三角形组成的网格来描述,我们把这种模型称之为Mesh模型。
看这只兔子,随着三角形数量的增加,它的表面越来越平滑/准确。
在Three中,Mesh的构造函数是这样的:
Mesh( geometry, material )
2)Geometry(形状、几何形状)
Geometry通过存储模型用到的点集和点间关系(哪些点构成一个三角形)来达到描述物体形状的目的。
Three提供了立方体(其实是长方体)、平面(其实是长方形)、球体、圆形、圆柱、圆台等许多基本形状;
你也可以通过自己定义每个点的位置来构造形状;
对于比较复杂的形状,我们还可以通过外部的模型文件导入。
3)Material(材质)
材质其实是物体表面除了形状以为所有可视属性的集合,例如色彩、纹理、光滑度、透明度、反射率、折射率、发光度。
材质(Material)、贴图(Map)和纹理(Texture)的关系。
材质上面已经提到了,它包括了贴图以及其它。
贴图其实是“贴”和“图”,它包括了图片和图片应当贴到什么位置。
纹理嘛,其实就是“图”了。
Three提供了多种材质可供选择,能够自由地选择漫反射/镜面反射等材质。
4)Points(点)
Points其实就是一堆点的集合,它在之前很长时间都被称为ParticleSystem(粒子系统),r68版本时更名为PointCloud,r72版本时才更名为Points。更名主要是因为,Mr.doob认为,粒子系统应当是包括粒子和相关的物理特性的处理的一套完整体系,而Three中的Points简单得多。因此最终这个类被命名为Points。
5)Light(光)
光影效果是让画面丰富的重要因素。
Three提供了包括环境光AmbientLight、点光源PointLight、 聚光灯SpotLight、方向光DirectionalLight、半球光HemisphereLight等多种光源。
可在场景中添加需要的光源。
6)Renderer(场景)
在场景中建立了各种物体,也有了光,还有观察物体的相机,是时候把看到的东西渲染到屏幕上了。这就是Render做的事情了。
Renderer绑定一个canvas对象,并可以设置大小,默认背景颜色等属性。
调用Renderer的render函数,传入scene和camera,就可以把图像渲染到canvas中了。
怎么才能让静态的画面动起来?
改变场景中object的位置啊角度啊各种属性,然后重新调用render函数渲染就好了。
那么重新渲染的时机怎么确定?
HTML5为我们提供了requestAnimFrame,它会自动在每次页面重绘前调用传入的函数。
如果我们一开始这样渲染:
function render()
{
renderer.render(scene, camera);
}
只需要改成这样:
function render()
{
requestAnimationFrame(render);
object.position.x += 1;
renderer.render(scene, camera);
}
object就可以动起来了!
Three.js动效方案 掘金
通过NPM安装three.js
这种安装three 的 npm 模块的方式是从r106版本开始出现的。目前,这种方式需要结合某种构建工具(bundling tool)使用,比较麻烦。
【模块(module)本质上是JavaScript 文件,其中按规范包含各种功能——变量和函数,这些功能作为库公开给其他模块或用户编写的JavaScript 文件使用。
对于ES modules,想进一步学习了解可见下列链接
了解JavaScript中的ES模块 - 51CTO.COM
【翻译】ES modules:通过漫画进行深入理解 - 知乎
掘金 】
可以先在CMD(Windows操作系统中可用的命令行解释器应用程序)中使用npm -v命令进行npm的版本号的查看,若提示:'npm' 不是内部或外部命令,也不是可运行的程序或批处理文件。说明未安装,npm是nodejs的一个组成部分,所以要使用npm,安装nodejs即可。
要安装three 的 npm 模块的步骤【参见 three.js docs】,打开cmd窗口,先切换到你的项目文件夹(我这儿是D:\测试文件夹2),并运行:
npm install --save three
参见下图:
包将会被下载并安装。
然后你就可以将它导入你的代码了:
//方式 1: 导入整个 three.js核心库
import * as THREE from 'three';
const scene = new THREE.Scene();
//方式 2: 仅导入你所需要的部分
import { Scene } from 'three';
const scene = new Scene();
目前,这种方式需要结合某种构建工具(bundling tool)使用,在此不深入介绍了,感兴趣的读者,可参见:vue页面引入three.js创造3d动画场景 vue页面引入three.js创造3d动画场景_程可爱的博客-CSDN博客
参考
郭隆邦_技术博客 WebGL
如何运行threejs里的examples 如何运行threejs里的examples_whahu1989的专栏-CSDN博客
Three.js库开发3D程序(简易教程)Three.js库开发3D程序(简易教程)_哔哩哔哩_bilibili
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)