ThreeJS 入门教程(一) 是选择桌面的固守还是云原生?
myzbx 2025-05-09 20:34 3 浏览
导读:最近我购置了一台新的电脑,硬盘空间只有1T。我很担心这个电脑还能用多久。性能限制或者空间的限制,都使得在未来3-5年内,这个电脑会被淘汰。
但是,基于云APP的使用,老的电脑是足够了,而且,我们也不会被window或者linux的选择而费尽心思。
性能,在本地的限制将不再成为瓶颈。
第一章 ThreeJS简介
第一节:ThreeJS本地测试安装
作为学习来说,第一步是安装ThreeJS。
仅仅是学习测试,只需要做到以下两步即可。
1、到官网下载Threejs的包。
2、vscode,安装live server 。
这些就够了
当然,还需要浏览器。
很多教程都说要nodejs。其实不需要的。
下载的threejs的文件的结构如下:
源代码在src目录。创建好的在build目录。
其他的目录都是一些工具。可以在后期的使用中慢慢熟悉。
第二节: 开发结构
- 没有最好的结构,只有最适合的
如果说什么结构最好,这个没法说的。
这里先推荐一个初学者的结构。
就是在一个目录中有一个index.html文件。
然后就是three目录里面放源码。
需要多少,就向这个three目录放多少。
2、最开始的three目录
src主要引用three.js
jsm引用orbitcontrols 组件
第三节: 基本代码结构
我们先列出一个最简单的完整的代码结构
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>ThreeJS学习笔记</title>
</head>
<body>
<div id="container"></div>
<script type="importmap">
{
"imports": {
"three": "./three/src/Three.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import {OrbitControls} from "./three/jsm/controls/OrbitControls.js";
console.log(THREE.REVISION);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
const container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
//document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
let controls = new OrbitControls( camera, renderer.domElement );
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
animate();
</script>
</body>
</html>
代码分析:
1、头部:属于标准头部信息。
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>ThreeJS学习笔记</title>
</head>
2、定义嵌入的块名称
<div id="container"></div>
定义一个div块,名称用id来标识。在后面的render放置的位置时会指明。
3、导入模块文件
<script type="importmap">
{
"imports": {
"three": "./three/src/Three.js",
"controls":"./three/jsm/controls/OrbitControls.js"
}
}
</script>
单独定义一个script块,类型是importmap,用于导入一个模块,并重命名。
4、主程序代码
<script type="module">
import * as THREE from 'three';
import {OrbitControls} from "controls";
console.log(THREE.REVISION);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
const container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
//document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
let controls = new OrbitControls( camera, renderer.domElement );
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
animate();
</script>
(1)首先将three的名称重命名为THREE
(2)引入OrbitControls 组件,
注意:这里必须要加上{},否则,会出现错误信息,The requested module 'controls' does not provide an export named 'default'。
(3)接下来就是整个代码的编写。
整个过程显示之后,是如下的一个界面效果
基本的代码结构就是如此了。
以后的讨论中,我们将仅仅在主程序范围内,去讨论代码了。
第四节:ThreeJS组成部分
主程序部分
/*主要有6部分组成
1、场景Scene,是所有元素放置的空间
2、摄像头 Camera
3、几何网格Mesh
4、一系列的动作
5、渲染
6、主循环
ThreeJS就是一个剧本语言,舞台是Scene,场景里,布置了各种灯光,还有Mesh演员。通过各种动作包括声音,图像等,形成了一个故事,然后用摄像头把这些故事拍摄下来。
第二章:ThreeJS组件
第一节 场景Scene
const scene = new THREE.Scene();
ThreeJS的场景,是Scene类的一个实例。
我们的几何和灯光,必须要加载到scene里,才能被摄像头拍摄到,才能被渲染。那么,一系列的动作,才能被我们可见。
否则,我们就是摄像头里的隐形人。
常用的设置参数有如下两个:
scene.background = new THREE.Color( 0x88ccee ); //背景色
scene.fog = new THREE.Fog( 0x88ccee, 0, 50 ); //雾
一个设置了背景色。一个设置了雾的属性。
注意,ThreeJs中的颜色,是用Color类来定义的。
第二节 摄像头Camera
摄像机(Camera)
摄像机的抽象基类。在构建新摄像机时,应始终继承此类。
构造函数
Camera()
创建一个新的Camera(摄像机)。注意:这个类并不是被直接调用的;有你所想要的或许是一个 两种摄像机够摄影师使用:
- PerspectiveCamera(透视摄像机)
- 或者 OrthographicCamera(正交摄像机)。
常用的是透视摄像机,就是我们眼睛看到的效果。
PerspectiveCamera相机有四个参数。
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000 );
如下图:
第一个属性75设置的是视角(field of view)。
第二个属性设置的是相机拍摄面的长宽比(aspect ratio)。我们几乎总是会使用元素的宽除以高,否则会出现挤压变形。
接下来的2个属性是近裁剪面(near clipping plane) 和 远裁剪面(far clipping plane)。这几个参数所限定的绿色3D空间被称之为视椎体(View Frustum),用来裁剪视图,在该视锥体以外的物体将不会被渲染。我们暂时可以先不管,但你需要了解这个空间和渲染性能有关。
第三节 渲染Renderer
接下来是渲染器,所有魔法效果都在这里产生。除了我们这里使用的WebGLRenderer,three.js还支持一些其它渲染器,基本上只是用来回退处理那些不支持WebGL的旧式用户浏览器。
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
const container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
除了创建renderer实例,我们还需要设置渲染空间的尺寸,一般就使用目标屏幕的宽高(window.innerWidth和window.innerHeight),也可以给定一个小尺寸。
如果你想保持渲染空间的尺寸,但使用一个较低的分辨率,你可以在调用setSize的时候设置参数updateStyle为false,比如 setSize(window.innerWidth/2, window.innerHeight/2, false) 将使用1/2分辨率来绘制你的应用程序,假定<canvas>为100%的宽高。
最后,我们把 renderer 元素添加到HTML文档中。这里是一个 <canvas> 元素,渲染器用来显示场景。
上面的都是准备工作,电影布景都好了,演员还没进场。接下来我们添加“演员”(3D立方体)。
第四节 几何与网格
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
一个Mesh,包含两个参数,一个参数给定几何,一个参数给定材料。
从基本的属性可以看出,颜色等都在材料类中定义,几何类定义物体的几何属性。
ThreeJS提供了很多几何的设定。
也有很多素材
这些需要在后期的学习中不断的去学习和熟练。
第五节 控制组件
let controls = new OrbitControls( camera, renderer.domElement );
ThreeJS中的控制组件主要是控制摄像头和渲染的一些行为。
OrbitControls是可以让鼠标在视窗内旋转移动物体的视角。仅仅是视角,并不是实际的位置。也就是说,只是控制着摄像头。
控制类,ThreeJS提供了以下控制类型
这些文件在js和jsm目录下。
第六节 主循环
每一个页面都是静态的,只有加上跟踪时间的循环,才能让这个世界动起来。
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
animate();
我们需要定义一个函数,这个函数是自嵌套的。
requestAnimationFrame()函数,就是告诉每一帧,按时去检查。
controls.update()也是具有时间的更新。
所以,主循环,就是在这个场景中,设置时间。和跟随时间的行为。
第三章 故事的叙述
第一节 时间
Scene给了我们空间,材料给了我们一层蒙皮,模拟这个世界还需要什么?
当然还需要时间。
下面我们就简单看看时间是怎么获取的。
在ThreeJS中有一个时钟,Clock。这个时钟包含getDelta()函数。
如下代码就是一个测试代码:
var t=0;
var dt =0;
function time_count()
{
dt=dt+time.getDelta();
}
// 控制和主循环
let controls = new OrbitControls( camera, renderer.domElement );
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
time_count();
if (dt >1)
{
t=t+dt;
console.log(t);
dt=0;}
}
animate();
运行结果:
这就完成了时间的迭代,那么怎么才能使用这个时间呢?
大家可以思考一下。
就动画的所有的基础,就此已经准备完毕,剩下的,就是我们的故事本身了。
这里特别使用类js的类来表达这个代码:
// 时间测试
class Time{
constructor(){
this.clock = new THREE.Clock()
this.t = 0;
this.dt = 0;
}
update(){
this.dt=this.dt+this.clock.getDelta();
this.t=this.t+this.clock.getDelta();
}
flash(){
this.t=this.t+this.dt;
this.dt = 0;}
}
在主循环中,这样调用
let mytime = new Time();
// 控制和主循环
let controls = new OrbitControls( camera, renderer.domElement );
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
mytime.update();
if (mytime.dt >1)
{
mytime.flash();
console.log(mytime.t);
}
}
animate();
第二节 颜色
当色彩来到这个世界,我们的世界才开始变得精彩。
//empty constructor - will default white
const color1 = new THREE.Color();
//Hexadecimal color (recommended)
const color2 = new THREE.Color( 0xff0000 );
//RGB string
const color3 = new THREE.Color("rgb(255, 0, 0)");
const color4 = new THREE.Color("rgb(100%, 0%, 0%)");
//X11 color name - all 140 color names are supported.
//Note the lack of CamelCase in the name
const color5 = new THREE.Color( 'skyblue' );
//HSL string
const color6 = new THREE.Color("hsl(0, 100%, 50%)");
//Separate RGB values between 0 and 1
const color7 = new THREE.Color( 1, 0, 0 );
第三节 动画
来先拿我们之前的那个立方体的颜色来试试吧,我们只需要修改他的材料的属性就可以了。
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
mytime.update();
if (mytime.dt >0.1)
{
mytime.flash();
console.log(mytime.t);
var ccc = Math.abs(Math.sin(mytime.t));
material.color = new THREE.Color(ccc,1-ccc,0);
}
}
animate();
这里我们使用了JavaScript的数学库的sin函数。
以正弦函数的值变化。
除了颜色,我们还可以变化位置
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
mytime.update();
if (mytime.dt > 1/24)
{
mytime.flash();
console.log(mytime.t);
var ccc = Math.abs(Math.sin(mytime.t));
material.color = new THREE.Color(ccc,1-ccc,0);
cube.position.y = 3*Math.sin(mytime.t);
}
}
animate();
第四节 Gui
在实际的界面中,我们还需要做一些交互。ThreeJS提供了简单设置界面的类。
首先我们需要将一个文件包含到js代码中
import { GUI } from './three/jsm/libs/lil-gui.module.min.js';
下面的事情就看起来很简单了
// gui设置
let params = {
colorMap: 'red',
};
function updateColors() {
scene.background = new THREE.Color(params.colorMap); //背景色
}
const gui = new GUI();
gui.add(params, 'colorMap', ['red', 'yellow', 'blue', 'gray']).onChange(function () {
updateColors();
});
先定义个一个变量,params,这是一个json的格式字典。
我们窗一键GUI之后,只需要使用add函数,添加到这个GUI里,就可以了。
并且对它的响应设置一个函数。
执行之后的效果是:
第五节 使用精灵Sprite 生成标签
我们需要用一系列的牌子来显示内容。
如上图中的“车间生产实况”等等,这些,不会随着模型的转动而转动。使用精灵类来完成这些效果会是比较好的选择。
精灵 Sprite,是不会随着我们的3D旋转而改变的效果。
下面的代码是生成一些提示牌的演示代码
//生成精灵
function showSign(wid, hgt, textword, ww, wh, cvsPosition) {
//用canvas生成图片
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = wid //100
canvas.height = hgt //50
//制作矩形
ctx.fillStyle = "rgba(140, 141, 142,0.8)";
ctx.fillRect(0, 0, 100, 50)
//设置文字
ctx.fillStyle = "#fff";
ctx.font = 'normal 20pt "楷体"'
//文字换行
ctx.fillText(textword, ww, wh)
//生成图片
let url = canvas.toDataURL('image/png');
var spriteMaterial = new THREE.SpriteMaterial({
map: new THREE.TextureLoader().load(url), //设置精灵纹理贴图
transparent: true, //开启透明(纹理图片png有透明信息)
});
// 创建精灵模型对象,不需要几何体geometry参数
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(100, 30, 0); //精灵图大小
sprite.translateY(50);
sprite.position.set(...cvsPosition)
scene.add(sprite);
}
showSign(100, 50, '正方体', 15, 35, [0, 0, 0]);
显示效果如下:
结束
当前,以云和3D两个属性的方式展现的产品已经逐步成为主流。最近在数字化领域,越来越多的产品,都是基于云原生的形式来展现。3D,包含的信息和展现形式,将会融入更多维的数据和信息。
于是,我不得不去逐步学习,尽量在云端进行工作。
最近,我开始使用了石墨文档,使用亿图的思维导图,wps的云空间也在使用。大势之中,我们还是得逐步的接受这些新的事物吧。
最后,祝大家早日在云中安家。
相关推荐
- MORROR ART:毫无音质可言,真的只是好看而已...
-
今天早上我在微博上发了一条短视频,内容是某款网红音箱正在放声歌唱——这玩意就是此前曾经在网上挺火的所谓“悬浮歌词音箱”。这款产品是我同事收到的礼品,但她嫌在家里放着没用,所以拿到公司里做我们的拍摄道具...
- 「JS优化篇」你的 if - else 代码肯定没我写的好
-
作者:小生方勤转发链接:https://mp.weixin.qq.com/s/JzOQ_OwAYoP5Ic1VBtCZNA前言最近部门在对以往的代码做一些优化,我在代码中看到一连串的if(){}el...
- 细聊微内核架构在前端的应用「干货」
-
作者:semlinker转发链接:https://mp.weixin.qq.com/s/ywc98dS4TVB4t3L2tIyk8g一、微内核架构简介1.1微内核的概念微内核架构(Microke...
- ThreeJS 入门教程(一) 是选择桌面的固守还是云原生?
-
导读:最近我购置了一台新的电脑,硬盘空间只有1T。我很担心这个电脑还能用多久。性能限制或者空间的限制,都使得在未来3-5年内,这个电脑会被淘汰。但是,基于云APP的使用,老的电脑是足够了,而且,我们也...
- 推荐三款正则可视化工具「JS篇」(正则在线调试)
-
作者:代码先森转发链接:https://mp.weixin.qq.com/s/rw29yKBwti5sIsx2GKG9pw前言最近老王对可视化非常着迷。例如,算法可视化、正则可视化、Vue数据劫持可...
- Javascript 多线程编程的前世今生
-
作者:jolamjiang腾讯技术工程转发链接:https://mp.weixin.qq.com/s/87C9GAFb0Y_i5iPbIL5Hzg为什么要多线程编程大家看到文章的标题《Javasc...
- Pug 3.0.0正式发布,不再支持 Node.js 6/8
-
作者:李俊辰前端之巅转发链接:https://mp.weixin.qq.com/s/q-49Gf-SFijeu7d2MqztIQ前言近日,Pug3.0.0正式发布,Pug原名Jade,是由...
- 36个工作中常用的JavaScript函数片段「值得收藏」
-
作者:Eno_Yao转发链接:https://segmentfault.com/a/1190000022623676前言如果文章和笔记能带您一丝帮助或者启发,请不要吝啬你的赞和收藏,你的肯定是我前进的...
- 深入JavaScript教你内存泄漏如何防范
-
作者:大道至简转发链接:https://mp.weixin.qq.com/s/0w6aWwpR3MAJnmyLwDnAzA前言一般情况下,忽视内存管理不会对传统的网页产生显著的后果。这是因为,用户刷新...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...
- 用STM32做了个电子秤,成本仅两位数,精度高!解析一下原理
-
俗话说得好!人在胖,秤在看!所以,我想DIY一个精度高的体重秤!并希望它不只能称体重:还能像这样称克重(可设置KG,G,最低可称100克)……这样一来,做甜品的时候,还能拿来应应急。保姆级教程,记录在...
- 前端开发需要了解常用7种JavaScript设计模式
-
作者|Deven译者|王强策划|小智转发链接:https://mp.weixin.qq.com/s/Lw4D7bfUSw_kPoJMD6W8gg前言JavaScript中的设计模式指的是...
- 毛姆的一个手法|王培军(毛姆作品简介)
-
鲁本斯画《海伦娜·芙尔曼肖像》钱锺书在《宋诗选注》文同小传中说:“具体的把当前风物比拟为某种画法或某某大画家的名作”,是“从文同正式起头”。如钱先生所举的:“峰峦李成似,涧谷范宽能”,“独坐水轩人不到...
- 欣赏 | 朝戈:我渴望找到直达心灵的永恒
-
朋友,通过艺术让我们共同感知世界的永恒与不朽。——朝戈橙色的人物117X71cm布面油画2003包与陈185cm×103cm2007年白色80cm×40cm2009年光布面油画-Light-Oilo...
- Web页面如此耗电!到了某种程度,会是大损失
-
现在用户上网大多使用移动设备或者笔记本电脑。对这两者来说,电池寿命都很重要。在这篇文章里,我们将讨论影响电池寿命的因素,以及作为一个web开发者,我们如何让网页耗电更少,以便用户有更多时间来关注我们的...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 选择器 (30)
- CSS 轮廓 (30)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 中级教程 (30)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)