文章目录
- 简介
- 从 dat.GUI 到 lil-gui
- 例子
- 安装 lil-gui 并实例化
- 不同类型的调整
- 改变位置
- 针对非属性的调整
- 复选框
- 颜色
- 功能/按钮
- 调整几何形状
- 文件夹
- 调整 GUI
- 宽度
- 标题
- 关闭文件夹
- 隐藏
- 按键切换
- 结论
简介
每一个创意项目的一个基本方面是能够轻松调整。开发人员和参与项目的其他参与者(如设计师甚至客户)必须能够更改尽可能多的参数。
您必须考虑到这一点,以便他们找到完美的颜色、速度、数量等,获得最佳体验。您甚至可能会得到意想不到的很棒的结果。
首先,我们需要一个调试 UI。
虽然您可以使用 HTML / CSS / JS 创建自己的调试 UI,但已经有多个库:
- dat.GUI
- lil-gui
- control-panel
- ControlKit
- Uil
- Tweakpane
- Guify
- Oui
所有这些库都可以做我们想做的事,但我们将使用lil-gui,因为它很流行、维护良好、并且易于使用
从 dat.GUI 到 lil-gui
最初,Three.js
练习都是使用 dat.GUI
一段时间以来,这个库一直没有更新,NPM 在安装它时开始触发漏洞警告。这些漏洞已经修复,但替代方案已经开始出现,这就是 lil-gui
作为 dat.GUI
的替代品越来越受欢迎的原因。额外的好处是它甚至有更好的功能。
所有 Three.js
练习现在都使用 lil-gui
顺便说一下,GUI 代表图形用户界面。
例子
https://bruno-simon.com/#debug
安装 lil-gui 并实例化
npm i lil-gui
引入并使用
import GUI from 'lil-gui'
/**
* Debug
*/
const gui = new GUI()
不同类型的调整
- 范围— 针对具有最小值和最大值的数字
- 颜色— 适用于各种格式的颜色
- 文本— 用于简单文本
- 复选框— 用于布尔值(true或false)
- 选择— 从值列表中进行选择
- 按钮——触发功能
改变位置
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
gui.add(mesh.position, 'y')
或者写一个范围,这样 ui
就会变成一个滑杆
gui.add(mesh.position, 'y', - 3, 3, 0.01)
也可以使用链式调用
gui
.add(mesh.position, 'y')
.min(- 3)
.max(3)
.step(0.01)
针对非属性的调整
这里需要注意的一点是 lil-gui 只能修改属性。如果你想更新变量,则不能:
let myVariable = 1337
gui.add(myVariable, '???')
但是您可以使用一些技巧来实现这一点,例如创建一个对象,其目的是保存 lil-gui 在该对象上使用的属性:
const myObject = {
myVariable: 1337
}
gui.add(myObject, 'myVariable')
复选框
lil-gui 会自动检测你想要调整的属性类型,并使用相应的接口。Object3D visible
的属性就是一个很好的例子。它是一个布尔值,如果,false
则会隐藏对象:
gui.add(mesh, 'visible')
颜色
处理颜色有点麻烦。让我们尝试修改 color
的属性 material
。
需要通过回调函数里的 value 来设置值, GUI
上的 hex
并不是最终的值
你最终得到了错误的颜色:
这是因为 Three.js
应用了一些颜色管理来优化渲染。因此,调整中显示的颜色值与内部使用的值不同。
我们现在不讨论色彩管理, 有两种方法可以解决这个问题。
gui.addColor(material, 'color')
需要通过回调函数来覆盖掉 ui 上显示的值
debugObject.color = '#3a6ea6'
const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2)
const material = new THREE.MeshBasicMaterial({ color: debugObject.color, wireframe: false })
cubeTweaks
.addColor(debugObject, 'color')
.onChange(() =>
{
material.color.set(debugObject.color)
})
功能/按钮
有时,我们只想按需触发指令。现在,当我们点击调试 UI 中的某个位置时,我们希望让立方体执行一点旋转动画。
我们可以通过向包含函数的 tweak 发送一个属性来实现这一点。不幸的是,这意味着我们不能让一个函数像这样独立存在,然后将其发送给 lil-gui
const myFunction = () => {
console.log('do something')
}
gui.add(myFunction, '???')
但是我们可以为我们之前创建的对象添加一个spin属性debugObject,并将 GSAP 动画集成到其中:
debugObject.spin = () =>
{
gsap.to(mesh.rotation, { duration: 1, y: mesh.rotation.y + Math.PI * 2 })
}
最后,我们可以将调整添加到 debugObject.spin
debugObject.spin = () =>
{
// ...
}
gui.add(debugObject, 'spin')
调整几何形状
gui
.add(debugObject, 'subdivision')
.min(1)
.max(20)
.step(1)
.onChange(() =>
{
console.log('subdivision changed')
})
对于 CPU 来说,构建几何图形可能是一个相当漫长的过程。现在,我们正在监听更改事件,如果用户过多地拖放范围调整,则可能会多次触发该事件。
onChange
我们不会使用 ,而是使用onFinishChange
,它仅当我们停止调整值时才会触发:
gui
.add(debugObject, 'subdivision')
.min(1)
.max(20)
.step(1)
.onFinishChange(() =>
{
console.log('subdivision finished changing')
})
除此之外console.log(),我们还可以使用 构建一个新的几何体,并通过将其分配给其属性来debugObject.subdivision将其与 关联:meshgeometry
gui
.add(debugObject, 'subdivision')
.min(1)
.max(20)
.step(1)
.onFinishChange(() =>
{
mesh.geometry = new THREE.BoxGeometry(
1, 1, 1,
debugObject.subdivision, debugObject.subdivision, debugObject.subdivision
)
})
就是这样,但我们犯了一个小错误。旧几何图形仍位于 GPU 内存中的某个位置,这可能会导致内存泄漏。
dispose()为了解决这个问题,我们可以在创建新的几何图形之前在旧几何图形上调用该方法:
gui
.add(debugObject, 'subdivision')
.min(1)
.max(20)
.step(1)
.onFinishChange(() =>
{
mesh.geometry.dispose()
mesh.geometry = new THREE.BoxGeometry(
1, 1, 1,
debugObject.subdivision, debugObject.subdivision, debugObject.subdivision
)
})
文件夹
假设我们有很多调整,调试 UI 开始变得拥挤。我们可以使用此addFolder()方法将它们分成文件夹。
要创建文件夹,请调用addFolder()并发送您想要的名称作为参数。请确保在调整之前执行此操作并将其保存为cubeTweaks:
const cubeTweaks = gui.addFolder('Awesome cube')
然后,不要使用gui来创建调整,而是使用cubeTweaks变量:
const cubeTweaks = gui.addFolder('Awesome cube')
cubeTweaks
.add(mesh.position, 'y')
// ...
cubeTweaks
.add(mesh, 'visible')
cubeTweaks
.add(material, 'wireframe')
cubeTweaks
.addColor(material, 'color')
// ...
// ...
cubeTweaks
.add(debugObject, 'spin')
// ...
cubeTweaks
.add(debugObject, 'subdivision')
// ...
可以默认
const cubeTweaks = gui.addFolder('Awesome cube')
cubeTweaks.close()
调整 GUI
宽度
const gui = new GUI({
width: 300
})
标题
const gui = new GUI({
width: 300,
title: 'Nice debug UI'
})
关闭文件夹
const gui = new GUI({
width: 300,
title: 'Nice debug UI',
closeFolders: true
})
隐藏
const gui = new GUI({
width: 300,
title: 'Nice debug UI',
closeFolders: false,
})
// gui.close()
gui.hide()
按键切换
window.addEventListener('keydown', (event) =>
{
if(event.key == 'h')
gui.show(gui._hidden)
})
结论
随着你的 项目的进行,来添加各种各样的 gui
参数