欢迎大家来到IT世界,在知识的湖畔探索吧!
导读:最近我购置了一台新的电脑,硬盘空间只有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的云空间也在使用。大势之中,我们还是得逐步的接受这些新的事物吧。
最后,祝大家早日在云中安家。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/31515.html