用Three.js做一个简单的3D场景

Three.js是什么

Three.js 是一款运行在浏览器中的 3D 引擎,我们可以用它来创造我们所需要的一系列3D动画场景,简而言之就是建在网页上的3D模型。利用Three.js可以制作出很多酷炫的3D动画,并且Three.js还可以通过鼠标、键盘、拖拽等事件形成交互,在页面上增加一些3D动画和3D交互可以产生更好的用户体验。


Three.js程序结构

主要分为三大结构:场景Scene 相机Camera 渲染器Renderer

程序整个运行的过程就是:先加载场景—— 然后相机——最后渲染器

 

 从实际生活中拍照角度理解,立方体网格模型和光照组成了一个虚拟的三维场景类似你要拍摄的物体,相机对象就像你生活中使用的相机一样可以拍照,只不过一个是拍摄真实的景物,一个是拍摄虚拟的景物,拍摄一个物体的时候相机的位置和角度需要调整,虚拟的相机还需要设置投影方式,当你创建好一个三维场景,相机也设置好,就差一个动作“咔”,通过渲染器就可以执行拍照动作了

 

简单理解了用Three.js做3D引擎的原理,那今天我们就来做一个简单的3D立方体吧


立方体

首先我们要在html文件中引入three.js,就像引入其它.js文件一样直接引入,它需要去官网下载

这里,我用的是相对路径

或者引用相对路径

<!--绝对路径远程加载-->
<script src="http://www.yanhuangxueyuan.com/3D/example/three.js"></script>
<!-- 压缩版本 -->
<script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>

 然后,在body里插入代码段就可以了,具体代码解释如下:

<body>
  <script>

    //  创建场景对象Scene

    var scene = new THREE.Scene();

    //创建网格模型
    // var geometry = new THREE.SphereGeometry(60, 40, 40); //创建一个球体几何对象
    var geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象
    var material = new THREE.MeshLambertMaterial({       //创建材质对象Material
      color: 0x008080   //立方体的颜色
    });
    var mesh = new THREE.Mesh(geometry, material); //创建网格模型对象Mesh
    scene.add(mesh);   //将网格mesh模型添加到场景中
    
    // 光源设置
    
    //点光源
    var point = new THREE.PointLight(0xffffff);
    point.position.set(400, 200, 300); //点光源的位置
    scene.add(point); //点光源添加到场景中
    //环境光
    var ambient = new THREE.AmbientLight(0x444444);
    scene.add(ambient);
    // console.log(scene)
    // console.log(scene.children)
    
     // 相机设置
     
    var width = window.innerWidth; //窗口宽度
    var height = window.innerHeight; //窗口高度
    var k = width / height; //窗口宽高比
    var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
    //创建相机对象
    var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
    camera.position.set(200, 300, 200); //设置相机位置
    camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
    
      // 创建渲染器对象
    
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);//设置渲染区域尺寸
    renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
    document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
    //执行渲染操作   指定场景、相机作为参数
    renderer.render(scene, camera);
  </script>

</body>

 展示效果:

旋转动画 

做到这里,只是在网页上呈现一个不动的3D立方体,为了增加趣味性和操作性,我们可以将渲染操作封装成一个函数,用setInterval让它间隔20ms周期性地调用render()渲染函数、不断地刷新

    // 渲染函数
    function render() {
        renderer.render(scene,camera);//执行渲染操作
        mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
    }
    //间隔20ms周期性调用渲染函数render()
    setInterval("render()",20);

这里的时间单位是ms,20ms也就是刷新频率为50FPS(1s/20ms),即1s内屏幕刷新50次(相信打游戏的小伙伴都不陌生)

展示效果如下:

或者也可以通过requestAnimationFrame请求再次执行渲染函数render,渲染下一帧,这样也可以达到不断刷新,旋转的效果

    // 渲染函数
    let T0 = new Date();//上次时间
    function render() {
        let T1 = new Date();//本次时间
        let t = T1-T0;//时间差
        console.log(t);//两帧之间时间间隔  单位:ms
        T0 = T1;//把本次时间赋值给上次时间
        renderer.render(scene,camera);//执行渲染操作
        mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
        requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
    }
    render();

我们可以创建两个临时变量T1和T0去记录本次执行渲染和上次执行渲染所需时间,再将他们相减,就得到了两帧之间的时间间隔,发现稳定在17ms左右,58的fps,相较于我们自己设置的时间周期,它的fps更高,也没有局限性

展示效果如下: 

 鼠标操作三维场景旋转缩放

我们已经实现了让立方体机械性的动了起来,那可不可以通过鼠标来操控,让它可以转到任意我们想要的角度和位置呢

首先,我们还需要引入一个新的Threejs扩展控件——OrbitControls.js,它叫轨道控件,用它可以实现场景用鼠标交互,让场景动起来,控制场景的旋转、平移和缩放

  <!-- 引入轨道控件OrbitControls.js -->
  <!-- 相对路径 -->
  <script src="./OrbitControls.js"></script>
  <!-- 绝对路径 -->
  <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>

这里,轨道控件提供了一个构造函数,我们创建一个新的构造函数,再添加一个鼠标监听事件,鼠标有所动作,触发渲染函数,立方体会执行相应的效果

    // 渲染函数
    function render() {
      renderer.render(scene, camera); //执行渲染操作
    }
    render();
    //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
    var controls = new THREE.OrbitControls(camera,renderer.domElement);
    //监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
    controls.addEventListener('change', render);

展示效果:

 实际上轨道控件还有很多属性可以设置,但在本小例中没有应用到,详细的用法可参考官方文档:点击打开链接

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值