百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

ThreeJS 入门教程(一) 是选择桌面的固守还是云原生?

myzbx 2025-05-09 20:34 47 浏览

导读:最近我购置了一台新的电脑,硬盘空间只有1T。我很担心这个电脑还能用多久。性能限制或者空间的限制,都使得在未来3-5年内,这个电脑会被淘汰。

但是,基于云APP的使用,老的电脑是足够了,而且,我们也不会被window或者linux的选择而费尽心思。

性能,在本地的限制将不再成为瓶颈。

第一章 ThreeJS简介

第一节:ThreeJS本地测试安装

作为学习来说,第一步是安装ThreeJS。

仅仅是学习测试,只需要做到以下两步即可。

1、到官网下载Threejs的包。

2、vscode,安装live server 。

这些就够了

当然,还需要浏览器。

很多教程都说要nodejs。其实不需要的。

下载的threejs的文件的结构如下:

源代码在src目录。创建好的在build目录。

其他的目录都是一些工具。可以在后期的使用中慢慢熟悉。

第二节: 开发结构

  1. 没有最好的结构,只有最适合的

如果说什么结构最好,这个没法说的。

这里先推荐一个初学者的结构。

就是在一个目录中有一个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的云空间也在使用。大势之中,我们还是得逐步的接受这些新的事物吧。

最后,祝大家早日在云中安家。

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 &quot;小贱贱&quot;韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...