每个学 Three.js 的都被安利了 dat.GUI 吧?
我也不例外!
今天就来了学习下 dat.GUI,并记录下来自己的学习成果。
一、什么是 dat.GUI?
dat.GUI 是一个轻量级的图形用户界面库(GUI 组件),使用这个库可以很容易地创建出能够改变代码变量的界面组件。
官网:https://github.com/dataarts/dat.gui
国内地址:GitCode - 开发者的代码家园
Three.js 每个官方的案例都有这个面板,用于参数调试。
二、引入方式
从官网下载 dat.gui-master.zip
,解压后,在 build
目录看到相关文件,用的就是它们。
1. script 标签方式
<script src="js/gui/dat.gui.min.js"></script>
<script>
const gui = new dat.GUI();
</script>
2. npm 安装
$ npm install --save dat.gui
// CommonJS:
const dat = require('dat.gui');
// ES6:
import * as dat from 'dat.gui';
三、创建 GUI 对象
const gui = new dat.GUI();
此时,我们在页面就有了一个 GUI 面板,不过此刻面板里什么都没有。
四、参数控制
主要用到的方法是:
-
gui.add()
-
gui.addColor()
它们都会返回一个参数控制对象。
1. 数值参数控制
gui.add(object, attr, min, max, step);
添加某个参数的控制块。其参数含义:
-
object:必须。要控制的对象。
-
attr:必须。控制对象的某个参数。
-
min,max:数值的最小值和最大值。它们必须同时存在。可选。
-
step:步进。即拖动下,数据改变多少。可选。
let ctrl = gui.add(obj, attr); // input 型,有一个输入框
let ctrl = gui.add(obj, attr, 1, 100); // 拖动滑块型。最小,最大值
let ctrl = gui.add(obj, attr, 1, 100, 1); // 拖动滑块型。最小,最大值,步进
或者
let ctrl = gui.add(obj, attr).min(1).max(100).step(1);
2. 颜色参数控制
gui.addColor( object, attr);
针对颜色的参数设置。
-
object:必须。要控制的对象。
-
attr:必须。控制对象的某个颜色型属性。
GUI提供了4种颜色值类型的控件(CSS、RGB、RGBA、Hue),四种类型均使用 gui.addColor()
添加。
var palette = {
color1: '#FF0000', // CSS string
color2: [ 0, 128, 255 ], // RGB array
color3: [ 0, 128, 255, 0.3 ], // RGB with alpha
color4: { h: 350, s: 0.9, v: 0.3 } // Hue, saturation, value
};
gui.addColor(palette, 'color1');
gui.addColor(palette, 'color2');
gui.addColor(palette, 'color3');
gui.addColor(palette, 'color4');
3.下拉框参数控制
下拉框控件既可以是数字类型,也可以是字符串类型,它们都是通过 gui.add()
方法进行配置。
gui.add(object, attr, array/object );
-
object:必须。要控制的对象。
-
attr:必须。控制对象的某个属性。
-
array: 字符串类型配置; object:数字类型配置。
gui.add( obj, "addr", ["北京","上海","天津"] );
gui.add( obj, "speed", {
"fast":1,
"normal":2,
"slow":3
} );
4. 单选框参数控制
首先,要保证对应的属性值为 true/false
布尔值。利用 gui.add()
方法,自然会形成单选框。
gui.add(object, attr)
-
object:必须。要控制的对象。
-
attr:必须。控制对象的某个属性。其值必须为布尔值。
gui.add(obj, "isCenter");
5. 添加/删除菜单文件夹
// 添加文件夹
let f = gui.addFolder( folderName )
// 给文件夹添加参数控制
f.addColor( obj, attr )
// 删除文件夹
gui.removeFolder(f)
例如:
let obj = {
"fontSize": 30,
"color" : "#ff0000",
"isCenter": true,
"addr":"北京",
"speed": 1
}
// 创建 GUI 面板。
const gui = new dat.GUI();
// 创建文件夹
let f = gui.addFolder("文字设置");
f.add(obj, "fontSize", 1, 100, 1);
f.addColor(obj, "color");
f.open();
let f2 = gui.addFolder("其他");
f2.add(obj, "addr", ["北京","上海","天津"]);
f2.add(obj, "isCenter");
6. 事件
修改参数后,能执行什么操作?
对于面板中的每一个控制项,可以设置 onChange 和 onFinishChange 监听事件。
-
onChange:控制项值改变时响应,比如拖动滑块过程中。
-
onFinishChange:控制项值改变完毕后相应。
注意:这两个事件本质是 gui 定义的对象方法,不能通过 addEventListener 添加。
f.add(obj, "fontSize", 1, 100, 1);
f.onChange(function(value){ // value 就是改变后的值
console.log("onChange:" + value)
});
f.onFinishChange(function(value){ // value 就是改变后的值
console.log("onFinishChange:" + value)
});
// 也可以直接链式操作。
f.add(obj, "fontSize", 1, 100, 1).onChange(function(value){ // value 就是改变后的值
console.log("onChange:" + value)
});
五、其他功能
1. 折叠,展开,隐藏,显示
gui.close(); // gui折叠
f.close(); // 文件夹折叠
gui.open(); // gui展开
f.open(); // 文件夹展开
gui.hide(); // 隐藏
f.hide();
gui.show(); // 显示
f.show();
2. 获取设置值
ctrl.getValue()
ctrl.setValue(newValue)
const one=gui.add(options, 'color5');
one.setValue('333')
console.log(one.getValue());//333
3. 刷新控制器
刷新此控制器的视图显示,以便与对象的当前值保持同步。
const options = {
color5: 'xxxx',
speed: 40,
types: 'two'
};
const gui = new dat.GUI();
let num = gui.add(options, 'speed', 10, 20, .1);
options.speed=12
// 比如直接修改对象,然后更新
gui.updateDisplay()
六、示例:用 GUI 控制某个标签的样式
要利用 GUI 控制某个标签的样式。
<h1 id="box">你好,这是 GUI 测试示例。</h1>
<script src="js/gui/dat.gui.js"></script>
<script>
let box = document.getElementById("box");
// 要修改参数的对象。
let obj = {
"fontSize": 30,
"color" : "#ff0000",
"isCenter": true
}
// 修改 h1 样式
box.style.cssText = `
font-size:30px;
color:#ff0000;
text-align:center;
`;
</script>
添加 GUI 代码:
// 创建 GUI 面板。利用 GUI 修改 h1 样式。
const gui = new dat.GUI();
// 创建文件夹
let f = gui.addFolder("文字设置");
let ctrl1 = f.add(obj, "fontSize", 1, 100, 1);
ctrl1.onChange(function(value){
box.style.fontSize = value +"px"
});
f.addColor(obj, "color").onFinishChange(function(value){
box.style.color = value ;
});
f.open(); // 默认第一个文件夹打开
// 创建文件夹2
let f2 = gui.addFolder("其他");
f2.add(obj, "addr", ["北京","上海","天津"]);
f2.add(obj, "isCenter").onFinishChange(function(value){
if(value){
box.style.textAlign = "center";
}else{
box.style.textAlign = "left";
}
});
七、示例:跟 Three.js 结合
构建一个立方体,利用 dat.gui 控制网格的大小和格子数量;控制立方体的颜色和缩放。
html:
<script type="importmap">
{
"imports":{
"three":"./js/three.module.min.js",
"three/addons/":"./js/jsm/",
"dat":"./js/gui/dat.gui.module.js"
}
}
</script>
<script type="module" src="./js/myjs6.js"></script>
JS:
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import * as dat from 'dat';
// 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color("#cccccc");
// 网格辅助器
let gridSize = 10;
let gridDivs = 10;
let gridHelper = new THREE.GridHelper(gridSize,gridDivs);
scene.add( gridHelper );
// 相机
let winH = window.innerHeight;
let winW = window.innerWidth;
const camera = new THREE.PerspectiveCamera(50, winW/winH, 1, 1000 );
camera.position.set(5,5,5);
camera.lookAt( scene.position );
scene.add(camera);
// 物体
const geometry = new THREE.BoxGeometry(1,1,1);
const material = new THREE.MeshBasicMaterial({
color:"#ff3300"
});
const box = new THREE.Mesh( geometry, material );
scene.add( box );
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(winW, winH);
renderer.render( scene, camera );
document.body.appendChild( renderer.domElement );
// 4. 渲染:不停的渲染
function animation() {
renderer.render(scene, camera)
requestAnimationFrame(animation)
}
animation()
添加 dat.gui 控制:
// gui 控制
const params = {
gridParam:{
size: 10,
divsitions:10
},
boxParam:{
color:"#ff3300"
}
}
const gui = new dat.GUI();
// 网格控制
const folderGrid = gui.addFolder("网格控制");
folderGrid.add( params.gridParam, "size",10,100 ).onChange(function(value){
scene.remove( gridHelper ); // 删除原有的网格
// 添加新的网格
gridSize = value;
gridHelper = new THREE.GridHelper(gridSize,gridDivs);
scene.add( gridHelper );
renderer.render( scene, camera );
});
folderGrid.add( params.gridParam, "divsitions",5,100 ).onChange(function(value){
scene.remove( gridHelper ); // 删除原有的网格
// 添加新的网格
gridDivs = value;
gridHelper = new THREE.GridHelper(gridSize,gridDivs);
scene.add( gridHelper );
renderer.render( scene, camera );
});
folderGrid.open();
// box控制
const folderBox = gui.addFolder("立方体控制");
folderBox.add( box.scale,"x",1,10);
folderBox.add( box.scale,"y",1,10);
folderBox.add( box.scale,"z",1,10);
folderBox.addColor( params.boxParam,"color").onChange(function(value){
material.color.set(value);
});
folderBox.open();