JavaScript 3D动画库three.js入门篇

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 Libraryhttps://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即可。

打开CMDWindows操作系统中可用的命令行解释器应用程序),把当前目录切换到你下载后解压放置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

猜你喜欢

转载自blog.csdn.net/cnds123/article/details/121060565