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));
};
相关推荐
时光足迹1 小时前
Tiptap编辑器
前端·javascript·react.js
im_AMBER1 小时前
手撕hot100之矩阵!看完这篇就AC~
javascript·数据结构·线性代数·算法·leetcode·矩阵
时光足迹1 小时前
电子书阅读器之笔记高亮(跨段处理)
前端·javascript·react.js
Dabei1 小时前
Android 副屏(Virtual Display)创建与悬浮窗画中画显示实战
前端·架构
Hello-Mr.Wang2 小时前
【保姆级教程】MasterGo MCP + Cursor 一键实现 UI 设计稿还原
前端·javascript·vue.js·ai编程
Dabei2 小时前
Android 无障碍服务实现美团/微信自动化:客户端开发实践
前端·设计模式
华超磊2 小时前
关于手动实现滚动的尝试
前端
宁雨桥2 小时前
前端修行日记之JS 原型与 AI基础常识
前端·javascript·原型模式
程序员陆通2 小时前
月烧 400 刀到不到 20 刀:我是怎么把 OpenClaw 的 Token 账单砍掉 95% 的
java·前端·数据库