Three.js--5.用动画扩展你的首个场景

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vivian_1122/article/details/86735471

         如果要在场景中加入动画,那么首先要找到一种方法,使得场景可以以一定的时间间隔进行渲染;

在HTML5和JavaScript API(应用开发接口)出来之前,这个方法是使用setInterval(function,interval)方法;

虽然,我们可以通过setInterval() 方法指定函数每100毫秒调用一次,但是,这个函数的问题是它并不考虑

浏览器中发生的事情;如果你正在浏览其他页面  ,这个函数仍然会每隔几毫秒就会被调一次;

除此之外,setInterval()方法并没有跟显示器的重画同步,这可能会导致较高的CPU使用率,降低系统效率。

引入requestAnimationFrame()方法

          幸运的是 ,现在的浏览器已经有了解决setInterval()函数问题的方法,即requestAnimationFrame()函数;

通过requestAnimationFrame() 你可以指定一个函数,按照浏览器定义的时间间隔调用。

你可以在这个指定的函数里执行所有必要的绘画操作,而浏览器则会尽可能保证绘画过程平滑,高效;

写一个负责渲染的函数

function animate(){
    requestAnimationFrame(animate);
    renderer.render(scene,camera);
}
animate();

          在animate() 函数里,我们又调用了一次 requestAnimationFrame(),目的是让这个动画持续进行;

整个场景创建完毕之后,调用一次animate() 函数来启动动画;

添加动画之前,需要引入一个小的辅助库

这个辅助库可以检测出动画运行的帧频;
显示动画时,该库可以在一个小图片里显示每秒显示的帧数(FPS)

//引入库
<script type="text/javascript" src="./libs/stats.js"></script>

//添加一个div元素,用来显示统计图形
<div id = "Stats-output"></div>

//初始化统计对象,并添加到div元素里
function initStats(){
    var stats = new Stats();
    //设置为0,监测的是FPS,如果设置为1,那么监测的是渲染时间
    stats.setMode(0);
    stats.domElement.style.position='absolute';
    stats.domElement.style.left='opx';
    stats.domElement.style.top='opx';
    document.getElementById('Stats-output').appendChild(stats.domElement);
    return stats;
}
//一开始调用此函数,使场景拥有了统计的功能
function init(){
    var stats = initStats();
    ...
}

//告诉stats对象每次渲染开始的时间,可以在animate()函数里调用stats.update()方法
function animate(){
    stats.update();
    ...
    requestAnimationFrame(animate);
    renderer.render(scene,camera);
}

添加动画,完整的代码参考

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>这世界唯一的妳</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<script src="./libs/three.js"></script>
<script src="./libs/stats.js"></script>

<body onload='init()'>
    <div id="dv"></div>
    <script>
        function init() {
            var stats = initStats();
            var scene = new THREE.Scene();
            var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            var renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(0x000000);
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMapEnabled = true;

            var planeGeometry = new THREE.PlaneBufferGeometry(60, 20);
            var planeMaterial = new THREE.MeshLambertMaterial({
                color: 0xcccccc
            });
            var plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.x = 10;
            plane.position.y = 0;
            plane.position.z = 0;
            plane.receiveShadow = true;
            scene.add(plane);

            var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
            var cubeMaterial = new THREE.MeshLambertMaterial({
                color: 0xff0000
            });
            var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.position.x = -10;
            cube.position.y = 3;
            cube.position.z = 0;
            cube.castShadow = true;
            scene.add(cube);

            var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
            var sphereMaterial = new THREE.MeshLambertMaterial({
                color: 0x0D4012
            });
            var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
            sphere.position.x = 13;
            sphere.position.y = 3;
            sphere.position.z = 0;
            sphere.castShadow = true;
            scene.add(sphere);


            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40, 60, -10);
            spotLight.castShadow = true;
            scene.add(spotLight);
            var ambientLight = new THREE.AmbientLight(0x0c0c0c);
            scene.add(ambientLight);

            camera.position.x = -30;
            camera.position.y = 40;
            camera.position.z = 30;
            camera.lookAt(scene.position);

            function initStats() {
                var stats = new Stats();
                stats.setMode(0);
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.left = '0px';
                stats.domElement.style.top = '0px';
                document.getElementById('dv').appendChild(stats.domElement);
                return stats;
            }

            document.getElementById('dv').appendChild(renderer.domElement);

            var step = 0
            var animate = function() {
                stats.update();
                //球的弹跳速度
                step += 0.04;
                requestAnimationFrame(animate);
                sphere.position.x = 20 + (10 * (Math.cos(step)));
                sphere.position.y = 2 + (5 * Math.abs(Math.sin(step)));
                cube.rotation.x += 0.05;
                cube.rotation.y += 0.05;
                renderer.render(scene, camera);
            }
            animate();

        }
    </script>
</body>

</html>

下一节,使用dat.GUI库添加一个用户界面

猜你喜欢

转载自blog.csdn.net/vivian_1122/article/details/86735471