Skip to main content

three.js 基础

· 9 min read
Chengzihan

three.js 简介

three.js 是一个基于 WebGLJavaScript 3D 库,它可以让你在浏览器中使用 JavaScript 创建 3D 图形。three.js 的目标是让 3D 在 Web 上变得简单。

引入 three.js

three.js 可以直接在原生 html 语法中引用。

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/three/build/three.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/three/build/three.min.js"></script>

或者可以使用 npm 安装。

npm install three

程序结构

three.js 的程序结构如下图所示。

1

基本使用

下面是一个简单的 three.js 程序。

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>第一个three.js文件_WebGL三维场景</title>
<style>
body {
margin: 0;
overflow: hidden;
/* 隐藏body窗口区域滚动条 */
}
</style>
<!--引入three.js三维引擎-->
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
<!-- <script src="./three.js"></script> -->
<!-- <script src="http://www.yanhuangxueyuan.com/threejs/build/three.js"></script> -->
</head>

<body>
<script>
/**
* 创建场景对象Scene
*/
var scene = new THREE.Scene();
/**
* 创建网格模型
*/
// var geometry = new THREE.SphereGeometry(60, 40, 40); //创建一个球体几何对象
var geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
var material = new THREE.MeshLambertMaterial({
color: 0x0000ff
}); //材质对象Material
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
/**
* 光源设置
*/
//点光源
var point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300); //点光源位置
scene.add(point); //点光源添加到场景中
//环境光
var ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);
// console.log(scene)
// console.log(scene.children)
/**
* 相机设置
*/
var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口宽高比
var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
/**
* 创建渲染器对象
*/
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
//执行渲染操作 指定场景、相机作为参数
renderer.render(scene, camera);
</script>
</body>
</html>

几何体 Geometry

//创建一个立方体几何对象Geometry
var geometry = new THREE.BoxGeometry(100, 100, 100);
// 创建一个球体几何对象
var geometry = new THREE.SphereGeometry(60, 40, 40);

材质 Material

//材质对象Material
var material = new THREE.MeshLambertMaterial({
color: 0x0000ff
});

光源 Light

//点光源
var point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300); //点光源位置
scene.add(point); //点光源添加到场景中
//环境光
var ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);

参数0xffffff定义的是光照强度。如果设置为0x000000,那么就是没有光照,如果设置为0xffffff,那么就是最大光照。three.js引擎对WebGL光照模型算法都进行了封装,不需要你了解计算机图形学, 可以直接使用调用three.js光源相关API直接创建一个光源对象。

相机 Camera

//创建相机对象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(200, 300, 200); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

把该构造函数参数中用到的参数s,也就是代码var s = 200;中定义的一个系数,可以把 200 更改为 300 ,你会发现立方体显示效果变小,这很好理解,相机构造函数的的前四个参数定义的是拍照窗口大小, 就像平时拍照一样,取景范围为大,被拍的人相对背景自然变小了。camera.position.set(200, 300, 200);camera.lookAt( scene.position);定义的是相机的位置和拍照方向,可以更改camera.position.set(200,300,200) ;参数重新定义的相机位置,把第一个参数也就是x坐标从200更改为250, 你会发现立方的在屏幕上呈现的角度变了,这就像你生活中拍照人是同一个人,但是你拍照的位置角度不同,显示的效果肯定不同。

渲染器 Renderer

//创建渲染器对象
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
//执行渲染操作 指定场景、相机作为参数
renderer.render(scene, camera);

场景——相机——渲染器

2

周期渲染

// 渲染函数
function render() {
renderer.render(scene, camera);//执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
}

//间隔20ms周期性调用函数fun,20ms也就是刷新频率是50FPS(1s/20ms),每秒渲染50次
setInterval("render()", 20);

上面代码定义了一个渲染函数render(),函数中定义了三个语句,通过setInterval("render()",20); 可以实现m每间隔20毫秒调用一次函数render(),每次调用渲染函数的时候,执行renderer.render(scene,camera); 渲染出一帧图像,执行mesh.rotateY(0.01);语句使立方体网格模型绕y轴旋转0.01弧度。

实际开发中,为了更好的利用浏览器渲染,可以使用函数requestAnimationFrame()代替setInterval() 函数,requestAnimationFrame()setInterval()一样都是浏览器window对象的方法。

// 渲染函数
function render() {
renderer.render(scene, camera);//执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render
}

render();//执行渲染函数render

鼠标动作

为了使用鼠标操作三维场景,可以借助three.js众多控件之一OrbitControls.js

可以通过npm install three-orbitcontrols安装OrbitControls.js,也可以直接下载OrbitControls.js 文件,然后在html文件中引入OrbitControls.js文件。

// 引入OrbitControls.js
<script src="js/OrbitControls.js"></script>

npm install three-orbitcontrols

首先可以使用它响应鼠标的上下左右:

function render() {
renderer.render(scene, camera);//执行渲染操作
}

render();
var controls = new THREE.OrbitControls(camera, renderer.domElement);//创建控件对象
controls.addEventListener('change', render);//监听鼠标、键盘事件

OrbitControls.js控件提供了一个构造函数THREE.OrbitControls() ,把一个相机对象作为参数的时候,执行代码new THREE.OrbitControls(camera,renderer.domElement),浏览器会自动检测鼠标键盘的变化, 并根据鼠标和键盘的变化更新相机对象的参数,比如你拖动鼠标左键,浏览器会检测到鼠标事件,把鼠标平移的距离按照一定算法转化为相机的的旋转角度,你可以联系生活中相机拍照,即使景物没有变化,你的相机拍摄角度发生了变化,自然渲染器渲染出的结果就变化了,通过定义监听事件controls.addEventListener('change', render) ,如果你连续操作鼠标,相机的参数不停的变化,同时会不停的调用渲染函数render()进行渲染,这样threejs就会使用相机新的位置或角度数据进行渲染。

执行构造函数THREE.OrbitControls()浏览器会同时干两件事,一是给浏览器定义了一个鼠标、键盘事件,自动检测鼠标键盘的变化,如果变化了就会自动更新相机的数据, 执行该构造函数同时会返回一个对象,可以给该对象添加一个监听事件,只要鼠标或键盘发生了变化,就会触发渲染函数。