threejs入门学习第一篇
Three.js
Three.js使用JavaScript语言对WebGL进行了封装,让前端开发人员不需要了解大量的专业知识也能够轻松进行web 3D开发,降低前端入门3D开发的门槛,提升开发效率。粗鄙的说就是:你不懂计算机图形学,只要理解了three.js的一些基本概念就可以开始入门web 3D开发
理解Three.js的基本要素
1、渲染器
WebGLRenderer负责将所有的数据渲染绘制到canvas上,即浏览器页面里。
2、场景
场景是所有物体的容器,需要绘制的数据都要塞到场景里,摄像机拍照后,交给渲染器去渲染到指定的canvas上
3、相机
摄像机默认指向Z轴负方向,上方向朝向Y轴正方向,默认放置在原点。一般是创建透视相机PerspectiveCamera,决定场景中哪些角度的内容会显示出来。
Three.js 使用的坐标系是右手坐标系,即右手伸开,拇指为X,四指为Y,手心为Z。
const fov = 75; // 视野范围,向上75度角观察。
const aspect = 2; // 相机默认值,画布宽高比,默认是2
const near = 0.1; // 可视区最近距离
const far = 5; // 可视区最远距离
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
4、网格
一个网格Mesh通常包括几何体(物体的形状)、材质以及在场景中的位置朝向等
兼容性检测 - detector.js
顾名思义,引入该文件用于判断浏览器对canvas、webgl的兼容性,页面增加不兼容的友好提示信息。
性能监视器 - stats.js
用于监视threejs运行中的刷新率,如果刷新率过低,说明我们的代码存在性能问题,我们需要对我们的代码做优化。
地址:https://github.com/mrdoob/stats.js
轨道控制器 - orbitControls.js
用于场景交互的,可以让我们用鼠标控制场景的平移、旋转、缩放等。
地址:https://github.com/mrdoob/three.js/blob/r145/examples/js/controls/OrbitControls.js
可视化控制 - dat.gui.js/lil-gui
顾名思义,就是直接在页面中,通过修改参数,改变我们的threejs对象的绘制。或者使用另外一个插件lil-gui,这个插件我在r145版本里看见在使用
地址:https://github.com/dataarts/dat.gui
一个最基础的示例 - 只是用于学习
对应的js文件
<!DOCTYPE html>
<html lang="zh-CN">
<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: 0px; padding: 0px; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<canvas id="three_canvas"></canvas>
<div id="webgl_warning"></div>
<script src="../lib/three.js"></script>
<script src="../lib/detector.js"></script>
<script src="../lib/controls/orbitControls.js"></script>
<script src="../lib/stats/stats.js"></script>
<script src="../lib/dat-ui/dat.gui.js"></script>
<script>
// 准备场景、相机、渲染器、光线
let scene = null;
let camera = null;
let renderer = null;
let light = null;
let stats = null;// 性能监控
let controls = null;// 轨道控制器,必须等相机和渲染器创建完毕
let GUIOBJ = null;
let gui = null;// 可视化控制
let initThree = function() {
// 增加一个性能监视器
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
// 创建渲染器
const canvas = document.querySelector('#three_canvas');
renderer = new THREE.WebGLRenderer({canvas});// 创建渲染器,canvas可传可不传。传一个canvas对象更灵活
renderer.setPixelRatio(window.devicePixelRatio);// 设置渲染器的分辨率倍数,分辨率越高消耗的资源越多
renderer.setSize(window.innerWidth, window.innerHeight);// 设置渲染器的宽高
// 创建相机
const fov = 75;// 视野范围,垂直方向75度角
const aspect = window.innerWidth / window.innerHeight;// 画布的宽高比,默认是2,建议使用画布在浏览器里的大小比,
const near = 0.1;// 近平面
const far = 1000;// 远平面,近平面和远平面限制了摄像机面朝方向的可绘区域,任何距离小于或超过这个范围的物体都将被裁剪掉(不绘制)
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
// 增加一个轨道控制器
controls = new THREE.OrbitControls(camera, canvas);
camera.position.z = 5;// 设置相机距离原点的距离,相机z轴移动,避免相机与场景里的物体重合
// 对相机有任何操作,必须更新控制器
controls.update();
GUIOBJ = {
name: "GUI Control",
width: 1,
height: 1,
depth: 1,
speed: 0.001
};
gui = new dat.GUI();
gui.add(GUIOBJ, "name");
gui.add(GUIOBJ, "width");
gui.add(GUIOBJ, "height");
gui.add(GUIOBJ, "depth");
gui.add(GUIOBJ, "speed").min(0).max(1).step(0.001);
// 创建场景
scene = new THREE.Scene();
// 创建一束光线
const color = 0xFFFFFF;// 光颜色
const intensity = 1;// 光照强度
light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);// 设置光源发射点的位置
scene.add(light);
// 增加坐标轴 轴线长100
const axes = new THREE.AxesHelper(100);
scene.add(axes);
}
// 初始化立方体
let cube = null;
let initBox = function() {
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
const material = new THREE.MeshPhongMaterial({color: 0xff0000});// MeshPhongMaterial受到灯光影响的材质
cube = new THREE.Mesh(geometry, material);
scene.add(cube);
}
let animate = function (time) {
cube.scale.x = GUIOBJ.width;
cube.scale.y = GUIOBJ.height;
cube.scale.z = GUIOBJ.depth;
// 给立方体加一个小动画
time *= GUIOBJ.speed;
cube.rotation.x = time;
cube.rotation.y = time;
// 渲染场景和相机
renderer.render(scene, camera);
// 随动画更新性能监视器
stats.update();
// 随动画更新控制器 如果 controls.enableDamping 或 controls.autoRotate 设置为 true
controls.update();
// 回调动画
requestAnimationFrame(animate);
}
if (Detector.webgl) {
// 启动方法或其他初始化方法
initThree();
initBox();
animate();
} else {
let warning = Detector.getWebGLErrorMessage();
document.getElementById('webgl_warning').appendChild(warning);
}
</script>
</body>
</html>
BoxGeometry 几何体
可构造立方体或者长方体等几何体
new THREE.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
// 六个参数分别为宽x轴、高y轴、深z轴、x轴方向上分割成几份、y轴方向上分割成几份、z轴方向上分割成几份
宽、高、深这三个参数是必须的,widthSegments、heightSegments、depthSegments默认是1
CircleGeometry 圆形平面
可构造正三角形、正多边形、圆、半圆形
new THREE.CircleGeometry(radius, segments, thetaStart, thetaLength)
// 四个参数分别为半径
// 平面由多少部分分割组成,最少是3个,默认是8个
// 起始角
// 圆的角度,画多大的圆,最大是2 * Math.PI,即一个圆的弧度值
ConeGeometry 锥形
setAnimationLoop
创建动画时,建议使用渲染器的setAnimationLoop代替window.requestAnimationFrame方法