canvas画布动态变化
js
// canvas画布动态变化
// 简体页面窗口变化
// 画布变化 需要更新相机和渲染参数
window.onresize = function () {
//更改画布大小
renderer.setSize(window.innerWidth,window.innerHeight);
//摄像机视锥体长宽比
camera.aspect = window.innerWidth / window.innerHeight;
//更新摄像机投影矩阵。在任何参数被改变以后必须被调用。
camera.updateProjectionMatrix();
}
阵列立方体
沿x、y、z轴分布排列,可以改变相机的fov参数观察,fov越大视野越大
js
// 循环创建阵列物体
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
for(let k=0;k<10;k++){
// 创建物体-网格模型
const mesh = new THREE.Mesh(geometry, meterial);
// 设置物体的位置
mesh.position.set(i*10, j*10, k*10);
// 将物体添加到场景中
scene.add(mesh);
}
}
}
高光网格材质
js
// 创建球形几何体
const geometry = new THREE.SphereGeometry( 30, 32, 16 );
// 高光网格材质(受光照影响、镜面反射)
const meterial = new THREE.MeshPhongMaterial({
color: 0x0000FF,
shininess:20, //亮度,默认20
specular:0xFFFFFF, //反射光颜色
})
// 创建物体-网格模型
const mesh = new THREE.Mesh(geometry, meterial);
MeshPhongMaterial
:镜面反射 类似与阳光照射到镜子
MeshLambertMaterial
:漫反射 类似于阳光照射到白纸上,不会感到刺眼
添加dat.gui.js
dat.gui.js可以快速创建控制三维场景的UI交互界面,three.js已内置,无需下载
js
// 添加dat.gui.js
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
gui改变模型位置
.add(obj,'xx',value1,value2)
添加改变的对象属性,value1、value2
为可选范围
js
// gui改变模型位置
gui.add(mesh.position,'x',0,100);
gui.add(mesh.position,'y',0,100);
gui.add(mesh.position,'z',0,100);
name方法为属性命名
js
// 为属性命名
gui.add(mesh.position,'x',0,100).name('x轴');
gui.add(mesh.position,'y',0,100).name('y轴');
gui.add(mesh.position,'z',0,100).name('z轴');
step方法为模型添加改变步长
js
// step方法为模型添加改变步长 上下箭头增减时 每次调整的大小
gui.add(rotate,'x',0,1).name('沿x轴旋转速度').step(0.01);
gui.add(rotate,'y',0,1).name('沿y轴旋转速度').step(0.01);
addColor添加颜色
js
const colorObj = {
color:0xffffff
}
gui.addColor(colorObj,'color').onChange(value=>{
// console.log(value)
mesh.material.color.set(value);
})
下拉
js
// 下拉菜单 数组或对象
gui.add(mesh.position,'x',[0,50,100]).name('x轴下拉');
gui.add(mesh.position,'y',{
左:0,
中:50,
右:100
}).name('y轴下拉');
单选
js
// 是否旋转
const rotate = {
bool:true
}
gui.add(rotate,'bool').name('是否旋转');
addFolder 添加分组
js
const gui = new GUI();
// 创建文件夹
const positionFolder = gui.addFolder('位置');
//子文件夹添加控制属性
positionFolder.add(mesh.position,'x',0,100).name('x轴');
positionFolder.add(mesh.position,'y',0,100).name('y轴');
positionFolder.add(mesh.position,'z',0,100).name('z轴');
效果展示:
完整代码
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js学习之旅-gui</title>
<script type="importmap">
{
"imports":{
"three":"./node_modules/three/build/three.module.js",
"three/addons/":"./node_modules/three/examples/jsm/"
}
}
</script>
</head>
<body>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<script type="module">
import * as THREE from 'three';
// 引入轨道控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 添加dat.gui.js
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
// 创建场景
const scene = new THREE.Scene();
// 创建长方形几何体
const geometry = new THREE.BoxGeometry(20, 20, 20); //长 宽 高
// 创建物体材质-基础网格材质(不受光照影响)
// const material = new THREE.MeshBasicMaterial({
// color: 0x0000FF
// });
//漫反射材质(受光照影响)
const material = new THREE.MeshLambertMaterial({
color: 0x0000FF
});
// 创建物体-网格模型
const mesh = new THREE.Mesh(geometry, material);
// 设置物体的位置
mesh.position.set(0, 0, 0);
// 将物体添加到场景中
scene.add(mesh);
// 定义canvas画布
const width = window.innerWidth;
const height = window.innerHeight;
// 创建相机(透视投影相机)
//PerspectiveCamera(fov, aspect, near, far)
const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 1000); // 定义相机视距大小
// 设置相机位置
camera.position.set(200, 200, 200);
// 设置相机观察目标点
camera.lookAt(0, 0, 0);
// 或者直接看物体
camera.lookAt(mesh.position);
// 添加辅助观察坐标系
// 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴 -- R G B
// AxesHelper( size : Number ) size -- (可选的) 表示代表轴的线段长度. 默认为 1.
const axesHelper = new THREE.AxesHelper(100);
scene.add(axesHelper);
//创建光源
// 环境光
const light = new THREE.AmbientLight(0xffffff);
scene.add(light);
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
// 设置光源位置
directionalLight.position.set(80, 40, 60);
// 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
directionalLight.target = mesh;
scene.add(directionalLight);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染画布大小
renderer.setSize(width, height);
// 渲染场景、相机
renderer.render(scene, camera);
// 将渲染画布插入到body中
document.body.appendChild(renderer.domElement); //renderer.domElement为渲染画布元素
// 添加轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 监听控制器事件
controls.addEventListener('change', () => {
// 执行渲染操作
renderer.render(scene, camera)
})
// 旋转物体
const rotate = {
x:0.01,
y:0.01,
bool:true
}
function render() {
// 每次执行时render()函数时,重新渲染
renderer.render(scene, camera);
// 物体沿x轴旋转
if(rotate.bool){
mesh.rotateX(rotate.x);
mesh.rotateY(rotate.y);
}
requestAnimationFrame(render); //下一帧执行函数render
}
render()
// 创建gui对象
const gui = new GUI();
// 创建文件夹
const positionFolder = gui.addFolder('位置');
const rotateFolder = gui.addFolder('旋转');
const colorFolder = gui.addFolder('颜色');
// gui改变模型位置 为属性命名
positionFolder.add(mesh.position,'x',0,100).name('x轴');
positionFolder.add(mesh.position,'y',0,100).name('y轴');
positionFolder.add(mesh.position,'z',0,100).name('z轴');
// 下拉菜单 数组或对象
positionFolder.add(mesh.position,'x',[0,50,100]).name('x轴下拉');
positionFolder.add(mesh.position,'y',{
左:0,
中:50,
右:100
}).name('y轴下拉');
// step方法为模型添加改变步长 上下箭头增减时 每次调整的大小
rotateFolder.add(rotate,'x',0,1).name('沿x轴旋转速度').step(0.01);
rotateFolder.add(rotate,'y',0,1).name('沿y轴旋转速度').step(0.01);
// 单选
rotateFolder.add(rotate,'bool').name('是否旋转');
// addColor添加颜色
const colorObj = {
color:0xffffff
}
colorFolder.addColor(colorObj,'color').onChange(value=>{
// console.log(value)
mesh.material.color.set(value);
})
</script>
</body>
</html>