07-three.js Debug UI
Three.js Journey — Learn WebGL with Three.jsThe ultimate Three.js course whether you are a beginner or a more advanced developerhttps://threejs-journey.com/?c=p3
lil-gui的安装
在终端中(如果服务器未运行,或者在同一文件夹中打开另一个终端窗口),运行 npm install lil-gui,
安装成功后,将其导入 script.js ,再重启服务器:
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import gsap from 'gsap'
import GUI from 'lil-gui'
// console.log(GUI);
/**
* Debug
*/
const gui = new GUI()
不同的调整类型
1.范围
/**
* Debug
*/
const gui = new GUI()
// 方式2:const gui = new dat.GUI() // 范围 —带最小值和最大值的数字
// 颜色 —各种格式的颜色
// 文本 —简单的文本
// 复选框 —布尔值(true 或 false)
// Select —用于从值列表中进行选择
// Button —用于触发功能// 1.范围
gui.add(mesh.position, 'y')
2.复选框
// 2.复选框
// lil-gui 会自动检测你想要调整的属性类型,并使用相应的界面
gui.add(mesh, 'visible')
// 2.1 wireframe
// 布尔值,wireframe 属性(位于 material 中)
gui.add(material, 'wireframe')
3.颜色
【重难点】
// 3.颜色
// 注意,颜色不能使用 .add(),而是使用 .addColor(),因为颜色是一个对象
gui.addColor(material, 'color')
3.1取色器色值修正
取色器色值修正,思路是通过onChange()监听全局变量对象 debugObject.color 的变化来.set() material.color。
方法步骤:
// 取色器色值修复,步骤1:
gui.addColor(material, 'color') // 这处后面会修改.onChange((value)=>{// console.log('color is changing!'); console.log(material.color);console.log(value); })
/*** debugObject*/
const debugObject = {}
debugObject.color = '#ff0000' // 取色器色值修复 步骤2,在全局一开始就设置一个debug对象,修改内容都从这个对象里改
gui.addColor(debugObject, 'color') // 取色器色值修复 步骤3.1,将绑定从 material.color 改为 debugObject.color.onChange((value)=>{// console.log('color is changing!'); // console.log(material.color);// console.log(value);// console.log(value.getHexString()) // 取色器色值修复 步骤3.2,赋值material.color.set(debugObject.color) console.log('更新后的颜色', material.color.getHexString());})
4.函数/按钮
// 4.函数 / 按钮
// 通过创建的`debugObject`对象,在其中添加一个名为`spin`的属性,并将其与 GSAP 动画集成
debugObject.mesh1Spin = () => {gsap.to(mesh1.rotation, { duration: 1, y: mesh1.rotation.y + Math.PI * 2 })
}
debugObject.mesh2Spin = () => {gsap.to(mesh2.rotation, { duration: 1, x: mesh2.rotation.x + Math.PI * 2 })
}
gui.add(debugObject, 'mesh1Spin').name('mesh1 spin')
gui.add(debugObject, 'mesh2Spin').name('mesh2 spin')
5.调整几何细分
// 5.调整几何细分
// 先在创建的`debugObject`对象设置一个属性,subdivision
debugObject.subdivision = 3
// 使用 `onFinishChange`,当我们停止调整值时才会触发更新
gui.add(debugObject, 'subdivision').min(1).max(20).step(1).onFinishChange(() => {// console.log('subdivision finished changing', debugObject.subdivision);// 将新值赋给 `mesh` 的 `geometry` 属性// 先清掉旧的几何体,否则旧的几何体仍然存在于 GPU 内存中,这可能会导致内存泄漏mesh1.geometry.dispose()mesh1.geometry = new THREE.BoxGeometry(1, 1, 1,debugObject.subdivision, debugObject.subdivision, debugObject.subdivision)mesh2.geometry.dispose()mesh2.geometry = new THREE.BoxGeometry(1, 1, 1,debugObject.subdivision, debugObject.subdivision, debugObject.subdivision)})
6.文件夹
// 6.文件夹
const itemTweaks = gui.addFolder('my items')
// 可设置默认关闭
itemTweaks.close()
itemTweaks.add(myObject, 'myVariable')
7.非属性的调整
lil-gui 只能修改属性,如果想更新一个变量,可以使用一些技巧来实现。如果需要和材质或网格相关联,还需要通过 .onChange() 或 .set() 来另外设置。
例如创建一个对象,其目的是为 lil-gui 持有的属性提供存储空间:
// 非属性的调整
const myObject = {myVariable: 1337
}
gui.add(myObject, 'myVariable')
GUI样式设置与触发开关
/**
* Debug
*/
// gui的样式设置
const gui = new GUI({width: 312, // 宽度title: 'my debug UI', // 标题closeFolders: false // 是否关闭其中文件夹
})
gui.close() // 关闭整个面板
gui.hide() // 隐藏整个面板
【注】gui._hidden 属性,该属性表示当前是否被隐藏,为布尔值,可切换显示状态
window.addEventListener('keydown', (e) => {if (e.key == 'h')gui.show(gui._hidden)
})
练习
练习,将双击事件设置为 debug UI 触发开关,如果在debugUI界面点击快了也会令其消失
// 练习
window.addEventListener('dblclick', () => {// 注释原来的双击全屏// if (!document.fullscreenElement) {// canvas.requestFullscreen();// } else {// document.exitFullscreen();// }gui.show(gui._hidden)
})
// 练习 end
练习,相机的移动,注意,OrbitControls会影响camera的lookAt
// 练习
gui.add(camera.position, 'x').min(-3).max(3).step(0.01).name('camera x')
gui.add(camera.position, 'y').min(-3).max(3).step(0.01).name('camera y')
gui.add(camera.position, 'z').min(3).max(8).step(0.01).name('camera z')
// 练习 end
【完整代码】
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import gsap from 'gsap'
import GUI from 'lil-gui'
// console.log(GUI);/*** debugObject*/
const debugObject = {}
debugObject.color = '#ff0000' // 取色器色值修复 步骤2,在全局一开始就设置一个debug对象,修改内容都从这个对象里改// Canvas
const canvas = document.querySelector('canvas.webgl')// Scene
const scene = new THREE.Scene()/*** Object*/
// width: x 轴上的大小
// height: y 轴上的大小
// depth: z 轴上的大小
// widthSegments: x 轴上的细分数量
// heightSegments: 在 y 轴上的细分数量
// depthSegments: 在 z 轴上的细分数量
const geometry1 = new THREE.BoxGeometry(1, 1, 1)
const geometry2 = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: debugObject.color, wireframe: true })
const mesh1 = new THREE.Mesh(geometry1, material)
const mesh2 = new THREE.Mesh(geometry2, material)
scene.add(mesh1)
scene.add(mesh2)mesh1.position.x = 0
mesh2.position.x = 2/*** Sizes*/
const sizes = {width: window.innerWidth,height: window.innerHeight
}/*** Camera*/// 自定义控制
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 1, 1000)
camera.position.x = 1
camera.position.y = 0
camera.position.z = 3
camera.rotation.set(0, 0, 0); // 重置旋转,让相机看向 -Z 方向
scene.add(camera)/*** Controls*/
// OrbitControls会影响camera的lookAt
// const controls = new OrbitControls(camera, canvas)
// controls.enableDamping = true/*** Renderer*/
const renderer = new THREE.WebGLRenderer({canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.render(scene, camera)const tick = () => {// Update controls// controls.update()renderer.render(scene, camera)window.requestAnimationFrame(tick)
}
tick()/**
* Debug
*/
// gui的样式设置
const gui = new GUI({width: 312, // 宽度title: 'my debug UI', // 标题closeFolders: false // 是否关闭其中文件夹
})
gui.close() // 关闭整个面板
gui.hide() // 隐藏整个面板// 练习
gui.add(camera.position, 'x').min(-3).max(3).step(0.01).name('camera x')
gui.add(camera.position, 'y').min(-3).max(3).step(0.01).name('camera y')
gui.add(camera.position, 'z').min(3).max(8).step(0.01).name('camera z')
// 练习 end// 方式2:const gui = new dat.GUI() // 范围 —带最小值和最大值的数字
// 颜色 —各种格式的颜色
// 文本 —简单的文本
// 复选框 —布尔值(true 或 false)
// Select —用于从值列表中进行选择
// Button —用于触发功能// 1.范围
// 方式1,基础用法
// gui.add(mesh.position, 'y')
// 方式2,指定最小值、最大值和精度,可以在参数中设置
// gui.add(mesh.position, 'y', - 3, 3, 0.01)
// 方式3,可以直接在 `add(...)` 方法之后链式调用 `min(...)`、`max(...)` 和 `step(...)` 方法,name()可以更改标签名
gui.add(mesh1.position, 'y').min(-3).max(3).step(0.01).name('mesh1 y轴方向')
gui.add(mesh2.position, 'y').min(-3).max(3).step(0.01).name('mesh2 y轴方向')// 2.复选框
// 布尔值,lil-gui 会自动检测你想要调整的属性类型,并使用相应的界面
gui.add(mesh1, 'visible').name('mesh1 visible')
gui.add(mesh2, 'visible').name('mesh2 visible')// 2.1 wireframe
// 布尔值,wireframe 属性(位于 material 中)
gui.add(material, 'wireframe')// 3.颜色
// 注意,颜色不能使用 .add(),而是使用 .addColor(),因为颜色是一个对象
// gui.addColor(material, 'color')
// 取色器色值修复,首选需要得到当前选择的颜色数值,步骤1:
gui.addColor(debugObject, 'color') // 取色器色值修复 步骤3.1,将绑定从 material.color 改为 debugObject.color,通过onChange()监测debugObject.color的变化来.set() material.color.onChange((value) => {// console.log('color is changing!'); // console.log(material.color);// console.log(value);// console.log(value.getHexString()) // 取色器色值修复 步骤3.2,赋值material.color.set(debugObject.color)// console.log('修改前的颜色', value.getHexString());console.log('修改后的颜色', material.color.getHexString());})// 4.函数 / 按钮
// 通过创建的`debugObject`对象,在其中添加一个名为`spin`的属性,并将其与 GSAP 动画集成
debugObject.mesh1Spin = () => {gsap.to(mesh1.rotation, { duration: 1, y: mesh1.rotation.y + Math.PI * 2 })
}
debugObject.mesh2Spin = () => {gsap.to(mesh2.rotation, { duration: 1, x: mesh2.rotation.x + Math.PI * 2 })
}
gui.add(debugObject, 'mesh1Spin').name('mesh1 spin')
gui.add(debugObject, 'mesh2Spin').name('mesh2 spin')// 5.调整几何细分
// 先在创建的`debugObject`对象设置一个属性,subdivision
debugObject.subdivision = 1
// 使用 `onFinishChange`,当我们停止调整值时才会触发更新
gui.add(debugObject, 'subdivision').min(1).max(20).step(1).onFinishChange(() => {// console.log('subdivision finished changing', debugObject.subdivision);// 将新值赋给 `mesh` 的 `geometry` 属性// 先清掉旧的几何体,否则旧的几何体仍然存在于 GPU 内存中,这可能会导致内存泄漏mesh1.geometry.dispose()mesh1.geometry = new THREE.BoxGeometry(1, 1, 1,debugObject.subdivision, debugObject.subdivision, debugObject.subdivision)mesh2.geometry.dispose()mesh2.geometry = new THREE.BoxGeometry(1, 1, 1,debugObject.subdivision, debugObject.subdivision, debugObject.subdivision)})// 非属性的调整
const myObject = {myVariable: 1337
}
// gui.add(myObject, 'myVariable')// 6.文件夹
const itemTweaks = gui.addFolder('my items')
// 可设置默认关闭
// itemTweaks.close()
itemTweaks.add(myObject, 'myVariable')window.addEventListener('resize', () => {// 1. 更新 sizessizes.width = window.innerWidthsizes.height = window.innerHeight// 2.1 更新 camera aspect 纵横比camera.aspect = sizes.width / sizes.height// 2.2 更新 aspect 时要配合更新投影矩阵 updateProjectionMatrixcamera.updateProjectionMatrix()// 3. 更新 rendererrenderer.setSize(sizes.width, sizes.height)renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))})window.addEventListener('keydown', (e) => {if (e.key == 'h')gui.show(gui._hidden)
})// 练习
window.addEventListener('dblclick', () => {// 注释原来的双击全屏// if (!document.fullscreenElement) {// canvas.requestFullscreen();// } else {// document.exitFullscreen();// }gui.show(gui._hidden)
})
// 练习 end
项目创建参考
01-three.js vite基础示例_three.js示例-CSDN博客文章浏览阅读390次。three.js 基本示例代码_three.js示例https://blog.csdn.net/gaowxx/article/details/147954918?spm=1001.2014.3001.5501