Three.js官网demo分析(一)

moyebaobei 2019-07-01

Three.js官方文档比较精简,重点介绍api,没有一个合适的零基础的教程,但官网的demo十分丰富,遂产生从demo来逐渐学习Three.js的想法。

以下是目前收集到的较好的学习资源:

  1. Three.js入门指南:http://www.ituring.com.cn/boo...
  2. Three.js官网中文文档:https://threejs.org/docs/inde...
  3. 大牛博客,有很多demo: http://www.wjceo.com/blog/thr...
  4. 图解WebGL&Three.js工作原理: https://www.cnblogs.com/wanbo...
  5. Three.js源码注释: https://blog.csdn.net/omni360...

好,下面回归正题,这是今天要分析的: demo,官网的例子,可以直接跳到github上查看源码,我建议直接把three.js整个项目下载下来,可以直接查看demo的效果,直接打开html文件可能效果有不一样,可以看官网的说法, 也就是需要启动一个本地的服务器,如果你用的webstorm的话,直接右键html文件,就会有个 run 文件的选项,点击就可以启动一个本地服务器来启动本地的文件。

下面是demo的代码:

var camera, scene, renderer;
    var mesh;

    init();
    animate();

    function init() {

        // 初始化透视相机,参数(fov : Number, aspect : Number, near : Number, far : Number)
        // fov — 摄像机视锥体垂直视野角度
        // aspect — 摄像机视锥体长宽比
        // near — 摄像机视锥体近端面
        // far — 摄像机视锥体远端面
        camera = new THREE.PerspectiveCamera( 70, ( window.innerWidth - 600 ) / window.innerHeight, 1, 1000 );
        // position是camera继承自Object3D的属性,表示相机对象在三维空间中的位置
        camera.position.z = 400;

        // 初始化场景
        scene = new THREE.Scene();
        // 加载纹理,TextureLoader是一个加载器,load方法加载文件,返回一个新的纹理对象
        var texture = new THREE.TextureLoader().load( 'textures/crate.gif' );
        // BoxBufferGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
        var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
        // 材质,map属性表示贴图,这里将之前的texture纹理对象添加进来
        var material = new THREE.MeshBasicMaterial( { map: texture } );
        // Mesh方法表示以三角形组成基本网格来形成物体
        mesh = new THREE.Mesh( geometry, material );
        // 将物体添加到场景中
        scene.add( mesh );

        // 初始化渲染器,antialias表示抗锯齿, canvas属性将three.js加载到已有的canvas元素上。
        renderer = new THREE.WebGLRenderer( { antialias: true, canvas: document.getElementById('my-canvas') } );
        // 设置设备像素比。通常用于避免HiDPI设备上绘图模糊
        renderer.setPixelRatio( window.devicePixelRatio );
        // .setSiZe( width : Integer, height : Integer, updateStyle : Boolean )
        // 设置输出canvas的大小,将updateStyle设置为false以阻止对canvas的样式做改变
        renderer.setSize( window.innerWidth - 600, window.innerHeight );
        // domElement为自动创建或已有的canvas元素
        document.body.appendChild( renderer.domElement );

        // 监听浏览器尺寸的修改
        window.addEventListener( 'resize', onWindowResize, false );

    }
    // 浏览器尺寸改变时的回调,重新设置相机和渲染器参数
    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        // 在大多数属性发生改变之后,你将需要调用.updateProjectionMatrix来使得这些改变生效。
        camera.updateProjectionMatrix();

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

    }
    // 动画
    function animate() {
        // 每一帧调用一次
        requestAnimationFrame( animate );

        mesh.rotation.x += 0.005;
        mesh.rotation.y += 0.01;

        renderer.render( scene, camera );
    }

对于初始化透视相机中fov — 摄像机视锥体垂直视野角度和视锥体的理解,可以看看入门指南中的透视相机一章,但视锥体的长宽比都说要和canvas的长宽比一样,我试了一下,如果不一样的话物体就会变形。有点难以理解,其实道理跟图片要在固定长宽的div填满且没有裁剪和空白的情形一样,如果图片跟div长宽比不同的话就会变形。这里的视锥体垂直视野角度在照相机距离物体角度固定的情况下,相当于固定了宽,再根据长宽比算出长,视锥体的面积就固定了,此时视锥体的就相当于一张图片,而canvas就相当于固定宽高的div,所以此时视锥体拉伸铺满。

widthSegments属性可以看入门指南中的基本形状了解

设备像素比可以看链接

一般情况下new THREE.WebGLRenderer()会自动创建一个canvas元素,如果想用自己定义的canvas元素的话,可以传入canvas属性,值为获取的元素。

相关推荐