three.js
一、第一个three.js程序
1.1 引入three.js
学习three.js前需简单了解node.js
运行前需安装 live-server,安装命令cnpm install live-server -g
运行程序命令 live-server
第一个three.js程序:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script>
// Our Javascript will go here.
</script>
</body>
</html>
效果:
1.2 创建场景
在three.js中显示东西,我们需要三样东西:scene, camera和renderer,这样我们就可以用camera渲染场景。
在之前的script中添加代码
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
效果:
1.3 创建立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
要创建一个立方体,我们需要一个BoxGeometry。这是一个包含立方体的所有点(顶点)和填充(面)的对象。我们将在未来对此进行更多的探索。
除了几何形状之外,我们还需要一种材质来给它上色。Three.js自带了几个材质,但我们现在只使用MeshBasicMaterial。所有材料都有一个将被应用于其上的属性对象。为了保持简单,我们只提供一个颜色属性0x00ff00,它是绿色的。这与颜色在CSS或Photoshop(十六进制颜色)中的工作方式相同。
我们需要的第三样东西是一个网格。网格是一个对象,它接受一个几何,并应用一个材料,然后我们可以插入到我们的场景中,并自由移动。
默认情况下,当我们调用scene.add()时,我们添加的东西将被添加到坐标(0,0,0)中。这将导致摄像机和立方体都在对方的内部。为了避免这种情况,我们简单地将摄像机移出一点。
1.4 渲染场景
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
效果:
1.5 动画多维数据集
如果您将上述所有代码插入到您在开始之前创建的文件中,您应该会看到一个绿色框。旋转一下,让它更有趣一些。
在渲染器的右上方添加如下内容。在你的动画函数渲染调用:
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
这将每帧运行一次(通常是每秒60次),并给立方体一个漂亮的旋转动画。基本上,当应用运行时,任何你想移动或改变的东西都必须经过动画循环。你当然可以从那里调用其他函数,这样你就不会最终得到一个有几百行代码的动画函数。
效果:
1.6 第一个three.js的全部代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
二、
2.1、绘直线
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script>
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 500 );
camera.position.set( 0, 0, 100 );
camera.lookAt( 0, 0, 0 );
const scene = new THREE.Scene();
const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );
const points = [];
points.push( new THREE.Vector3( - 10, 0, 0 ) );
points.push( new THREE.Vector3( 0, 10, 0 ) );
points.push( new THREE.Vector3( 10, 0, 0 ) );
const geometry = new THREE.BufferGeometry().setFromPoints( points );
const line = new THREE.Line( geometry, material );
scene.add( line );
renderer.render( scene, camera );
</script>
</body>
</html>
三、创建地球案例
3.1、创建一个可鼠标拖动的球
<!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="js/three.js"></script>
<script src="OrbitControls.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对象
//执行渲染操作 指定场景、相机作为参数
function render() {
renderer.render(scene,camera);//执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render
}
render();
// 已经通过requestAnimationFrame(render);周期性执行render函数,没必要再通过监听鼠标事件执行render函数
var controls = new THREE.OrbitControls(camera, renderer.domElement);
</script>
</body>
</html>
效果如下:
3.2、增加贴图
增加地图图片
var texLoader = new THREE.TextureLoader();
var material = new THREE.MeshLambertMaterial({
// color: 0x0000ff,
map: texLoader.load('./贴图/diffuse.png'),
}); //材质对象Material
可以看到,光线不是很均匀
3.3、改变光源
改变光线,将点光源改变为两束平行光
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
directionalLight.position.set(400, 200, 300);
scene.add(directionalLight);
// var point = new THREE.PointLight(0xffffff);
// point.position.set(100, 100, 100); //点光源位置
// scene.add(point); //点光源添加到场景中
var directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.9);
directionalLight2.position.set(-400, -200, -300);
scene.add(directionalLight2);
3.4、改变环境光
var ambient = new THREE.AmbientLight(0xffffff, 0.6);
//var ambient = new THREE.AmbientLight(0x444444);
3.5、改变背景颜色,修改球大小,增加凹凸性
var geometry = new THREE.SphereGeometry(100, 40, 40); //创建一个球体几何对象
//renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
var material = new THREE.MeshPhongMaterial({
// color: 0x0000ff,
map: texLoader.load('./贴图/diffuse.png'),
normalMap: texLoader.load('./贴图/normal.png'),
//设置深浅程度,默认值(1,1)。
normalScale: new THREE.Vector2(2, 2),
}); //材质对象Material
3.6、创建地球的全部代码
<!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="js/three.js"></script>
<script src="OrbitControls.js"></script>
</head>
<body>
<script>
/**
* 创建场景对象Scene
*/
var texLoader = new THREE.TextureLoader();
var scene = new THREE.Scene();
/**
* 创建网格模型
*/
// TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
// var geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
var geometry = new THREE.SphereGeometry(100, 25, 25);
// MeshLambertMaterial
var material = new THREE.MeshPhongMaterial({
// color: 0x0000ff,
// 设置颜色贴图
map: texLoader.load('./贴图/diffuse.png'),
//法线贴图
normalMap: texLoader.load('./贴图/normal.png'),
//设置深浅程度,默认值(1,1)。
normalScale: new THREE.Vector2(2, 2),
//高光贴图
specularMap: texLoader.load('./贴图/specular.png'),
}); //材质对象Material
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
scene.add(mesh); //网格模型添加到场景中
/**
* 光源设置
*/
// 平行光1
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
directionalLight.position.set(400, 200, 300);
scene.add(directionalLight);
// 平行光2
var directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.9);
directionalLight2.position.set(-400, -200, -300);
scene.add(directionalLight2);
//环境光
var ambient = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambient);
/**
* 相机设置
*/
var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口宽高比
var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
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({
antialias: true, //开启锯齿
});
renderer.setSize(width, height); //设置渲染区域尺寸
// renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
//mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}
render();
//创建控件对象 相机对象camera作为参数 控件可以监听鼠标的变化,改变相机对象的属性
var controls = new THREE.OrbitControls(camera, renderer.domElement);
</script>
</body>
</html>
四、创建天体运行案例
4.1、给地球添加三维坐标
var axesHelper = new THREE.AxesHelper(200);
scene.add(axesHelper);
其中200为三维坐标的长度
4.2、 创建另一个天体形状
首先缩小地球
var geometry = new THREE.SphereGeometry(10, 25, 25); // 20 代表圆的直径
创建太阳
var geometry2 = new THREE.SphereGeometry(30, 25, 25);
var material2 = new THREE.MeshBasicMaterial({
// 设置颜色贴图
map: texLoader.load('./贴图/太阳.jpg'),
}); //材质对象Material
var mesh2 = new THREE.Mesh(geometry2, material2); //网格模型对象Mesh
scene.add(mesh2); //网格模型添加到场景中
将地球进行沿着z轴平移
mesh.position.z = 150
开启自转
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
mesh2.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}
效果如下
4.3、 使地球公转
通过angle改变位置
var R = 130;// 地球公转半径
var angle = 0;
// 渲染函数
function render() {
renderer.render(scene, camera); //执行渲染操作
mesh.rotateY(0.02);//每次绕y轴旋转0.01弧度
mesh2.rotateY(0.01);//每次绕y轴旋转0.01弧度
angle += 0.01;// 每次执行render角度新增加
var x = R*Math.sin(angle);//地球x坐标计算
var z = R*Math.cos(angle);//地球z坐标计算
// 设置地球xz坐标,实现公转动画
mesh.position.set(x,0,z);
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}
效果图:
4.4、 绘制轨迹路线
var R = 130;// 地球公转半径
circle(R);//调用函数circle绘制圆弧轨迹
function circle(r) {
// ArcCurve创建一个圆弧曲线
var arc = new THREE.ArcCurve(0, 0, r, 0, 2 * Math.PI, true);
// 获取点数越多,圆弧越光滑
var points = arc.getPoints(100); //返回一个vector2对象作为元素组成的数组
// console.log('points', points);
var geometry = new THREE.Geometry();
//setFromPoints方法的本质:遍历points把vector2转变化vector3
geometry.setFromPoints(points);
var material = new THREE.LineBasicMaterial({
color: 0x006666,
});
// THREE.Line
var line = new THREE.LineLoop(geometry, material); //起始点闭合
// 圆弧线默认在XOY平面上,绕x轴旋转到XOZ平面上
line.rotateX(Math.PI / 2);
scene.add(line);
}