Three.js学习之旅--相机适配与dat.gui库

canvas画布动态变化

js 复制代码
// canvas画布动态变化
// 简体页面窗口变化
// 画布变化 需要更新相机和渲染参数
window.onresize = function () {
    //更改画布大小 
    renderer.setSize(window.innerWidth,window.innerHeight);
    //摄像机视锥体长宽比
    camera.aspect = window.innerWidth / window.innerHeight;
    //更新摄像机投影矩阵。在任何参数被改变以后必须被调用。
    camera.updateProjectionMatrix();
}

阵列立方体

沿x、y、z轴分布排列,可以改变相机的fov参数观察,fov越大视野越大

js 复制代码
// 循环创建阵列物体
for (let i = 0; i < 10; i++) {
    for (let j = 0; j < 10; j++) {
        for(let k=0;k<10;k++){
            // 创建物体-网格模型
            const mesh = new THREE.Mesh(geometry, meterial);
            // 设置物体的位置
            mesh.position.set(i*10, j*10, k*10);
            // 将物体添加到场景中
            scene.add(mesh);
        }
    }
}

高光网格材质

js 复制代码
// 创建球形几何体
const geometry = new THREE.SphereGeometry( 30, 32, 16 );
// 高光网格材质(受光照影响、镜面反射)
const meterial = new THREE.MeshPhongMaterial({
    color: 0x0000FF,
    shininess:20, //亮度,默认20
    specular:0xFFFFFF, //反射光颜色
})
// 创建物体-网格模型
const mesh = new THREE.Mesh(geometry, meterial);

MeshPhongMaterial:镜面反射 类似与阳光照射到镜子
MeshLambertMaterial:漫反射 类似于阳光照射到白纸上,不会感到刺眼

添加dat.gui.js

dat.gui.js可以快速创建控制三维场景的UI交互界面,three.js已内置,无需下载

js 复制代码
// 添加dat.gui.js
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'

gui改变模型位置

.add(obj,'xx',value1,value2)添加改变的对象属性,value1、value2为可选范围

js 复制代码
// gui改变模型位置
gui.add(mesh.position,'x',0,100);
gui.add(mesh.position,'y',0,100);
gui.add(mesh.position,'z',0,100);

name方法为属性命名

js 复制代码
// 为属性命名
gui.add(mesh.position,'x',0,100).name('x轴');
gui.add(mesh.position,'y',0,100).name('y轴');
gui.add(mesh.position,'z',0,100).name('z轴');

step方法为模型添加改变步长

js 复制代码
// step方法为模型添加改变步长  上下箭头增减时 每次调整的大小
gui.add(rotate,'x',0,1).name('沿x轴旋转速度').step(0.01);
gui.add(rotate,'y',0,1).name('沿y轴旋转速度').step(0.01);

addColor添加颜色

js 复制代码
const colorObj = {
    color:0xffffff
}
gui.addColor(colorObj,'color').onChange(value=>{
    // console.log(value)
    mesh.material.color.set(value);
})

下拉

js 复制代码
// 下拉菜单 数组或对象
gui.add(mesh.position,'x',[0,50,100]).name('x轴下拉');
gui.add(mesh.position,'y',{
    左:0,
    中:50,
    右:100
}).name('y轴下拉');

单选

js 复制代码
// 是否旋转
const rotate = {
    bool:true
}
gui.add(rotate,'bool').name('是否旋转');

addFolder 添加分组

js 复制代码
const gui = new GUI();
// 创建文件夹
const positionFolder = gui.addFolder('位置');
//子文件夹添加控制属性
positionFolder.add(mesh.position,'x',0,100).name('x轴');
positionFolder.add(mesh.position,'y',0,100).name('y轴');
positionFolder.add(mesh.position,'z',0,100).name('z轴');

效果展示:

完整代码

js 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js学习之旅-gui</title>
    <script type="importmap">
        {
         "imports":{
             "three":"./node_modules/three/build/three.module.js",
             "three/addons/":"./node_modules/three/examples/jsm/"
         }
        }
     </script>
</head>

<body>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
    <script type="module">
        import * as THREE from 'three';
        // 引入轨道控制器
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
        // 添加dat.gui.js
        import { GUI } from 'three/addons/libs/lil-gui.module.min.js'

        // 创建场景
        const scene = new THREE.Scene();
        // 创建长方形几何体
        const geometry = new THREE.BoxGeometry(20, 20, 20); //长 宽 高
        // 创建物体材质-基础网格材质(不受光照影响)
        // const material = new THREE.MeshBasicMaterial({
        //     color: 0x0000FF
        // });
        //漫反射材质(受光照影响)
        const material = new THREE.MeshLambertMaterial({
            color: 0x0000FF
        });
        // 创建物体-网格模型
        const mesh = new THREE.Mesh(geometry, material);
        // 设置物体的位置
        mesh.position.set(0, 0, 0);
        // 将物体添加到场景中
        scene.add(mesh);


        // 定义canvas画布
        const width = window.innerWidth;
        const height = window.innerHeight;


        // 创建相机(透视投影相机)
        //PerspectiveCamera(fov, aspect, near, far)
        const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 1000); // 定义相机视距大小
        // 设置相机位置
        camera.position.set(200, 200, 200);
        // 设置相机观察目标点
        camera.lookAt(0, 0, 0);
        // 或者直接看物体
        camera.lookAt(mesh.position);


        // 添加辅助观察坐标系
        // 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴 -- R G B
        // AxesHelper( size : Number ) size -- (可选的) 表示代表轴的线段长度. 默认为 1.
        const axesHelper = new THREE.AxesHelper(100);
        scene.add(axesHelper);

        //创建光源
        // 环境光
        const light = new THREE.AmbientLight(0xffffff);
        scene.add(light);

        // 平行光
        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        // 设置光源位置
        directionalLight.position.set(80, 40, 60);
        // 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
        directionalLight.target = mesh;
        scene.add(directionalLight);

        // 创建渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染画布大小
        renderer.setSize(width, height);
        // 渲染场景、相机
        renderer.render(scene, camera);
        // 将渲染画布插入到body中
        document.body.appendChild(renderer.domElement); //renderer.domElement为渲染画布元素


        // 添加轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        // 监听控制器事件
        controls.addEventListener('change', () => {
            // 执行渲染操作
            renderer.render(scene, camera)
        })


        // 旋转物体
        const rotate = {
            x:0.01,
            y:0.01,
            bool:true
        }
        function render() {
            // 每次执行时render()函数时,重新渲染
            renderer.render(scene, camera);
            // 物体沿x轴旋转
            if(rotate.bool){
                mesh.rotateX(rotate.x);
                mesh.rotateY(rotate.y);
            }
            requestAnimationFrame(render); //下一帧执行函数render
        }
        render()


        // 创建gui对象
        const gui = new GUI();
        // 创建文件夹
        const positionFolder = gui.addFolder('位置');
        const rotateFolder = gui.addFolder('旋转');
        const colorFolder = gui.addFolder('颜色');
        
        // gui改变模型位置 为属性命名
        positionFolder.add(mesh.position,'x',0,100).name('x轴');
        positionFolder.add(mesh.position,'y',0,100).name('y轴');
        positionFolder.add(mesh.position,'z',0,100).name('z轴');

        // 下拉菜单 数组或对象
        positionFolder.add(mesh.position,'x',[0,50,100]).name('x轴下拉');
        positionFolder.add(mesh.position,'y',{
           左:0,
           中:50,
           右:100
        }).name('y轴下拉');



        // step方法为模型添加改变步长  上下箭头增减时 每次调整的大小
        rotateFolder.add(rotate,'x',0,1).name('沿x轴旋转速度').step(0.01);
        rotateFolder.add(rotate,'y',0,1).name('沿y轴旋转速度').step(0.01);

        // 单选
        rotateFolder.add(rotate,'bool').name('是否旋转');


        // addColor添加颜色
        const colorObj = {
            color:0xffffff
        }
        colorFolder.addColor(colorObj,'color').onChange(value=>{
            // console.log(value)
            mesh.material.color.set(value);
        })
    </script>
</body>

</html>
相关推荐
乘风gg30 分钟前
还在养虾吗?虾王已诞生:微信龙虾 ClawBot
前端·ai编程·claude
小小小小宇1 小时前
LLM 长期记忆构建
前端
lichenyang4531 小时前
从 Express 老项目到 NestJS + Docker:一次车辆管理系统的渐进式重构
前端
Momo__2 小时前
VueUse createReusableTemplate —— 单文件组件内的模板复用神器
前端·vue.js
程序员小富2 小时前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇2 小时前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇2 小时前
React中的forwardRef
前端·react.js·面试
槑有老呆2 小时前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
风骏时光牛马2 小时前
Verilog开发常见问题汇总解析
前端
子兮曰3 小时前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端