three.js第一个3D案例

news2025/1/18 4:41:01

在正式学习Three.js之前,先做一些必要的准备工作,具体说就是下载threejs官方文件包,threejs官方文件包提供了很多有用的学习资源

threejs官方文件包所有版本:https://github.com/mrdoob/three.js/releases

threejs文件资源目录介绍

对于开发者而言,大家经常接触的是文档docs案例examples两个文件夹,平时查看文档,可以打开文档docs里面html文件,案例examples里面提供了海量threejs功能案例。

three.js-文件包
└───build——three.js相关库,可以引入你的.html文件中。
    │
└───docs——Three.js API文档文件
    │───index.html——打开该文件,本地离线方式预览threejs文档
└───examples——大量的3D案例,是你平时开发参考学习的最佳资源
    │───jsm——threejs各种功能扩展库
└───src——Three.js引擎的源码,有兴趣可以阅读。
    │
└───editor——Three.js的可视化编辑器,可以编辑3D场景
    │───index.html——打开应用程序  

工欲善其事,必先利其器

Web3D开发的代码编辑器和平时web前端开发一样,你可以根据自己的喜好选择,本课程选择的代码编辑器是  vscode

本地静态服务器

如果你想预览代码3D效果,咱们需要提供一个本地静态服务器的开发环境,正式的web项目开发,往往会用webpack或vite或其它方式配置一个开发环境。

如果只是学习threejs的话,可通过代码编辑器快速创建本地静态服务器,比如vsocde,安装live-server插件即可。或者使用phpstudy, 下载下来直接给下载的three.js包放在www目录里面,创建自己的HTML文件,引入three.js,就可以学习了

vscode配置live-server插件

  • 安装: vscode软件界面左侧,点击扩展,输入live-server关键词查询安装。
  • 使用:如果你想预览代码3D效果,打开对应.html文件,右键点击Open with Live Server即可。
预览3D案例和文档

打开课件案例,注意把Three.js视频教程源码文件作为根目录,使用vscode创建本地静态服务就可以预览。 

three.js-文件包
...
└───docs——Three.js API文档文件
    │───index.html——打开该文件,本地离线方式预览threejs文档
└───examples——大量的3D案例,是你平时开发参考学习的最佳资源
    │───.html——各种3D案例
...    

script标签方式引入three.js

通过script标签把three.js当做一个js库引入你的项目。three.js库可以在threejs官方文件包下面的build目录获取到。

<script src="./build/three.js"></script>

console.log(THREE.Scene); 

ES6 import方式引入

给script标签设置type="module",也可以在.html文件中使用import方式引入three.js。

<script type="module">
// 现在浏览器支持ES6语法,自然包括import方式引入js文件
import * as THREE from './build/three.module.js';
</script>

type="importmap"配置路径

通过配置<script type="importmap">,实现学习环境.html文件和vue或reaact脚手架开发环境一样的写法。这样你实际项目的开发环境复制课程源码,不用改变threejs引入代码。

下面配置的type="importmap"代码具体写法不用掌握记忆,复制粘贴后,能修改目录就行,

<!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">
    {
		"imports": {
			"three": "../../../three.js/build/three.module.js"
		}
	}
</script>

<!-- 配置type="importmap",.html文件也能和项目开发环境一样方式引入threejs -->
<script type="module">
    import * as THREE from 'three';
    // 浏览器控制台测试,是否引入成功
    console.log(THREE.Scene);
</script>

type="importmap"配置——扩展库引入

通过配置<script type="importmap">,让学习环境.html文件,也能和vue或react开发环境中一样方式方式引入threejs扩展库。

<script type="importmap">
    {
		"imports": {
			"three": "./three.js/build/three.module.js",
            "three/addons/": "./three.js/examples/jsm/"
		}
	}
</script>

<script type="module">
    // three/addons/路径之后对应的是three.js官方文件包`/examples/jsm/`中的js库
    // 扩展库OrbitControls.js
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    // 扩展库GLTFLoader.js
    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
    console.log(OrbitControls);
    console.log(GLTFLoader);
</script>

配置addons/等价于examples/jsm/

项目的开发环境引入threejs

比如你采用的是Vue + threejsReact + threejs技术栈,这很简单,threejs就是一个js库,直接通过npm命令行安装就行。

// 比如安装148版本
npm install three@0.148.0 --save

//执行import * as THREE from 'three';ES6语法引入three.js核心。

// 引入three.js
import * as THREE from 'three';

npm安装后,如何引入three.js其他扩展库

了three.js核心库以外,在threejs文件包中examples/jsm目录下,你还可以看到各种不同功能的扩展库。一般来说,你项目用到那个扩展库,就引入那个,用不到就不需要引入。

// 引入扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入扩展库GLTFLoader.js
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

前期准备工作准备好后,我们就可以开始创建自己的第一个3D场景案例了。

入门Three.js的第一步,就是认识场景Scene相机Camera渲染器Renderer三个基本概念

三维场景Scene 

你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。

// 创建3D场景对象Scene
const scene = new THREE.Scene();

物体形状:几何体Geometry

Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状。

//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(200, 200, 200); 

物体外观:材质Material

如果你想定义物体的外观效果,比如颜色,就需要通过材质Material相关的API实现。

threejs不同材质渲染效果不同,下面就以threejs最简单的网格基础材质MeshBasicMaterial为例实现一个蓝色材质效果。

//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({
    color: 0x00ff00,//0x00ff00设置材质颜色为蓝色
}); 

物体:网格模型Mesh

在threejs中可以通过网格模型Mesh表示一个虚拟的物体,比如一个电脑等。

// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh

模型位置.position

实际生活中,一个物体往往是有位置的,对于threejs而言也是一样的,你可以通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置。

const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);

在threejs中你创建了一个表示物体的虚拟对象Mesh,需要通过.add()方法,把网格模型mesh添加到三维场景scene中。

scene.add(mesh); 

透视投影相机PerspectiveCamera

Threejs如果想把三维场景Scene渲染到web网页上,还需要定义一个虚拟相机Camera,就像你生活中想获得一张照片,需要一台用来拍照的相机。

Threejs提供了正投影相机OrthographicCamera 和透视投影相机PerspectiveCamera 

透视投影相机PerspectiveCamera 本质上就是在模拟人眼观察这个世界的规律

// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();

相机位置.position 

相机对象Camera具有位置属性.position,通过位置属性.position可以设置相机的位置。

//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(200, 100, 400); 

相机观察目标.lookAt()

你用相机拍照你需要控制相机的拍照目标,具体说相机镜头对准哪个物体或说哪个坐标。对于threejs相机而言,就是设置.lookAt()方法的参数,指定一个3D坐标。

//相机观察目标指向Threejs 3D空间中某个位置
camera.lookAt(0, 0, 0); //坐标原点

camera.lookAt(0, 10, 0);  //y轴上位置10


camera.lookAt(mesh.position);//指向mesh对应的位置

 判断相机相对三维场景中长方体位置

你可以把三维场景中长方体mesh想象为一个房间,然后根据相机位置和长方体位置尺寸对比,判断两者相对位置。你可以发现设置相机坐标(200, 200, 200),位于长方体外面一处位置。

// 长方体尺寸100, 100, 100
const geometry = new THREE.BoxGeometry( 100, 100, 100 );
const mesh = new THREE.Mesh(geometry,material);
// 网格模型位置xyz坐标:0,10,0
mesh.position.set(0,10,0);
// 相机位置xyz坐标:200, 200, 200
camera.position.set(200, 200, 200); 

定义相机渲染输出的画布尺寸 

Canvas画布:课程中会把threejs虚拟相机渲染三维场景在浏览器网页上呈现的结果称为Canvas画布

// 定义相机输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度

透视投影相机PerspectiveCamera:视锥体 

透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。

// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = 800; //宽度
const height = 500; //高度
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
PerspectiveCamera( fov, aspect, near, far )

//参数	含义	                            默认值
fov	    相机视锥体竖直方向视野角度。	        50

aspect	相机视锥体水平方向和竖直方向长度比,一般设置为Canvas画布宽高比。 width / height	1

near	相机视锥体近裁截面相对相机距离	。        0.1

far	    相机视锥体远裁截面相对相机距离,far-near构成了视锥体高度方向。	2000

 WebGL渲染器WebGLRenderer

通过WebGL渲染器WebGLRenderer 可以实例化一个WebGL渲染器对象

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();

设置Canvas画布尺寸.setSize()

// 定义threejs输出画布的尺寸(单位:像素px)
const width = 1000; //宽度
const height = 500; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)

渲染器渲染方法.render()

渲染器WebGLRenderer执行渲染方法.render()就可以生成一个Canvas画布(照片),并把三维场景Scene呈现在canvas画布上面,你可以把.render()

renderer.render(scene, camera); //执行渲染操作

渲染器Canvas画布属性.domElement

渲染器WebGLRenderer通过属性.domElement可以获得渲染方法.render()生成的Canvas画布,.domElement本质上就是一个HTML元素:Canvas画布。

document.body.appendChild(renderer.domElement);

到这里我们就可以创建了一个自己的3D场景第一个案例了,Canvas画布插入到任意HTML元素中

<div id="webgl" style="margin-top: 200px;margin-left: 100px;"></div>

document.getElementById('webgl').appendChild(renderer.domElement);

 轨道控制器

在 ThreeJS 中使用轨道控制器后,你可以通过长按鼠标左键并拖动鼠标来控制摄像头所处的位置。

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

// 用法
const orbitControls = new OrbitControls(camera, renderer.domElement);


<div class="first" id="myFirst"></div>
  <script type="importmap">
    {
      "imports": {
        "three": "./js/three.module.js",
        "three/jsm/": "./js/jsm/"
      }
    }
  </script>
  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from './js/jsm/controls/OrbitControls.js'; // 引入相机控件
    // three内置了 gui工具 我们先进行一个导入 允许我们动态的对于一些参数进行设置方便我们预览效果
    import { GUI } from './js/jsm/libs/lil-gui.module.min.js';
    //3D场景对象Scene
    const scene = new THREE.Scene();
    //创建一个长方体几何体
    const geometry = new THREE.BoxGeometry(2,4,1);
    //创建一个材质对象Material MeshBasicMaterial  不受光照影响
    const material = new THREE.MeshBasicMaterial({
      color: 0xff0000, //0xff0000设置材质颜色为红色
      transparent: true,
      opacity: 0.5,
    });
    //网格模型对象Mesh
    const mesh = new THREE.Mesh(geometry, material);
    // 添加到场景中去
    scene.add(mesh);

    let myFirst = document.getElementById("myFirst");
    // 实例化一个透视投影相机对象 PerspectiveCamera
    const camera = new THREE.PerspectiveCamera(75, myFirst.offsetWidth / myFirst.offsetHeight, 0.1, 1000);
    camera.position.z = 15;
    camera.position.x = 5;
    camera.position.y = 2;
    //camera.lookAt(-100, 100, 10); //坐标原点

    // 创建渲染器 WebGLRenderer
    const renderer = new THREE.WebGLRenderer({
      //lpha: true, // 背景是否可以设置透明色
      antialias: true, // 表示是否开启反锯齿
    });
    // AxesHelper:辅助观察的坐标系
    const axesHelper = new THREE.AxesHelper(150)
    scene.add(axesHelper)

    // 网格辅助线  第一个值是长度   第二个值是分割的段数
    const gridHelper = new THREE.GridHelper(10,10);
    scene.add(gridHelper)

    // 输出画布的尺寸
    
    renderer.setSize(myFirst.offsetWidth, myFirst.offsetHeight); // 设置渲染大小
    // 渲染到元素中
    myFirst.appendChild(renderer.domElement);
    //  相机控制控制的就是相机的postion的位置而在界面当中出现不同的几何体的观察形态
    const controls = new OrbitControls(camera, renderer.domElement);
    // addEventListener
    controls.addEventListener('change', ()=>{
      renderer.render(scene, camera)
    })

    // 创建一个GUI实例
    const gui = new GUI();
    // cube的位置
    const originPositon = {
      x: 0,
      y: 0,
      z: 0
    };
    // camera的位置
    const cameraPosition = {
      x: 0,
      y: 0,
      z: 5
    };
    // 创建第一个 gui的参数分组   几何体位置
    const cubeParams = gui.addFolder('几何体位置');
    cubeParams.add(originPositon, 'x', 0, 100).onChange(val => {
      cube.position.x = val;
      renderer.render(scene, camera)
    });
    cubeParams.add(originPositon, 'y', 0, 100).onChange(val => {
      cube.position.y = val;
      renderer.render(scene, camera)
    });

    //  相机位置的分组
    const cameraParams = gui.addFolder('相机的位置')
    // add(对象,属性名,数值)  生成的是一个数字输入框的交互
    // add(对象,属性名,数值1,数值2) 生成的是一个有可选范围的数字选择框
    cameraParams.add(cameraPosition, 'x', -5, 50).onChange(val => {
      camera.position.x = val;
      renderer.render(scene, camera)
    })
    cameraParams.add(cameraPosition, 'y', -5, 50).onChange(val => {
      camera.position.y = val;
      renderer.render(scene, camera)
    })
    // add(对象,属性名,数组)  会自动生成一个下拉菜单的交互界面
    //   cameraParams.add(cameraPosition,'x' ,[1,3,6]).onChange(val=>{
    //     camera.position.x = val;
    //     renderer.render(scene, camera) 
    //  })
    // add( 对象,属性名, 对象 ) 也会生成一下下拉菜单的交互方式
    // cameraParams.add(cameraPosition,'x' ,{
    //     param1: 1,
    //     param2: 5
    // }).onChange(val=>{
    //     camera.position.x = val;
    //     renderer.render(scene, camera) 
    //  })
    const testObj = {
        color: 0xff6600,
        val1: 10
    }
    // addColor 在gui当中添加一个 颜色选择器的交互 
    gui.addColor(testObj, 'color').onChange(val => {
      console.log('颜色的值', val)
    })
    // add()的其他后续的方法
    // .name(直接展示为参数的指定名称 方便理解)
    // .step(步进的数量) 每一个变化的最小单位
    gui.add(testObj, 'val1', 0, 100).name('某个值的大小').step(1)
    renderer.render(scene, camera)
  </script>

案例实际效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1470289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go 利用上下文进行并发计算

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; 在Go编程中&#xff0c;上下文&#xff08;context&#xff09;是一个非常重要的概念&#xff0c;它包含了与请求相关的信息&…

【嵌入式移植】7、U-Boot源码分析4—链接脚本分析

U-Boot源码分析4—链接脚本分析 1 u-boot-spl.lds1.1 链接脚本的生成1.2 u-boot-spl.lds内容分析1.3 text - 程序代码段1.4 sram其它段定义1.4.1 .rodata只读数据段1.4.2 .data数据段1.4.3 .u_boot_list段 1.5 BSS段1.6 /DISCARD/ 从上一篇文章【嵌入式移植】6、U-Boot源码分析…

130 如何通过vs2017开发linux c++程序

使用VS2017开发linux下的应用程序&#xff08;C/C&#xff09;_vc_linux.exe vs2017-CSDN博客 参考上面这哥们的&#xff0c;写的很详细 前言 本文章记录如何使用VS2017进行linux应用程序的开发&#xff08;针对新手小白&#xff09;&#xff0c;VS2017能较为方便的通过SSH编辑…

电脑蓝牙在哪里打开?1分钟轻松打开蓝牙!

“我在操作电脑的时候想将电脑的蓝牙打开来连接音响和键盘&#xff0c;但是不知道电脑蓝牙应该如何打开&#xff0c;有什么比较简单的方法吗&#xff1f;” 随着无线技术的日益发展&#xff0c;蓝牙已成为连接各种设备的重要桥梁。无论是传输文件、音频还是与外部设备进行通信&…

YOLO学习中的琐碎知识点

目录 一、导入的库 二、名词介绍 &#xff08;1&#xff09;pytorch张量 &#xff08;2&#xff09;边界框&#xff08;bounding box&#xff09; 三、pycharm操作 &#xff08;1&#xff09;参数设置 四、文件认识 五、YOLO如何训练自己的模型 一、导入的库 import to…

笔记本Win 10系统查看电池健康状况

博主最近换了个笔记本电池&#xff0c;之前的电池容量明显变小了很多&#xff0c;而且出现了轻微鼓包的情况。所以用gpt问了一下怎么用系统的方法查看电池情况。 在Windows 10系统中&#xff0c;您可以通过以下步骤来查看笔记本电脑电池的健康状况&#xff1a; 打开命令提示符&…

神经网络系列---归一化

文章目录 归一化批量归一化预测阶段 测试阶段γ和β&#xff08;注意&#xff09;举例 层归一化前向传播反向传播 归一化 批量归一化 &#xff08;Batch Normalization&#xff09;在训练过程中的数学公式可以概括如下&#xff1a; 给定一个小批量数据 B { x 1 , x 2 , … …

线程普通任务执行流程

&#xff08;1&#xff09;先判断是否存在空闲线程&#xff0c;存在直接分配&#xff0c;不存在执行&#xff08;2&#xff09;&#xff1b; &#xff08;2&#xff09;判断工作线程数量小于核心数量&#xff0c;未超出创建核心线程执行线程任务&#xff0c;超出执行&#xff…

为什么会员模式是一种明智的扩张方式

会员模式看起来是一种有趣、令人兴奋且很酷的业务发展方式&#xff0c;但当您真正深入研究时&#xff0c;您可能会惊讶地发现它远不止于此。 会员资格为我们提供了一条道德扩展的途径。我们可以就地为客户提供服务。 这就是为什么会员模式可能成为您企业的下一步&#xff0c;…

LeetCode 热题 100 | 二叉树(一)

目录 1 基础知识 1.1 先序遍历 1.2 中序遍历 1.3 后序遍历 2 94. 二叉树的中序遍历 3 104. 二叉树的最大深度 4 226. 翻转二叉树 5 101. 对称二叉树 菜鸟做题&#xff0c;语言是 C 1 基础知识 二叉树常见的遍历方式有&#xff1a; 先序遍历中序遍历后序遍历…

LeetCode | 寻找两个正序数组的中位数 Python C语言

Problem: 4. 寻找两个正序数组的中位数 文章目录 思路解题方法Code结果结果一些思考 思路 先合并&#xff0c;后排序&#xff0c;最后找中间轴。 解题方法 由解题思路可知 Code 这是python3的代码。 class Solution:def findMedianSortedArrays(self, nums1: List[int], …

微服务知识02

1、九大高并发解决方案 2、系统架构图​​​​​​​ 3、分布式事务 本地事务、分布式事务 操作不同服务器的数据库&#xff08;垂直分库&#xff09; 4、分布式事务解决方案&#xff08;没有seata之前&#xff09; &#xff08;1&#xff09;XA协议&#xff08;强一致性&a…

STM32单片机基本原理与应用(八)

温度传感器实验 实验内容&#xff1a; 单片机通过代码模拟1-Wire总线并对DS18B20进行读写&#xff0c;并在TFTLCD屏幕上显示当前实时温度。 电路原理图&#xff1a; 1-Wire总线 1-Wire总线&#xff1a;即单总线协议&#xff0c;采用单根信号线&#xff0c;既传输时钟&#…

深度学习基础(一)神经网络基本原理

之前的章节我们初步介绍了机器学习相关基础知识&#xff0c;目录如下&#xff1a; 机器学习基础&#xff08;一&#xff09;理解机器学习的本质-CSDN博客 机器学习基础&#xff08;二&#xff09;监督与非监督学习-CSDN博客 机器学习基础&#xff08;四&#xff09;非监督学…

python jupyter notebook打开页面方便使用

如果没安装jupyter, 请安装&#xff1a; pip install jupyter notebook 运行jupyter notebook jupyter-notebook

【SpringBoot】Spring常用注解总结

目录 ⭐spring springmvc和springboot的区别 Autowired 和Resource的区别和联系 1. SpringBootApplication 2. Spring Bean 相关 2.1. Autowired 2.2. Component,Repository,Service, Controller 2.3. RestController 2.4. Scope 2.5. Configuration 3. 处理常见的 HT…

利用R语言进行聚类分析实战(数据+代码+可视化+详细分析)

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

红队攻防之powershell上线基础免杀(一)

不努力&#xff0c;你背井离乡干嘛&#xff1f;当卧底啊 环境为win10&#xff0c;在哥斯拉生成的webshell下&#xff0c;执行powershell命令。 测试杀毒软件为&#xff1a;火绒&#xff0c;腾讯电脑管家 哥斯拉生成php文件的webshell 如图 哥斯拉进行连接 把要执行命令的文件…

[树形DP] 树的最大独立集

题目 这个挺简单的&#xff0c;注意状态转移时&#xff0c;如果选这个点&#xff0c;那么它的子结点状态应该为不选&#xff0c;如果这个点的状态是不选&#xff0c;那么可以在它的子结点里选择&#xff1a;选/不选两个状态&#xff0c;所以最后结果是max挑选。 #include<b…

业务流程管理系统(BPMS):一文掌握,组织业务流程优化必备。

大家好&#xff0c;我是大美B端工场&#xff0c;本期继续分享商业智能信息系统的设计&#xff0c;欢迎大家关注&#xff0c;如有B端写系统界面的设计和前端需求&#xff0c;可以联络我们。 一、什么是BPMS系统 BPMS是Business Process Management System&#xff08;业务流程管…