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

导读:最近我购置了一台新的电脑,硬盘空间只有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 组件

第三节: 基本代码结构

我们先列出一个最简单的完整的代码结构

ThreeJS学习笔记

代码分析:

1、头部:属于标准头部信息。

ThreeJS学习笔记

2、定义嵌入的块名称

定义一个p块,名称用id来标识。在后面的render放置的位置时会指明。

3、导入模块文件

单独定义一个script块,类型是importmap,用于导入一个模块,并重命名。

4、主程序代码

(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相机有四个参数。

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分辨率来绘制你的应用程序,假定为100%的宽高。

最后,我们把 renderer 元素添加到HTML文档中。这里是一个 元素,渲染器用来显示场景。

上面的都是准备工作,电影布景都好了,演员还没进场。接下来我们添加“演员”(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的云空间也在使用。大势之中,我们还是得逐步的接受这些新的事物吧。

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

展开阅读全文

页面更新:2024-04-17

标签:几何   函数   摄像机   属性   入门教程   定义   桌面   精灵   参数   结构   代码   时间

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top