WebGL+Three.js- 第 10 章 可视化调试工具
10.1 可视化调试工具简介
在深入学习three.js之前,我们先掌握好一些图形界面的调试工具,因为后续three.js的材质、光源等会有大量的属性。如果配合UI调试工具,将会非常方便我们对每个属性的掌握。
在这里介绍两个UI调试工具,一个是dat.gui,一个是lil.gui。两个工具的使用方式都非常相似,也十分简单。
dat.gui是一个可视化的属性面板UI工具库,它可以把你想调试的属性列在面板上,设置它的取值范围,然后就可以在面板中随意改变它的值,它会通过回调函数把值返回,我们再进行对应的操作。
lil.gui是three.js社区中非常流行的UI库,dat.gui是它的前身。它的使用方法跟dat.gui非常类似,也是一个语法简单、上手快的一个可视化的属性面板UI工具库。
以下是dat.GUI与lil.gui的结构图:
说明:由于dat.gui与lil.gui使用方式基本完全一致,在这里就一起讲解。
10.2 dat-gui与lil.gui
10.2.1 使用流程
1、引入库文件
(1)dat.gui
1.普通方式
<script src="dat.gui.js">
推荐一个可用的在线库:lf6-cdn-tos.bytecdntp.com/cdn/expire-…
2.npm
npm i dat.gui
import * as dat from 'dat.gui';
(2)lil.gui
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min';
2、实例化对象
(1)dat.gui
const gui = new dat.GUI();
(2)lil.gui
const gui = new GUI();
3、定义设置的属性对象
假设你有2个属性需要通过gui工具监听,那么可以设置一个对象,把需要监听的属性包裹在内:
const controls = {
color: 0xffffff,
numberInput: 0
}
4、属性对象绑定到gui
绑定属性主要是通过add和addColor两个方法,addColor顾名思义是用来监听颜色的,它会生成一个颜色面板,其余属性统一通过add方法。
add方法总共有4个参数,第一个参数是属性对象,第二个参数是需要监听的属性名,第三和第四个参数需要根据属性的类型进行设置,在往下会有详细讲述。前两个参数必选,而addColor方法只有前两个参数。
function initControl() {
const gui = new dat.GUI();
const controls = {
color: 0xffffff,
numberInput: 0.2
}
gui.addColor(controls, 'color')
gui.add(controls, 'numberInput')
}
initControl();
10.2.2 控件类型
10.2.2.1 Number类型
1、不设置限制条件(默认)
如果没有设置限制条件,则为一个input输入框。
function initControl() {
const gui = new dat.GUI();
const controls = {
numberInput: 0.2
}
gui.add(controls, 'numberInput')
}
initControl();
2、设置最小值最大值
可以设置最小值最大值范围,则显示为slider滑块组件(当然右侧还是有input输入)
function initControl() {
const gui = new dat.GUI();
const controls = {
numberSlider: 3
}
gui.add(controls, 'numberSlider', 0, 10)
}
initControl();
3、单独设置最小值最大值
还可以只单独限制最小值或者最大值,这个同样为一个input输入框。
function initControl() {
const gui = new dat.GUI();
const controls = {
numberMin: 3,
numberMax: 3
}
gui.add(controls, 'numberMin').min(0)
gui.add(controls, 'numberMax').max(10)
}
initControl();
4、设置步长
它可以通过step方法设置它的步长。
function initControl() {
const gui = new dat.GUI();
const controls = {
numberStep: 3
}
gui.add(controls, 'numberStep').step(0.2)
}
initControl();
5、下拉框
如果数字只是有限的几种固定值,那还可以使用下拉框的形式。
function initControl() {
const gui = new dat.GUI();
const controls = {
numberSelect: 1
}
gui.add(controls, 'numberSelect', {
selectOption1: 1,
selectOption2: 2,
selectOption3: 3,
})
}
initControl();
6、混合模式
它既可以设置最大最小值,同时也可以设置步长。
function initControl() {
const gui = new dat.GUI();
const controls = {
numberMix: 1
}
gui.add(controls, 'numberMix', 0, 10).step(0.2)
}
initControl();
10.2.2.2 String类型
1、不设置限制条件(默认)
如果没有设置限制条件,则为一个input输入框。
function initControl() {
const gui = new dat.GUI();
const controls = {
stringInput: 'test'
}
gui.add(controls, 'stringInput')
}
initControl();
2、下拉框
如果只是有限的几种固定值,那还可以使用下拉框的形式。
function initControl() {
const gui = new dat.GUI();
const controls = {
stringSelect: 'test1'
}
gui.add(controls, 'stringSelect', ['test1', 'test2', 'test3'])
}
initControl();
10.2.2.3 Boolean类型
使用复选框(Checkbox)的形式控制。
function initControl() {
const gui = new dat.GUI();
const controls = {
checkbox: true
}
gui.add(controls, 'checkbox')
}
initControl();
10.2.2.4 自定义函数
使用按钮(button)的形式控制,点击按钮会调用相应的方法。
function initControl() {
const gui = new dat.GUI();
const controls = {
checkbox: true
}
gui.add(controls, 'checkbox')
}
initControl();
10.2.2.5 颜色
dat.GUI一共提供了4种类型颜色输入控制:CSS、RGB、RGBA、Hue(注意:颜色使用addColor方法添加控件)
1、CSS
function initControl() {
const gui = new dat.GUI();
const controls = {
CssString: '#ffffff'
}
gui.add(controls, 'CssString')
}
initControl();
2、RGB
function initControl() {
const gui = new dat.GUI();
const controls = {
RGB: [0, 128, 255]
}
gui.add(controls, 'RGB')
}
initControl();
3、RGBA
function initControl() {
const gui = new dat.GUI();
const controls = {
RGBA: [0, 128, 255, 0.3]
}
gui.add(controls, 'RGBA')
}
initControl();
4、HSL
function initControl() {
const gui = new dat.GUI();
const controls = {
HSL: {h: 350, s: 0.9, v: 0.3}
}
gui.add(controls, 'HSL')
}
initControl();
10.2.3 回调函数
dat.gui的回调函数有两个方法:一个是onChange,一个是onFinishChange。onChange是在面板值变化的过程中实时返回值,onFinishChange顾名思义是面板值变化结束之后再返回值。
function initControl() {
const gui = new dat.GUI();
const controls = {
onChange: '#ffffff',
onFinishChange: 1
}
gui.addColor(controls, 'onChange').onChange(value => {
console.log('onChange值:' + value)
})
gui.add(controls, 'onFinishChange', 0, 10).onFinishChange(value => {
console.log('onFinishChange值:' + value)
})
}
initControl();
注意:监听颜色的时候,尽量避免使用十六进制的形式,虽然它也可以识别,但是它的返回值是一串数字,不利于我们使用。
function initControl() {
const gui = new dat.GUI();
const controls = {
onChangeHex: 0xffffff
}
gui.addColor(controls, 'onChangeHex').onChange(value => {
console.log('onChange值:' + value)
})
}
initControl();
10.2.4 创建文件夹
如果需要监听的属性太多,有可能会显示不全,而且也显得有点杂乱无章。这个时候可以使用gui提供的addFolder方法,字面意思是创建文件夹,实际上相当于建一个目录,把属性进行一个归类整理。
使用方法也很简单,首先用gui实例使用addFolder方法,只需要传入文件夹名参数即可。然后把需要归类的属性,通过文件夹名调用add方法添加进去。
function initControl() {
const gui = new dat.GUI();
const controls = {
numberInput: 0.2,
numberSlider: 3,
numberMin: 3,
numberMax: 3,
numberStep: 3,
numberSelect: 1,
numberMix: 1,
stringInput: 'test',
stringSelect: 'test1',
checkbox: true,
fn: function() {
console.log('自定义函数')
},
CssString: '#ffffff',
RGB: [0, 128, 255],
RGBA: [0, 128, 255, 0.3],
HSL: {h: 350, s: 0.9, v: 0.3},
onChange: '#ffffff',
onFinishChange: 1,
onChangeHex: 0xffffff,
}
const numberFolder = gui.addFolder('Number类型');
numberFolder.add(controls, 'numberInput')
......
const stringFolder = gui.addFolder('String类型');
stringFolder.add(controls, 'stringInput')
stringFolder.add(controls, 'stringSelect', ['test1', 'test2', 'test3'])
const checkboxFolder = gui.addFolder('Boolean类型');
checkboxFolder.add(controls, 'checkbox')
const fnFolder = gui.addFolder('自定义函数类型');
fnFolder.add(controls, 'fn')
const colorFolder = gui.addFolder('颜色类型');
colorFolder.addColor(controls, 'CssString')
......
const callbackFolder = gui.addFolder('回调函数');
callbackFolder.addColor(controls, 'onChange').onChange(value => {
console.log('onChange值:' + value)
})
......
}
initControl();
10.2.5 示例代码
1、dat.gui
2、lil.gui
10.3 结合three.js
学习完可视化调试工具之后,可以结合threejs场景进行控制,这里我们采用lil.gui作为例子,对以下几种类型进行结合演示。
1、函数类型:全屏、退出全屏
2、Number类型:控制立方体的x、y、z轴位置
3、Boolean类型:物体材质是否为线框模式
4、颜色类型:控制立方体颜色
10.3.1 全屏与退出全屏
data() {
return {
eventObj: {
// 全屏
fullScreen: function() {
document.body.requestFullscreen();
},
// 退出全屏
exitFullScreen: function() {
document.exitFullscreen();
}
}
}
},
method: {
// 初始化lil.gui调试工具
initControl() {
const gui = new GUI();
gui.add(this.eventObj, "fullScreen");
gui.add(this.eventObj, "exitFullScreen");
}
}
这里还可以修改一下它的别名,就是它默认会显示我们绑定的属性名字,假设我们想给它起一个别名,例如这里把fullScreen改成显示全屏,可以调用它的name方法:
method: {
// 初始化lil.gui调试工具
initControl() {
const gui = new GUI();
gui.add(this.eventObj, "fullScreen").name('全屏');
gui.add(this.eventObj, "exitFullScreen").name('退出全屏');
}
}
10.3.2 控制立方体位置
// 设置父元素旋转
parentCube.rotation.x = Math.PI / 4;
// 设置子元素旋转
this.cube.rotation.x = Math.PI / 4;
initControl() {
const gui = new GUI();
// 控制全屏、退出全屏
gui.add(this.eventObj, "fullScreen").name('全屏');
gui.add(this.eventObj, "exitFullScreen").name('退出全屏');
// 控制立方体的位置
gui.add(this.cube.position, 'x', -10, 10).step(1).name('立方体x轴位置')
gui.add(this.cube.position, 'y', -10, 10).step(1).name('立方体y轴位置')
gui.add(this.cube.position, 'z', -10, 10).step(1).name('立方体z轴位置')
}
注意:我们这里控制的是子立方体的位置,由于它的父立方体旋转了45°,因此它在y轴的方向也是旋转了45°(自己旋转的的角度不算),因此在控制它的y轴位置的时候,它是朝着y轴的45°的方向上下移动,而不是垂直。
10.3.3 控制立方体是否线框模式
initControl() {
const gui = new GUI();
......
// 控制父立方体是否线框模式
folder.add(this.parentCubeMaterial, 'wireframe').name('父元素线框模式')
}
10.3.4 控制立方体颜色
initControl() {
const gui = new GUI();
......
// 控制立方体颜色
folder.addColor(this.eventObj, 'cubeColor').name('立方体颜色').onChange(val => {
this.cube.material.color.set(val);
})
}
10.3.5 代码示例
上一篇: 我的大十中