zoukankan      html  css  js  c++  java
  • Three中的动画实现-[three.js]

    Table Of Content
    动画原理
    js中动画实现原理setInterval
    js中动画实现新方法requestAnimationFrame
    一个示例

    动画原理

    动画的本质实际上就是快速地不断变化的图片,每张图片对比前后两张图片有细微的变化。整个连续的过程达到一定速度在我们人眼看来就是动画。人眼一般能区分的帧率是24帧。过低给人的感觉就会很不流畅。
    和我们小时候看的动画书原理一样

    ![](https://img2018.cnblogs.com/blog/1735896/202001/1735896-20200101155537787-253121630.gif)

    ### js中动画实现原理 在js中,要实现动画,我们首先需要做的第一件事情,就是找到一个能够以特定时间间隔的方法重复渲染画面,在Three.js中就是重绘场景Scene。在HMTL5之前,JavaScript中的做法是使用JS API提供的定时器,`setInterval(function,interval)`方法,通过该方法,我们可以指定一个定时器,让他间隔的调用定时器函数,例如每隔100毫秒调用一次,在定时器的回调函数中,定义场景渲染。 但是通过`setInterval`方法,有一些很致命的问题,那就是该定时器函数并不会考虑浏览器发生的动作,例如,打开一个新的页面,该方法在后台还是会不断的执行。此外,`setInterval`函数并不是和重绘屏幕同步进行,这将会导致很高的CPU占用,性能会很差。
    ### js中动画实现新方法 为了解决上述问题,现代浏览器提供了一个解决方案,那就是`requestAnimationFrame`方法。 通过该方法,你可以通过调用浏览器定义的方法,指定一个定时器。你的任何重绘都将在该提供的方法中进行。浏览器将会确保流畅高效地绘制场景,该方法的使用也非常简单,你只需要创建一个处理渲染的函数。如下示例: ```javascript function renderScene(){ requestAnimationFrame(renderScene); renderer.render(scene,camera); } ``` 在该函数中,我们不断的调用本身,不断的重绘场景,实现动画效果。
    ### 一个示例: 以下是一个动画示例:
    ![](https://img2018.cnblogs.com/blog/1735896/202001/1735896-20200101223727644-1132905605.gif)

    模型部分代码如下

    function draw(scene,clock) {
    var textureLoader  = new THREE.TextureLoader();
    //太阳
    var sun = new THREE.SphereGeometry(50,50,50);
    var sunMaterial = new THREE.MeshPhongMaterial({
        map:textureLoader.load('./assets/2k_sun.jpg'),
        color:0xffaaaa,
        // wireframe:true
    });
    var sunModel = new THREE.Mesh(sun,sunMaterial);
    
    sunModel.position.set(0,60,0)
    sunModel.castShadow  = true;
    //这个函数 每帧都会在渲染之前执行一次  所有的网格模型 都有这个方法
    sunModel.onBeforeRender = function (renderer, scene, camera) {
        var elapsed =  clock.getElapsedTime();
        this.rotation.y += -Math.PI/120
    
    }
    
    scene.add(sunModel)
    
    //地球
    var sphereGeometry = new THREE.SphereGeometry(20,40,50);
    var sphereMaterial = new THREE.MeshPhongMaterial({
        map:textureLoader.load('./assets/earth_atmos_2048.jpg'),
        specular:0x333333,
    });
    var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);
    // sphere.position.y = 60
    sphere.castShadow  = true;
    
    //这个函数 每帧都会在渲染之前执行一次  所有的网格模型 都有这个方法
    sphere.onBeforeRender = function (renderer, scene, camera) {
        var elapsed =  clock.getElapsedTime();
        this.position.set(Math.sin(elapsed)*200,60,Math.cos(elapsed)*200);
        this.rotation.y += -Math.PI/120
    
    }
    
    scene.add(sphere)
    
    //月球
    var moonGeometry = new THREE.SphereGeometry(5,40,50);
    var moonMaterial = new THREE.MeshPhongMaterial({
        map:textureLoader.load('./assets/moon_1024.jpg'),
        specular:0x333333,
    
    });
    var moon = new THREE.Mesh(moonGeometry,moonMaterial);
    // sphere.position.y = 60
    moon.castShadow  = true;
    
    //这个函数 每帧都会在渲染之前执行一次  所有的网格模型 都有这个方法
    moon.onBeforeRender = function (renderer, scene, camera) {
        var elapsed =  clock.getElapsedTime();
        this.position.set((Math.sin(elapsed*5)*50+Math.sin(elapsed)*200),60,(Math.cos(elapsed)*200+Math.cos(elapsed*5)*50))
    }
    
    scene.add(moon)
    
    }
    

    控制更新以及初始化如下

    function init() {
        var stats = initStats();
        var renderer = initRenderer();
        var camera = initCamera();
        var scene = new THREE.Scene();
        var clock = new THREE.Clock();
        // var elapsed =  Math.acos(clock.getDelta())
    
        initDefaultLighting(scene);
        initModel()
        initControls();
        render();
        draw(scene,clock);
    
        function initModel() {
            //辅助工具
            var helper = new THREE.AxesHelper(900);
            scene.add(helper);
            // var map = new THREE.TextureLoader().load("./assets/jay.jag");
            //外部盒子
            // var material = new THREE.MeshLambertMaterial({
            //     // map: map
            //     color: 0xffffff,
            // });
            // material.transparent = true;
            // material.opacity = 0.4;
    
            //--------------------------------地板--------------------------
            var planeGeometry = new THREE.PlaneGeometry(1000, 1000, 50, 50);
            var planeMaterial = new THREE.MeshBasicMaterial({
                color: 0xff0000,
                wireframe: true
            });
            planeMaterial.transparent = true;
            planeMaterial.opacity = 0.2;
    
            plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.x = 0;
            plane.position.y = -6;
            plane.position.z = 0;
    
    
            //告诉底部平面需要接收阴影
            plane.receiveShadow = true;
    
            scene.add(plane);
            // scene.add(PlaneSegs);
            //--------------------------------地板end-----------------------
        }
    
        //初始化控制器
        var obtControls; //定义控制器变量
        function initControls() {
            //定义控制器核心           
            obtControls = new THREE.OrbitControls(camera, renderer.domElement);
    
            // 如果使用animate方法时,将此函数删除
            // controls.addEventListener('change', render);
            //以下都是为了满足各种需求的各种控制器配置参数
            obtControls.enableDampling = true; //使动画循环使用时阻尼或自转 意思是否有惯性
            obtControls.enableZoom = true; //是否允许缩放
            obtControls.enablePan = true; //是否开启鼠标右键拖拽
            obtControls.autoRotate = false; //是否允许自动旋转
            obtControls.dampingFactor = 0.25; //动态阻尼系数:就是鼠标拖拽旋转灵敏度
            obtControls.minDistance = 0; //设置相机距离原点的最近距离;
            obtControls.maxDistance = 1000; //设置相机距离原点的最远距离;
    
        }
        //控制更新
        function render() {
            stats.update();
            // fpControls.update(clock.getDelta());
            obtControls.update(clock.getDelta());
            requestAnimationFrame(render);
            renderer.render(scene, camera)
        }
    
    }
    

    该demo的完整代码在这里:Link

  • 相关阅读:
    86. Partition List
    328. Odd Even Linked List
    19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)
    24. Swap Nodes in Pairs
    2. Add Two Numbers(2个链表相加)
    92. Reverse Linked List II(链表部分反转)
    109. Convert Sorted List to Binary Search Tree
    138. Copy List with Random Pointer
    为Unity的新版ugui的Prefab生成预览图
    ArcEngine生成矩形缓冲区
  • 原文地址:https://www.cnblogs.com/jaycethanks/p/12125371.html
Copyright © 2011-2022 走看看