three.js 细一万倍教程 从入门到精通(一)

news2025/2/26 7:25:54

目录

一、three.js开发环境搭建

1.1、使用parcel搭建开发环境

1.2、使用three.js渲染第一个场景和物体

1.3、轨道控制器查看物体

二、three.js辅助设置

2.1、添加坐标轴辅助器

2.2、设置物体移动

2.3、物体的缩放与旋转

缩放

旋转

2.4、应用requestAnimationFrame

2.5、通过Clock跟踪时间处理动画

2.6、Gsap动画库基本使用与原理

2.7、Gsap控制动画属性与方法

2.8、根据尺寸变化实现自适应画面

阻尼效果

自适应画面

2.9、调用js接口控制画布全屏和退出全屏

2.10、应用图形用户界面更改变量


一、three.js开发环境搭建

1.1、使用parcel搭建开发环境

第一步:创建空项目

第二步:终端输入

npm init

直接一路回车。

第三步:安装parcel

npm install parcel-bundler

接着,通过修改你的package.json来添加这些任务脚本

"scripts": {
	"dev": "parcel src/index.html",
	"build": "parcel build src/index.html"
},

第四步:创建src/index.html

第五步:终端输入命令

npm install parcel-bundler -dev

第六步:创建静态文件,引入静态文件

第七步:编写style.css代码

* {
    margin: 0;
    padding: 0;
}

body {
    background-color: skyblue;
}

第八步:安装threejs依赖

npm install three --save

第九步:编写main.js代码,看threejs是否安装成功

import * as THREE from "three"

console.log(THREE);

第十步:启动项目

1.2、使用three.js渲染第一个场景和物体

import * as THREE from "three"

// 1、创建场景
const scene = new THREE.Scene()

// 2、创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

// 3、设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera)

// 添加物体
// 创建几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 材质
const cubeMaterial = new THREE.MeshBasicMaterial({color: 0xffff00});
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 将物体添加到场景中
scene.add(cube)

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

// 使用渲染器,通过相机将场景渲染进来
renderer.render(scene, camera);

1.3、轨道控制器查看物体

import * as THREE from "three"
// 导入轨道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'

// 1、创建场景
const scene = new THREE.Scene()

// 2、创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

// 3、设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera)

// 添加物体
// 创建几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
// 材质
const cubeMaterial = new THREE.MeshBasicMaterial({color: 0xffff00});
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 将物体添加到场景中
scene.add(cube)

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

// 使用渲染器,通过相机将场景渲染进来
// renderer.render(scene, camera);


// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);

function render() {
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

render();

可以拖动了。

二、three.js辅助设置

2.1、添加坐标轴辅助器

// 添加坐标轴辅助器 5代表轴的线段长度
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)

红色代表X轴,绿色代表Y轴,蓝色代表Z轴。

2.2、设置物体移动

// 修改物体的位置
// 参数分别为 x,y,z
cube.position.set(5, 2, 0)

当然你也可以使用直接点的形式:

cube.position.x = 5
cube.position.y = 2

小案例:模拟物体从左到右循环运动

function render() {
    cube.position.x += 0.01
    if (cube.position.x > 5) {
        cube.position.x = 0
    }
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

2.3、物体的缩放与旋转

缩放

// 缩放
// 参数 x轴是3倍,y轴是两倍
cube.scale.set(3, 2, 1)

旋转

//旋转
// 参数都为弧度,Math.PI / 4代表绕X轴旋转45度
cube.rotation.set(Math.PI / 4, 0, 0)

小案例:模拟物体从左到右循环运动,并按X轴旋转

function render() {
    cube.position.x += 0.01
    cube.rotation.x += 0.01
    if (cube.position.x > 5) {
        cube.position.x = 0
    }
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

2.4、应用requestAnimationFrame

首先,我们的render函数有个默认的参数time,代表每一帧的时间,如果你打印会发现每一帧的时间都不太匀速,比如我们上面这个案例,x轴长度为5,假如我打算1秒运动长度1,匀速就是5秒完成,但打印结果并不是匀速的。

// 匀速
function render(time) {
    let t = time / 1000 % 5;
    cube.position.x = t * 1
    if (cube.position.x > 5) {
        cube.position.x = 0
    }
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

2.5、通过Clock跟踪时间处理动画

// 设置时钟
const clock = new THREE.Clock();

function render() {
    // 获取时钟运行的总时长
    let time = clock.getElapsedTime();
    console.log("时钟运行总时长:", time);
    let deltaTime = clock.getDelta();
    console.log("两次获取时间的间隔时间:", deltaTime)

    let t = time % 5;
    cube.position.x = t * 1
    if (cube.position.x > 5) {
        cube.position.x = 0
    }
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

2.6、Gsap动画库基本使用与原理

npm install gsap

动画库的作用就解决了我们上面手动计算处理动画的问题。

// 设置动画
// x轴上移动到5的位置,所花费时间5秒
gsap.to(cube.position, {x: 5, duration: 5, ease: "power1.out"})
// 绕x轴上旋转到360度,所花费时间5秒
gsap.to(cube.rotation, {x: 2 * Math.PI, duration: 5})

function render() {
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

ease属性(速率):

        power1.out:起始阶段平滑地加速,然后以逐渐减速的方式结束。

        power1.in:起始阶段缓慢加速,然后以较快的速度向目标值靠近。

        power1.inOut:在动画开始和结束时,属性的变化速度较慢,然后在动画的中间阶段达到最快的变化速度。

2.7、Gsap控制动画属性与方法

// 设置动画
// x轴上移动到5的位置,所花费时间5秒
let animate1 = gsap.to(cube.position, {
    x: 5,
    duration: 5,
    ease: "power1.inOut",
    repeat: -1,  // 设置重复的次数,无限次循环-1
    yoyo: true, // 往返运动
    delay: 2, // 延迟2秒运动
    onStart: () => {
        console.log("动画开始")
    },
    onComplete: () => {
        console.log("动画完成")
    }
})
// 绕x轴上旋转到360度,所花费时间5秒
gsap.to(cube.rotation, {x: 2 * Math.PI, duration: 5})

// 点击动画,暂停或恢复
window.addEventListener("click", () => {
    if(animate1.isActive()) {
        animate1.pause(); // 暂停
    } else {
        animate1.resume(); // 恢复运动
    }
})

2.8、根据尺寸变化实现自适应画面

阻尼效果

// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用update()
controls.enableDamping = true;

function render() {
    controls.update();
    renderer.render(scene, camera);
    // 渲染下一帧的时候就会调用render函数
    requestAnimationFrame(render)
}

自适应画面

// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
    // 更新摄像头
    camera.aspect = window.innerWidth / window.innerHeight;
    // 更新摄像机的投影矩阵
    camera.updateProjectMatrix();
    // 在更新渲染器
    renderer.setSize(window.innerWidth, window.innerHeight)
    // 设置渲染器的像素比
    renderer.setPixelRatio(window.devicePixelRatio);
})

尽管你更改分辨率,这段代码都会保持画面原样。

2.9、调用js接口控制画布全屏和退出全屏

// 双击控制屏幕进入全屏,退出全屏
window.addEventListener("dblclick", () => {
    const fullScreenElement = document.fullscreenElement; // 页面是否处于全屏
    if (!fullScreenElement){
        renderer.domElement.requestFullscreen(); // 全屏
    } else {
        document.exitFullscreen(); // 退出全屏
    }
})

2.10、应用图形用户界面更改变量

很多时候我们调试3D图像很麻烦,普遍都是改完代码然后看页面效果,而dat.gui就大大简化了我们的操作问题。

npm install -save dat.gui
// 导入dat.gui
import * as dat from 'dat.gui'

const gui = new dat.GUI();
gui.add(cube.position, "x").min(0).max(5).name("移动X轴坐标").onChange((value) => {
    console.log("值被修改:", value)
}).onFinishChange((value) => {
    console.log("完全停下来触发:", value)
})

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

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

相关文章

windows11 MSYS2下载安装教程

MSYS2 可以理解为在windows平台上模拟linux编程环境的开源工具集 当前环境:windows11 1. 下载 官网地址可下载最新版本,需要科学上网 https://www.msys2.org/ 2. 安装 按照正常安装软件流程一路next就可以 打开 3. 配置环境 网上很多教程提到需…

回归预测模型:MATLAB岭回归和Lasso回归

1. 岭回归和Lasso回归的基本原理 1.1 岭回归: 岭回归(Ridge Regression) 是一种用于共线性数据分析的技术。共线性指的是自变量之间存在高度相关关系。岭回归通过在损失函数中添加一个L2正则项( λ ∑ j 1 n β j 2 \lambda \s…

【维生素C语言】附录:strlen 函数详解

写在前面:本篇将专门为 strlen 函数进行讲解,总结了模拟实现 strlen 函数的三种方法,并对其进行详细的解析。手写库函数是较为常见的面试题,希望通过本篇博客能够加深大家对 strlen 的理解。 0x00 strlen函数介绍 【百度百科】str…

【原创 附源码】Flutter安卓及iOS海外登录--Facebook登录最详细流程

最近接触了几个海外登录的平台,踩了很多坑,也总结了很多东西,决定记录下来给路过的兄弟坐个参考,也留着以后留着回顾。更新时间为2024年2月12日,后续集成方式可能会有变动,所以目前的集成流程仅供参考&…

计算机毕业设计基于的农村蔬菜销售系统SSM

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: vue mybatis Maven mysql5.7或8.0等等组成,B…

力扣题目训练(8)

2024年2月1日力扣题目训练 2024年2月1日力扣题目训练404. 左叶子之和405. 数字转换为十六进制数409. 最长回文串116. 填充每个节点的下一个右侧节点指针120. 三角形最小路径和60. 排列序列 2024年2月1日力扣题目训练 2024年2月1日第八天编程训练,今天主要是进行一些…

c入门第十篇——指针入门

一句话来说: 指针就是存储了内存地址值的变量。 在前面讨论传值和传址的时候,我们就已经开始使用了指针来传递地址。 在正式介绍指针之前,我们先来简单了解一下内存。内存可以简单的理解为一排连续的房子的街道,每个房子都有自己的地址&#…

中国电子学会2019年12月份青少年软件编程Scratch图形化等级考试试卷三级真题(选择题、判断题)

一、单选题(共 25 题,每题 2 分,共 50 分) 1.怎样修改图章的颜色?( ) A. 只需要一个数字来设置颜色 B. 设置 RGB 的值 C. 在画笔中设置颜色、饱和度、亮度 D. 在外观中设置或修改角色颜色特效 2.以下程序的执…

数据分析入门指南:用 Python 开启数据之旅

文章目录 前言发现宝藏为什么选择 Python 进行数据分析?准备工作数据分析基础1. 数据加载2. 数据探索3. 数据清洗4. 数据可视化 探索更多可能性好书推荐总结 前言 为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。…

接口测试06 -- pytest接口自动化封装Loggin实战

1. 接口关键字封装 1.1 基本概念 接口关键字封装是指:将接口测试过程中常用的操作、验证封装成可复用的关键字(或称为函数、方法),以提高测试代码的可维护性和可复用性。 1.2 常见的接口关键字封装方式 1. 发送请求:封装一个函数,接受参数如请求方法、URL、请求头、请求…

【开源】SpringBoot框架开发天沐瑜伽馆管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 瑜伽课程模块2.3 课程预约模块2.4 系统公告模块2.5 课程评价模块2.6 瑜伽器械模块 三、系统设计3.1 实体类设计3.1.1 瑜伽课程3.1.2 瑜伽课程预约3.1.3 系统公告3.1.4 瑜伽课程评价 3.2 数据库设计3.2.…

【java基础题型】录入3位数,求每一位是?

\t 制表符,用于整到8个格子 Scanner类,导入Scanner包(1),代码里导入Scanner类写录入,调用录入的对象的方法 通用求个位数,%10即可,余数不会小于除数 package java录入3位数;import java.util.Scanner; …

Stable Diffusion 模型下载:RealCartoon-Realistic - V13

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十

npm ERR! network This is a problem related to network connectivity.

问题详细描述 PS D:\ALearnBlog\shiyi-blog\blog-web> npm install -g vue/cli npm ERR! code ETIMEDOUT npm ERR! syscall connect npm ERR! errno ETIMEDOUT npm ERR! network request to https://registry.npmjs.org/vue%2fcli failed, reason: connect ETIMEDOUT 104.1…

1【算法】——最大子数组问题(maximum subarray)

一.问题描述 假如我们有一个数组,数组中的元素有正数和负数,如何在数组中找到一段连续的子数组,使得子数组各个元素之和最大。 二.问题分析 分治法求解: 初始状态: low0;highA.length-1;mid&am…

绞杀者模式

来自:https://martinfowler.com/bliki/StranglerFiqApplication.html 逐步用新的架构代理老的部分 绞杀着模式对于老久庞大,难以改造的遗留系统是比较适用的 总结: 老的不改,建新的新的搞完,杀老的

BUGKU-WEB 计算器

题目描述 计算正确即可得到flag,先看看场景: 解题思路 先输入正确答案,发现只能输入一位数那应该是设置了输入的最大长度是一所以需要我们把这个限制解除就行了呗 相关工具 F12大法 解题步骤 在场景界面按下F12,找到对应的标签右键进行…

【C语言】实现单链表

目录 (一)头文件 (二)功能实现 (1)打印单链表 (2)头插与头删 (3)尾插与尾删 (4) 删除指定位置节点 和 删除指定位置之后的节点 …

力扣(LeetCode)数据结构练习题

今天来分享两道力扣(LeetCode)的题目来巩固上篇时间复杂度和空间复杂度的知识,也就是在题目上加上了空间复杂度和时间复杂度的限制。 目录 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素&#xff0c…

双场板功率GaN HEMT电容模型以精确模拟开关行为

标题:Capacitance Modeling in Dual Field-Plate Power GaN HEMT for Accurate Switching Behavior(TED.16年) 摘要 本文提出了一种基于表面电位的紧凑模型,用于模拟具有栅极和源极场板(FP)结构的AlGaN/G…