之前一直对three.js比较好奇,但是一直没有着手学习。今天刷到一篇博客(博主:1_bit),觉得挺有意思,就跟着敲了一下。
html:
其中canvas用于添加渲染好的元素,本篇文章通过CDN形式引入three.js,另外一个js则是我们自己编写的代码
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div id="canvas"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/0.151.3/three.min.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
css:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
html{
width: 100vw;
height: 100vh;
overflow: hidden;
background: linear-gradient(to bottom, #11e8bb 0%, #8200c9 100%);
}
进入正题:
具体操作,在代码的注释中我都有写,就不在赘述了。以下就是完整的js代码
var renderer, scene, camera, inside, outside, particle;
window.onload = function () {
// 创建对象存储三要素(渲染器、场景、摄像头)
/**
* 渲染器
* 通过调用 THREE 对象的 WebGLRenderer 对摄像头进行创建,WebGLRenderer 方法接收传入一个渲染器的配置项对象
* antialias 表示抗锯齿打开,使几何体边缘平滑
* alpha 表示渲染器渲染时的画面有透明通道,若不打开将不会存在透明通道
*/
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
// 设置渲染器大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 获取canvas,并将渲染器添加到canvas窗口
// renderer.domElement 是得到渲染器渲染出的 canvas
document.querySelector('#canvas').appendChild(renderer.domElement)
/**
* 场景
* 通过 THREE 的 Scene 方法即可创建
*/
scene = new THREE.Scene()
/**
* 摄像头
* 使用 PerspectiveCamera 创建透视摄像头
* 参数含义:
* 相机可视垂直视野角度,相机可视长宽比,相机近端距离,相机远端距离
* 若可视物体小于了 相机近端距离 和 大于了 相机远端距离 都会不可见
*/
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
// 移动摄像头的 Z 轴,此时 z 轴就相当是人的视野
camera.position.z = 500
// 将摄像头加入到场景当中
scene.add(camera)
/**
* 创建几何体
*/
// 通过 IcosahedronGeometry 方法创建两个20面的几何体
// 参数含义:
// 1. 二十面体的半径,默认为1;
// 2.设置面角,默认为0,值超过1则是球体,超过0小于1则会增加顶点使其转变成非二十面几何体
var geom = new THREE.IcosahedronGeometry(7, 1)
var geom2 = new THREE.IcosahedronGeometry(15, 1)
// 为20面体创建显示样式(创建材质)
var mat = new THREE.MeshPhongMaterial({
color: 0xffffff,
shading: THREE.FlatShading //网格的渲染方式(之后要使用的网格),在此使用
})
var mat2 = new THREE.MeshPhongMaterial({
color: 0xffffff,
wireframe: true, // 渲染的网格将会呈现线框形式
side: THREE.DoubleSide // 双面渲染; THREE.FrontSide:单面渲染
})
// 创建 Mesh,用于组装3D对象
var planet = new THREE.Mesh(geom, mat)
// 对 planet 进行缩放显示
planet.scale.x = planet.scale.y = planet.scale.z = 16
// 创建Object3D,用于存放几何体
inside = new THREE.Object3D()
inside.add(planet)
scene.add(inside)
// 创建第二个 Mesh,并创建Object3D 对象存放
var planet2 = new THREE.Mesh(geom2, mat2);
planet2.scale.x = planet2.scale.y = planet2.scale.z = 10
outside = new THREE.Object3D();
outside.add(planet2);
scene.add(outside);
/**
* 创建光源
* 通过方法 AmbientLight 创建环境光,传入环境光颜色
// */
var ambientLight = new THREE.AmbientLight(0x999999);
scene.add(ambientLight);
/**
* 创建太阳光
* 通过 DirectionalLight 进行创建,
* 参数含义:
* 1.光照颜色,2.光照强度,默认为1
*/
var ligthts1 = new THREE.DirectionalLight(0xffffff,1)
ligthts1.position.set(1,0,0)
var ligthts2 = new THREE.DirectionalLight(0x11E8BB,1)
ligthts2.position.set(0.75,1,0.5)
var ligthts3 = new THREE.DirectionalLight(0x8200C9,1)
ligthts3.position.set(-0.75,-1,0.5)
scene.add(ligthts1)
scene.add(ligthts2)
scene.add(ligthts3)
// 创建环境物体
// 创建一个3D容器,并将其加入到场景中
particle = new THREE.Object3D();
scene.add(particle);
// 创建一个四面体,参数含义:1.半径,2.面角
var geometry = new THREE.TetrahedronGeometry(2, 0);
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
shading: THREE.FlatShading
});
for (var i = 0; i < 1000; i++) {
var mesh = new THREE.Mesh(geometry, material);
mesh.position.set(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize();
mesh.position.multiplyScalar(90 + (Math.random() * 700));
mesh.rotation.set(Math.random() * 2, Math.random() * 2, Math.random() * 2);//旋转
particle.add(mesh);
}
animate()
}
// 动画
function animate() {
requestAnimationFrame(animate);
particle.rotation.x += 0.0010;
particle.rotation.y -= 0.0040;
inside.rotation.x -= 0.0020;
inside.rotation.y -= 0.0030;
outside.rotation.x -= 0.0010;
outside.rotation.y += 0.0020;
renderer.clear();
// 渲染
renderer.render(scene, camera)
};
效果演示:
今日寄语:种一棵树最好的时间是十年前,其次是现在!