【ThreeJS基础教程-初识Threejs】1.ThreeJS的HelloWorld

学习ThreeJS的捷径

本段内容会写在0篇以外所有的,本人所编写的Threejs教程中

对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久

如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS

  1. 没事就把所有的文档翻一遍,哪怕看不懂,也要留个印象,至少要知道Threejs有什么
  2. 没事多看看案例效果,当你记忆的案例效果足够多时,下次再遇到相似问题时,你就有可能第一时间来找对应的案例,能更快解决你自己的问题
  3. 上述案例不只是官网的案例,郭隆邦技术博客,跃焱邵隼,暮志未晚等站点均有不少优质案例,记得一并收藏
    http://www.yanhuangxueyuan.com/ 郭隆邦技术博客
    https://www.wellyyss.cn/ 跃焱邵隼
    http://www.wjceo.com/ 暮志未晚
    这三个站点是我最常逛的站点,推荐各位有事没事逛一下,看看他们的案例和写法思路,绝对没坏处

那么,接下来,就正式进入ThreeJS的世界中探索吧

杂项

本教程参考官方写法,以ES6语法为主要语法编写,对ES6不熟悉的同学建议先去简单学习一下ES6相关语法后,再阅读本教程

第一个案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src = "../three.js-master/build/three.js"></script>
</head>
<body>
<script>
    let scene = new THREE.Scene();
    
    let renderer = new THREE.WebGLRenderer();
    
    renderer.setSize(800,800);
    
    document.body.appendChild(renderer.domElement);
    
    let camera = new THREE.PerspectiveCamera(
        60,800/800,0.1,2000
    );
    camera.position.z += 5;
    
    let geometry = new THREE.BoxGeometry(1,1,1);

    let material = new THREE.MeshBasicMaterial({
        color:"#ff0000"
    });

    let mesh = new THREE.Mesh(geometry,material);

    scene.add(mesh);

    function render() {
        renderer.render(scene,camera);
        requestAnimationFrame(render);
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.01;
    }

    render();

</script>
</body>
</html>

案例效果

可以看到你的浏览器中,出现了一个红色在旋转的方块

案例解析

引入threejs

<script src = "../three.js-master/build/three.js"></script>

这里笔者使用了本地版threejs,关于文件的位置在上一篇已经做了介绍,这里不做太多赘述

创建一个场景(演出舞台)

	let scene = new THREE.Scene();

场景:用于容纳要素的必要元素,所有的Threejs项目,案例,都必须要有至少一个这样一个场景对象,而且尽量放置于全局变量中,以方便访问

构造器 : new Scene();

构造器可以不用添加任何参数

官方文档解释:
场景能够让你在什么地方、摆放什么东西来交给three.js来渲染,这是你放置物体、灯光和摄像机的地方。
官方文档关于scene这个类的所有文档

本段内容针对【对 面向对象 概念模糊的同学】, 官方文档中最上方的一行

有一个 Object3D和箭头,点进去Object3D的话,可以看到Object3D这个类的文档

当有这样的标注时,Object3D的文档,加上咱们看到的Scene的文档,合起来,才是Scene完整的文档
在面向对象的概念中,Object3D是Scene的父类,超类,Scene为继承类,Scene继承全部的Object3D的属性,函数

本段内容结束

创建相机(摄影师)

场地有了,那么现在我们需要一个摄影师

    let camera = new THREE.PerspectiveCamera(
        60,800/800,0.1,2000
    );
    camera.position.z += 5;

three的摄影师也有好几位,但是我们一般默认请这位摄影师:PerspectiveCamera

透视相机官方文档

构造器:PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

关于相机的具体内容,将在后续的文章中详细描述,这里暂时仅放出这位摄影师的对应官方文档

属性:position
从官方文档可以看到,PerspectiveCamera继承自camera,camera又继承自Object3D,所以创建的这个PerspectiveCamera对象,可以使用Object3D这个类的属性: position
position,字面意思,物体位置

position的值,是一个Vector3对象,这个对象后续会详细讲解

camera.position.z += 5; 这一行的用途是,让摄影师沿着空间坐标系Z轴正半轴走5个单位
当这个值被改变时,我们看到的案例中的小方块的大小也会随之改变
注意,部分教程会在写案例或者教程的时候,使用OrthographicCamera正交相机,此时修改position.z不会出现近大远小的渲染效果

创建一个渲染器(相片处理)

 	let renderer = new THREE.WebGLRenderer();

    renderer.setSize(800,800);

    document.body.appendChild(renderer.domElement);

Threejs提供的渲染器有多种,WebGLRenderer 是最常用的渲染器,刚入坑的新人也可以像记忆上述scene一样,先把 项目中必定要创建渲染器 记在心里即可,只有少数情况下会用到其他渲染器,这个在后续的教程中会提到

渲染器简单介绍:如果以照相作为参考,那么,上面的场景Scene,就是你想要拍摄的场景,上面的相机Camera就是拍摄场景用的道具,而渲染器,就是相机拍摄后的照片

渲染器最主要的功能是,创建/获取一个画布< canvas >,然后更新它内部显示的图像

渲染器官方解释:WebGL Render 用WebGL渲染出你精心制作的场景。

渲染器官方文档

此时不建议过多阅读渲染器的文档,简单查阅一下能看懂的内容即可,这篇文档对于新人来说理解难度太高了

构造器:new WebGLRenderer(parameters:Object)

parameters为一个对象,对象中包含了大量设置,可以设置你的渲染器,达成不同的渲染效果

关于渲染器后续会专门出一期来详细讲解,这里不做过多赘述,本案例中并未加入任何参数,均使用默认值

函数:setSize( width, height );
用于设置画布的大小
上述案例中,笔者将画布设置到了800 * 800,这里的800使用的单位是px

如果你希望把画布铺满全屏,那么使用下面的代码即可

    renderer.setSize(window.innerWidth,window.innerHeight);

创建一个物体(演员)

场地有了,摄影师有了,渲染器有了,那么我们现在就缺一个演员了

	//演员
	let geometry = new THREE.BoxGeometry(1,1,1);
	//化妆师
    let material = new THREE.MeshBasicMaterial({
        color:"#ff0000"
    });
	//化妆后的演员
    let mesh = new THREE.Mesh(geometry,material);
	//演员登台
    scene.add(mesh);

BoxGeometry : 盒子模型,就是我们看到的案例效果中,那个会动的盒子,new出来的这位geometry就是我们的演员了,我们这位演员,长宽高均为1个单位,修改大小后,案例中的方块会出现相应的增大或者缩小
MeshBasicMaterial : 基础材质,这里给了一个对象,对象中给了一个属性:color : “#ff0000”,这个属性决定,这个材质使用到演员身上,会把演员染成红色,new出来的这位material,就相当于我们化妆师了
Mesh : 最后,经过我们的化妆师material对演员geometry进行化妆后,现在上场的就是我们正式出演的演员Mesh了
scene.add( mesh ):演员登台

以下为上述使用到的类的官方文档:
BoxGeometry
MeshBasicMaterial
Mesh

函数:Object3D.add( object:Object3D )
所有的Object3D对象均可使用该函数,用于添加一个子项,子项的类型必须为Object3D及其继承类
添加的子项可以使用Object3D.children属性来访问,该属性为一个数组

这里的所有要素均不做过多介绍,后续会有相应的文章来详细介绍各种的演员,化妆师,放心,一个都跑不了

开始渲染(演员正式演出)

    function render() {
        renderer.render(scene,camera);
        requestAnimationFrame(render);
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.01;
    }
    render();

既然我们所有的人都准备齐全了,那么我们就预设好一套表演流程吧

函数:renderer.render( scene: Scene, camera:Camera );
首先,摄影师需要拍摄下来,然后将拍摄后的初始相片交给渲染器,并由渲染器洗刷出来,放置到< canvas> 中
然后,设定拍摄频率,虽然可以用定时器setInterval,但是,这种方式,并不是比较好的一种方式,如果你的场景过大,或者设备等级过低,那么使用setInterval很可能会造成渲染卡顿,非常不流畅等问题

关于requestAnimationFrame

这里官方提供了一条: requestAnimationFrame( function : Function )
这个函数绑定的函数,会跟随浏览器刷新而执行,浏览器每刷新一帧,则该函数执行一次
requestAnimationFrame官方文档

常见的刷新帧率,如30,45,60,120,144等,也意味着这个函数,每秒会执行多少次

最常见的帧率为60帧,后续所有围绕requestAnimationFrame都会默认为它每秒执行60次来说明

这里不推荐在requestAnimationFrame 绑定的函数中写过多的代码,尤其是for循环,它的执行频率太高了

属性:Object3D.rotation
字面意思,该属性用于控制旋转,该属性的值为一个Euler对象,关于这个对象在后续会详细讲解

既然演员登台了,那么我们也不能让演员闲着,就让演员为咱们跳支舞
让它每一帧向x轴正半轴旋转0.01 rad(弧度),向y轴正半轴旋转0.01rad(弧度)

最后,设定好我们的演出方式后,开始演出,执行render()函数,正式演出

让我们的代码更加直观好看

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src = "../three.js-master/build/three.js"></script>
</head>
<body>
<script>

    let scene,renderer,camera;

    let mesh;

    function init(){
        scene = new THREE.Scene();

        renderer = new THREE.WebGLRenderer();
		
		renderer.setSize( 800, 800);

        document.body.appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(
            60,800/800,0.1,2000
        );
        camera.position.z += 5;

    }

    function addMesh(){
        let geometry = new THREE.BoxGeometry(1,1,1);
        let material = new THREE.MeshBasicMaterial({
            color:"#ff0000"
        });
        mesh = new THREE.Mesh(geometry,material);
        scene.add(mesh);
    }

    function render() {
        renderer.render(scene,camera);
        requestAnimationFrame(render);
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.01;
    }

    init();
    addMesh();
    render();

</script>
</body>
</html>

上述代码与第一版案例的代码,在效果上并没有什么不同,但是,这样写比起上面的代码来说,更具有逻辑性

init()函数,用于初始化threejs中必要的元素,如:场景,相机,渲染器
addMesh() 函数,用于添加元素到场景中
最后的render()函数与上面案例基本一致

向ES6出发

由于官方的案例,从106版本开始,全面向ES6靠拢,所以如果你是从新版本(140之后)开始学习的话,官网的案例可能会存在看不懂的情况,这里笔者也是写了一套类似于官网案例写法的,同样效果的上述案例

后续这里的案例均会以下列写法为主

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

<script type="importmap">
			{
				"imports": {
					"three": "../three.js-master/build/three.module.js"
				}
			}
		</script>
<script type="module">
    import * as THREE from 'three';

    let scene,renderer,camera;

    let mesh;

    function init(){
        scene = new THREE.Scene();

        renderer = new THREE.WebGLRenderer();

        renderer.setSize( 800, 800);


        document.body.appendChild(renderer.domElement);

        camera = new THREE.PerspectiveCamera(
            60,800/800,0.1,2000
        );
        camera.position.z += 5;

    }

    function addMesh(){
        let geometry = new THREE.BoxGeometry(1,1,1);
        let material = new THREE.MeshBasicMaterial({
            color:"#ff0000"
        });
        mesh = new THREE.Mesh(geometry,material);
        scene.add(mesh);
    }

    function render() {
        renderer.render(scene,camera);
        requestAnimationFrame(render);
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.01;
    }

    init();
    addMesh();
    render();

</script>
</body>
</html>

上方引入的<script async …这一大长串
是为了方便最新式的threejs能够方便引入库文件的一个库,参考官方写法写下来即可,无需深究,因为实际开发时,基本用不到这个东西

< script type=“importmap”>
{
“imports”: {
“three”: “…/three.js-master/build/three.module.js”
}
}
< /script>
这一部分的主要作用是预设three的位置,下方引用时,则无需再引入完整路径
这个路径根据自己实际情况去写

转换为ES6写法 有两个重要的点

第一:< script type=“module”> ,必须在这里带上 type=“module”,否则无法使用import语法
第二,引入方式完全使用ES6,而不再使用< script src=“”>方式引入

其他的相关内容,比如let,const,import等,熟悉vue,react的同学基本上无需多做讲解,vue和React也基本上都用的ES6语法

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值