three.js入门篇

2,393 阅读4分钟

背景

一个偶然的机会看到了用three.js开发的3D效果,立即引起了我的兴趣,直接用JavaScript轻松的创建在浏览器上显示的3D模型,这在以前要做这样的效果门槛可是很高的,这实在是前端开发的一个福音。

简介

OpenGL是最常用的跨平台图形库,WebGL是基于OpenGL设计的面向web的图形化标准,提供了一系列JavaScript API,通过这些API进行图形渲染将得以利用图形硬件从而获得较高性能。 而Three.js是通过对WebGL接口的封装与简化而形成的一个易用的图形库。

简单点的说法:WebGL可以看成是浏览器给我们提供的接口,在JavaScript中可以直接用这些API进行3D图形的绘制;而Three.js就是在这些接口上又帮我们封装得更好用一些。 Three.js是通过对WebGL接口的封装与简化而形成的一个易用的图形库。

也有很多人直接使用WebGL开发图形化应用,但WebGL门槛相对较高,需要相对较多的数学知识。虽然WebGL提供的是面向前端的API,但本质上WebGL跟前端开发完全是两个不同的方向,知识的重叠很少。相关性只是他们都在web平台上,都是用JavaScript而已。一个前端程序员或许还熟悉解析几何,但是还熟悉线性代数的应该寥寥无几了(比如求个逆转置矩阵试试?),更何况使用中强调矩阵运算中的物理意义,这在教学中也是比较缺失的。

因此,前端工程师想要短时间上手WebGL还是挺有难度的。于是,Three.js对WebGL提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本。并且,几乎没有损失WebGL的灵活性。

概念

在Three.js中,有3个重要的组件:场景(scene)、相机(camera)和渲染器(renderer)。这是将物体渲染到网页中的三个必不可少的要素。

场景
场景是所有物体的容器,如果要显示一个苹果,就需要将苹果对象加入场景中。

相机
相机决定了场景中那个角度的景色会显示出来。相机就像人的眼睛一样,人站在不同位置,抬头或者低头都能够看到不同的景色。

场景只有一种,但是相机却又很多种。和现实中一样,不同的相机确定了呈相的各个方面。比如有的相机适合人像,有的相机适合风景,专业的摄影师根据实际用途不一样,选择不同的相机。对程序员来说,只要设置不同的相机参数,就能够让相机产生不一样的效果。

渲染
最后一步就是设置渲染器,渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。

看一下代码框架:

var scene = new THREE.Scene();  // 场景
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);// 相机
var renderer = new THREE.WebGLRenderer();   // 渲染器
renderer.setSize(window.innerWidth, window.innerHeight);    
// 设置渲染器的大小为窗口的内宽度,也就是内容区的宽度
document.body.appendChild(renderer.domElement);

注: 渲染器renderer的domElement元素,表示渲染器中的画布,所有的渲染都是画在domElement上的,所以这里的appendChild表示将这个domElement挂接在body下面,这样渲染的结果就能够在页面中显示了。

例子

要开始three.js很简单,只要有浏览器和three.js这个源文件就可以开始了。

three.js可以直接引用cdn路径:cdn.bootcss.com/three.js/92…),或者到github下载源码

下面用three.js创建一个简单的例子,先看效果图:

下面是代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8>
     <style>
        body {
            margin: 0;
        }

    </style>
</head>
<body onload="init()">
<script src="https://cdn.bootcss.com/three.js/92/three.js"></script>
<script>
    //声明一些全局变量
    var renderer, camera, scene, geometry, material, mesh;
  
   //初始化场景
    function initScene() {
        scene = new THREE.Scene(); //实例化场景
    }

    //初始化相机
    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200); //实例化相机
        camera.position.set(0, 0, 15);
    }

    //初始化渲染器
    function initRenderer() {
        renderer = new THREE.WebGLRenderer(); //实例化渲染器
        renderer.setSize(window.innerWidth, window.innerHeight); //设置宽和高
        document.body.appendChild(renderer.domElement); //添加到dom
    }
    
    //创建模型
    function initMesh() {
        geometry = new THREE.BoxGeometry( 2, 2, 2 ); //创建几何体
        material = new THREE.MeshNormalMaterial(); //创建材质

        mesh = new THREE.Mesh( geometry, material ); //创建网格
        scene.add( mesh ); //将网格添加到场景
    }

    //运行动画
    function animate() {
        requestAnimationFrame(animate); //循环调用函数

        mesh.rotation.x += 0.01; //每帧网格模型的沿x轴旋转0.01弧度
        mesh.rotation.y += 0.02; //每帧网格模型的沿y轴旋转0.02弧度

        renderer.render( scene, camera ); //渲染界面
    }

    //初始化函数,页面加载完成是调用
    function init() {
        initScene();//初始化场景
        initCamera();//初始化相机
        initRenderer();//渲染
     
        initMesh();//创建模型
        animate();//运行动画
    }
</script>
</body>
</html>

可以看到,就是进行场景、相机、渲染器三个要素的准备之后就可以进行模型的创建了,这是一个很简单的3D效果的例子,更多效果可以看官网,web开发人员也可以实现很多复杂的3D效果。