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>
相关推荐
vx_bisheyuange10 分钟前
基于SpringBoot的便利店信息管理系统
前端·javascript·vue.js·毕业设计
晚烛11 分钟前
智启工厂脉搏:基于 OpenHarmony + Flutter 的信创工业边缘智能平台构建实践
前端·javascript·flutter
Zsnoin能14 分钟前
都快2026了,还有人不会国际化和暗黑主题适配吗,一篇文章彻底解决
前端·javascript
两个西柚呀15 分钟前
es6和commonjs模块化规范的深入理解
前端·javascript·es6
www_stdio15 分钟前
爬楼梯?不,你在攀登算法的珠穆朗玛峰!
前端·javascript·面试
光影少年16 分钟前
RN vs Flutter vs Expo 选型
前端·flutter·react native
风止何安啊23 分钟前
🚀别再卷 Redux 了!Zustand 才是 React 状态管理的躺平神器
前端·react.js·面试
鹿角片ljp28 分钟前
Spring Boot Web入门:从零开始构建web程序
前端·spring boot·后端
向下的大树34 分钟前
Vue 2迁移Vue 3实战:从痛点到突破
前端·javascript·vue.js
我很苦涩的35 分钟前
原生小程序使用echarts
前端·小程序·echarts