Three.js 快速入门教程【十六】调试神器 gui.js使用详解,可视化面板控制场景参数提高开发效率

请添加图片描述

系列文章目录

Three.js 快速入门教程【一】开启你的 3D Web 开发之旅
Three.js 快速入门教程【二】透视投影相机
Three.js 快速入门教程【三】渲染器
Three.js 快速入门教程【四】三维坐标系
Three.js 快速入门教程【五】动画渲染循环
Three.js 快速入门教程【六】相机控件 OrbitControls
Three.js 快速入门教程【七】常见几何体类型
Three.js 快速入门教程【八】常见材质类型
Three.js 快速入门教程【九】光源类型
Three.js 快速入门教程【十】常见的纹理类型
Three.js 快速入门教程【十一】天空盒的多种实现方式
Three.js 快速入门教程【十二】外部模型加载
Three.js 快速入门教程【十三】外部模型加载后常见的处理操作
Three.js 快速入门教程【十四】使用Stats.js监控渲染帧率和性能优化
Three.js 快速入门教程【十五】交互神器DragControls使用详解,实现对物体或模型拖拽
Three.js 快速入门教程【十六】调试神器 gui.js使用详解,可视化面板控制场景参数提高开发效率
Three.js 快速入门教程【十七】射线拾取模型——射线与射线投射器Raycaster介绍
Three.js 快速入门教程【十八】射线拾取模型——鼠标点击屏幕选中模型或物体
Three.js 快速入门教程【十九】CSS2D渲染器介绍,实现场景中物体或设备标注标签信息
Three.js 快速入门教程【二十】三维模型优化实战:使用gltf-pipeline与Draco对模型进行压缩,提高加载速度和流畅性
Three.js 快速入门教程【二十一】CSS3D渲染器(CSS3DRenderer、CSS3DObject 、CSS3DSprite)介绍,实现场景中物体标注标签信息
Three.js 快速入门教程【二十二】动画神器Tween.js使用指南



一、前言

      在使用 Three.js 进行 3D 场景开发时,我们常常需要动态调整场景中的各种参数,如物体的位置、旋转角度、材质属性、灯光强度等。手动修改代码再重新运行显然效率低下,这时 GUI.js 库就派上了用场。它能帮助我们快速创建用户界面,方便地控制场景中的参数进行调试。本文将详细介绍如何在 Three.js 项目中使用 GUI.js 库。


二、gui.js使用介绍

2.1 gui.js安装

(1)使用 npm 安装

npm install dat.gui

(2)使用 CDN

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>

2.2 创建基础GUI面板

首先我们先创建一个基础场景,包含一个正方体

import * as THREE from "three";
import * as dat from "dat.gui";
// 初始化场景、相机、渲染器
const scene = new THREE.Scene();
//相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(2, 3, 5);
scene.add(camera);
//坐标辅助线
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
//渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 加入灯光
let light = new THREE.DirectionalLight(0xffffff, 2, 3000, 1);
light.position.set(0, 20, 30);

// 添加立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

在这里插入图片描述

添加一行如下代码:

const gui = new dat.GUI();

添加完可以发现屏幕右上角多了一个黑色控制面板,此时还未向面板添加任何控件,所以内容为空。

在这里插入图片描述

继续添加代码:

// 添加滑动条控件
gui.add(cube.position, 'x', 0, 10).name('位置控制')

请添加图片描述

添加完,面板多出一个标题为位置控制的滑动控件,通过控制滑动控件可以实现对正方体的位置(x轴坐标)控制。

通过上面小示例,我们了解了gui.js最基本的使用方法,切身感受到gui.js作用,它通过可视化面板来控制场景中参数,方便开发调试。


三、 add方法深度解析

add方法法可以快速创建一个UI交互界面,并实现数据与界面的双向同步。作为 gui 最核心的方法,add承担了 90% 的控件创建工作,add方法不但能创建滑动控件,还支持下拉菜单、单选框等类型

3.1基础语法结构

// 标准语法
gui.add(object, propertyName, [min], [max], [step])
  .name('自定义名称')
  .onChange(callback)

参数说明:

参数类型必选说明
objectObject绑定的数据源对象(需为引用类型)
propertyObject对象属性名(支持嵌套属性:obj.a.b)
min/maxnumber/string/array范围限制(数值型 / 颜色 / 选项时生效)
stepnumber滑动步长(默认 1,小数需显式声明:0.01)

属性方法:
name:自定义控件标题,如果不设置默认以propertyName为标题
onChange:属性值改变触发回调


3.2核心控件创建

创建不同的控件主要受第三个参数和属性绑定的值类型有关

(1) 滑动条

滑动条绑定属性值类型是数字类型,一般4个入参,第三个参数是滑块可调节的最小值,第四个参数是滑块可调节的最大值。

const config = { width: 50 };
const gui = new dat.GUI();

// 添加滑块,范围 0-100,步长5
gui.add(config, 'width', 0, 100, 5);

运行效果:

在这里插入图片描述


(2)下拉菜单

第三个参数为数组即为下拉菜单类型

const themes = {
    theme: "dark",
  };

gui.add(themes, "theme", ["dark", "light", "system"])

运行效果:

在这里插入图片描述


(3)单选框

绑定的属性值类型为boolean,控件为单选框

 const state = {
    enableLight: true,
  };

  // 基础开关
  gui.add(state, "enableLight")
    .onChange((enabled) => (light.visible = enabled));//控制场景灯光是否禁用

运行效果:

在这里插入图片描述


四、 addColor方法(颜色选择器)

addColor方法用来添加一个颜色选择器控件,用法几乎跟add一样

const style = {
    primaryColor: "#44aa88",
  };

  gui.addColor(style, "primaryColor")
    .onChange((color) => material.color.set(color));//设置材质颜色

运行效果:

在这里插入图片描述
请添加图片描述


五、 addFolder方法(添加子菜单)

gui面板默认只有一个主菜单,控件从上往下排列,当控件很多界面混乱,这时候可以通过addFolder方法添加子菜单进行分类管理。

示例:

  // 创建GUI实例
 const gui = new dat.GUI();
//添加点光源菜单
const lightFolder = gui.addFolder("点光源控制");

上述代码新增一个点光源控制子菜单,返回子菜单对象lightFolder 同样具有gui对象的.add()、.onChange()、.addColor()等等属性方法

子菜单新增菜单项

  lightFolder.open();  //默认展开
  lightFolder.add(pointLight, "visible").name("开启"); //控制灯光是否启用
  lightFolder.add(pointLight, "intensity", 0, 30, 0.1).name("强度"); //控制灯光强度

在这里插入图片描述

继续新增模型控制菜单,并嵌套位置子菜单

   //添加模型控制子菜单
  const modelFolder = gui.addFolder("模型控制");
  modelFolder.open();
  //添加位置子菜单
  const positionFolder = modelFolder.addFolder("位置");
  positionFolder.open();
  positionFolder.add(model.position, "x", -10, 10, 0.1).name("x轴");
  positionFolder.add(model.position, "y", -10, 10, 0.1).name("y轴");
  positionFolder.add(model.position, "z", -10, 10, 0.1).name("z轴");

运行效果:
在这里插入图片描述

如上述示例所示,菜单对象可以重复调用addFolder方法嵌套无限层子菜单


四、完整示例

实现一个GUI面板对外部模型位置、旋转、缩放控制、对灯光强度、位置、颜色控制

import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import * as dat from "dat.gui";

// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x333333);
//坐标辅助线
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper);
// 创建相机
const camera = new THREE.PerspectiveCamera( // 透视相机
  75, // 视角 角度数
  window.innerWidth / window.innerHeight, // 宽高比 占据屏幕
  0.1, // 近平面(相机最近能看到物体)
  3000 // 远平面(相机最远能看到物体)
);
camera.position.set(2, 5, 5);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
  antialias: true, // 抗锯齿
});
// 设置渲染器宽高
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputEncoding = THREE.sRGBEncoding;
// renderer(渲染器)的dom元素添加到我们的HTML文档中
document.body.appendChild(renderer.domElement);

// 加入环境光
let ambientLight = new THREE.AmbientLight(0xffffff, 3);
scene.add(ambientLight);

//加入点光源
let pointLight = new THREE.PointLight(0xffffff, 15, 1000, 1);
pointLight.position.set(0, 3, 3);
scene.add(pointLight);
//点光源辅助
let pointLightHelper = new THREE.PointLightHelper(pointLight, 0.3);
scene.add(pointLightHelper);

//模型对象
let model;
// 加载GLTF模型
let loader = new GLTFLoader();
loader.load(
  "/wooden_table_02_4k.gltf/wooden_table_02_4k.gltf",
  (gltf) => {
    model = gltf.scene;
    scene.add(model);
    //添加GUI面板
    handleGui();
  },
  undefined,
  (error) => {
    console.error(error);
  }
);

// 控制器
const control = new OrbitControls(camera, renderer.domElement);
// 开启阻尼惯性,默认值为0.05
control.enableDamping = true;

// 渲染循环动画
function animate() {
  requestAnimationFrame(animate);
  control.update();
  renderer.render(scene, camera);
}

// 执行动画
animate();

// 添加GUI面板
function handleGui() {
  // 创建GUI实例
  const gui = new dat.GUI();

  /**
   * 光源设置
   */

  //添加灯光控制子菜单
  const lightFolder = gui.addFolder("点光源控制");
  //默认展开
  lightFolder.open();
  lightFolder.add(pointLight, "visible").name("开启"); //控制灯光是否启用
  lightFolder.add(pointLight, "intensity", 0, 30, 0.1).name("强度"); //控制灯光强度
  // 定义光源颜色参数对象
  const lightParams = {
    lightColor: "#ffffff",
  };
  //颜色设置
  lightFolder
    .addColor(lightParams, "lightColor")
    .name("颜色")
    .onChange((color) => {
      pointLight.color.set(color);
    });

  //添加光源位置子菜单
  const lightPositionFolder = lightFolder.addFolder("位置");
  lightPositionFolder.open();
  lightPositionFolder.add(pointLight.position, "x", -10, 10, 0.1).name("x轴");
  lightPositionFolder.add(pointLight.position, "y", -10, 10, 0.1).name("y轴");
  lightPositionFolder.add(pointLight.position, "z", -10, 10, 0.1).name("z轴");

  /**
   * 模型设置
   */

  //添加模型控制子菜单
  const modelFolder = gui.addFolder("模型控制");
  modelFolder.open();
  //添加位置子菜单
  const positionFolder = modelFolder.addFolder("位置");
  positionFolder.open();
  positionFolder.add(model.position, "x", -10, 10, 0.1).name("x轴");
  positionFolder.add(model.position, "y", -10, 10, 0.1).name("y轴");
  positionFolder.add(model.position, "z", -10, 10, 0.1).name("z轴");

  // 添加旋转子菜单
  const roationFolder = modelFolder.addFolder("旋转");
  roationFolder.open();
  //模型旋转控制
  roationFolder.add(model.rotation, "x", 0, Math.PI * 2).name("x轴");
  roationFolder.add(model.rotation, "y", 0, Math.PI * 2).name("y轴");
  roationFolder.add(model.rotation, "z", 0, Math.PI * 2).name("z轴");

  // 添加缩放子菜单
  const scaleFolder = modelFolder.addFolder("缩放");
  scaleFolder.open();
  //模型缩放控制
  scaleFolder.add(model.scale, "x", 0, 10, 0.1).name("x轴");
  scaleFolder.add(model.scale, "y", 0, 10, 0.1).name("y轴");
  scaleFolder.add(model.scale, "z", 0, 10, 0.1).name("z轴");
}

运行效果:

请添加图片描述

请添加图片描述


五、总结

       通过本文的介绍,你学会了如何在 Three.js 项目中使用 gui.js 库来创建用户界面,方便地控制场景中的参数。gui.js不仅可以提高开发效率,还能让用户在运行时灵活调整场景,增加了交互性和趣味性。希望你在今后的 Three.js 开发中能够熟练运用这一强大的工具。

更多three.js入门知识点请关注该系列教程后续的更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pixle0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值