ThreeJS之GUI控制器

上篇主要介绍了 three.js 的基础使用及配置,例如场景、相机、渲染器、轨道控制器、灯光等等;本篇主要介绍 GUI 控制器,方便调试模型属性,例如按钮事件、位置、颜色、线框模式等等

初始化模型

js 复制代码
let scene; // 场景
let camera; // 相机
let renderer; // 渲染器
let controls; // 轨道控制器
const width = 300;
const height = 300;
let glbScene; // 3d加载模型
let cube; // 立方体

// 1. 初始化场景
const initScene = () => {
  scene = new THREE.Scene();
  // 设置背景色
  scene.background = new THREE.Color(0xffffff);
};

// 2. 初始化相机
const initCamera = () => {
  camera = new THREE.PerspectiveCamera(
    75, // 视角
    width / height, // 宽高比
    0.1, // 近平面
    2000 // 远平面
  );
  camera.position.z = 2; // 设置相机在 z 轴上的位置
  camera.position.y = 0.2;
  camera.lookAt(0, 0, 0); // 看向原点
};

// 3. 创建渲染器
const initRenderer = (id) => {
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(width, height); // 设置渲染器尺寸
  // renderer.setClearColor(0xffffff, 0); // 设置背景颜色 默认黑色

  // 获取渲染元素
  const container = document.getElementById(id) as HTMLElement;
  container.appendChild(renderer.domElement);
};

// 4. 添加轨道控制器(调整相机位置,即视角位置)
const initControls = () => {
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
  controls.dampingFactor = 0.05; // 阻尼系数
  controls.rotateSpeed = 0.1; // 旋转速度
  // controls.autoRotate = true; // 自动旋转
  // controls.autoRotateSpeed = 1; // 自动旋转速度
};

// 5. 动画刷新
const animate = () => {
  requestAnimationFrame(animate);
  controls.update(); // 更新控制器状态
  renderer.render(scene, camera); // 重新渲染
};

// (1)添加3d元素(立方体)
const initBox = () => {
  // import buyImg from "../../../assets/img/buy-gift.png";
  // 环境贴图
  new THREE.TextureLoader().load(buyImg, (texture) => {
    // 创建立方体(width,height,depth)
    const box = new THREE.BoxGeometry(1, 1, 1);
    // 创建材质
    const material = new THREE.MeshBasicMaterial({
      color: 0x00ff00,
      map: texture,
      side: THREE.BackSide,
    });
    // 创建网格(将物体和材质链接起来)
    cube = new THREE.Mesh(box, material);
    cube.position.set(1, 1, 0);
    // 添加到场景
    scene.add(cube);
  });
};

// (2)加载3D模型
const initGlb = (url) => {
  // 创建GLTF实例
  const loader = new GLTFLoader();
  // 加载模型
  loader.load(url, (glb) => {
    // console.log("glb.scene", glb.scene);
    glbScene = glb.scene;
    glb.scene.position.y = -0.7;
    scene.add(glb.scene);
  });
};

// (3)添加灯光
const initLight = () => {
  // 添加环境光
  const ambientLight = new THREE.AmbientLight(0xffffff, 4); // 柔和的白光
  scene.add(ambientLight);
};

// (4)添加其他
const initOther = () => {
  // 添加网格地面
  const gridHelper = new THREE.GridHelper(10, 10);
  scene.add(gridHelper);

  // 添加坐标轴
  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);
};

initScene();
initCamera();
initRenderer(item.id);
initControls();
animate();

initBox();
initGlb(item.nftFileUrl);
initLight();
initOther();

添加灯光(initLight)和其他(initOther)前的效果:

添加灯光(initLight)和其他(initOther)后的效果:

添加 GUI 控制

js 复制代码
// 创建立方体
const initBox = () => {
  // 创建立方体(width,height,depth)
  const box = new THREE.BoxGeometry(1, 1, 1);
  // 创建材质
  const material = new THREE.MeshBasicMaterial({
    color: 0x00ff00,
    side: THREE.BackSide,
  });
  material.wireframe = true; // 设置为线框模式
  // 创建网格(将物体和材质链接起来)
  cube = new THREE.Mesh(box, material);
  cube.position.set(1, 1, 0);
  // 添加到场景
  scene.add(cube);
};

// 加载glb实例
const initGlb = (url) => {
  // 创建GLTF实例
  const loader = new GLTFLoader();
  // 加载模型
  loader.load(url, (glb) => {
    console.log("glb.scene", glb.scene);
    glbScene = glb.scene;
    glb.scene.position.y = -0.7;
    scene.add(glb.scene);

    // 添加GUI配置
    initGui();
  });
};

// 添加GUI配置
// import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
const initGui = () => {
  // 创建GUI
  const gui = new GUI();

  // 添加按钮(.name重命名为中文)
  const eventObj = {
    fullScreen: () => {
      // 全屏
      document.body.requestFullscreen();
    },
    exitScreen: () => {
      // 退出全屏
      document.exitFullscreen();
    },
  };
  gui.add(eventObj, "fullScreen").name("全屏");
  gui.add(eventObj, "exitScreen").name("退出全屏");

  // 控制模型位置
  console.log(glbScene);
  let folder = gui.addFolder("模型位置"); // 添加分组
  folder
    .add(glbScene.position, "x", -5, 5) // 参数和下面同等效果
    .onChange((val) => console.log("x", val)); // 变动时触发
  folder
    .add(glbScene.position, "y")
    .min(-5) // 最小值
    .max(5) // 最大值
    .step(1) // 部进
    .name("y轴") // 重命名
    .onFinishChange((val) => console.log("y", val)); // 变动结束时触发

  // 线框模式控制
  console.log("cube", cube);
  // 要有配置:material.wireframe = true,boolean值处理
  gui.add(cube.material, "wireframe").name("线框模式");

  // 颜色调整
  const colorParams = { cubeColor: "#ff0000" };
  gui
    .addColor(colorParams, "cubeColor")
    .name("立方体颜色")
    .onChange((val) => cube.material.color.set(val));
};
相关推荐
浏览器工程师25 分钟前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆27 分钟前
VSCode自动格式化三要素
前端
爱勇宝1 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen2 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518134 小时前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode4 小时前
Redis 在生产项目的使用
前端·后端
LiaCode4 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战4 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
风骏时光牛马4 小时前
# Ruby基于Rails框架实现多角色权限管理与数据分页查询完整实战代码案例
前端
weedsfly4 小时前
迭代器、生成器与异步迭代——让数据“按需流动”的艺术
前端·javascript