• 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

  • 相关阅读:
    UIView与CALayer的区别,很详细
    IOS图标尺寸一览
    iOS开发之WebView
    iOS开发之版本控制(SVN)
    IOS 多个ImageView图片层叠透明区域点击事件穿透
    UIButton
    UISwitch
    cocoapods_第二篇
    UIView
    IOS开发中 RunLoop,RunTime
  • 原文地址:https://www.cnblogs.com/jaycethanks/p/12125371.html
Copyright © 2020-2023  润新知