21.使用Tween.js做动画

<!DOCTYPE html>

<html>

<head>
    <title>Example 09.03 - Animation tween </title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/PLYLoader.js"></script>

    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <script type="text/javascript" src="../libs/tween.min.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>

<body>

    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>

    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        // once everything is loaded, we run our Three.js stuff.
        function init() {

            var stats = initStats();

            // create a scene, that will hold all our elements such as objects, cameras and lights.
            var scene = new THREE.Scene();

            // create a camera, which defines where we're looking at.
            var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

            // create a render and set the size
            var webGLRenderer = new THREE.WebGLRenderer();
            webGLRenderer.setClearColor(new THREE.Color(0x000, 1.0));
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.shadowMapEnabled = true;

            // position and point the camera to the center of the scene
            camera.position.x = 10;
            camera.position.y = 10;
            camera.position.z = 10;
            camera.lookAt(new THREE.Vector3(0, -2, 0));

            // add spotlight for the shadows
            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(20, 20, 20);
            scene.add(spotLight);

            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);

            // call the render function
            var step = 0;


            // setup the control gui
            var controls = new function() {
                // we need the first child, since it's a multimaterial


            };

            var pointCloud = new THREE.Object3D();
            var loadedGeometry;


            // create a tween
            // http://sole.github.io/tween.js/examples/03_graphs.html
            var posSrc = {
                pos: 1
            };
            // 这个库可以用来定义某个属性在两个值之间的过渡,自动计算出起始值和结束值之间的所有中间值。这个过程叫补间。
            // 这个补间定义的是如何从1过渡到0
            var tween = new TWEEN.Tween(posSrc).to({
                pos: 0
            }, 5000);

            tween.easing(TWEEN.Easing.Sinusoidal.InOut);

            //这个补间定义的是如何从0过渡到1
            var tweenBack = new TWEEN.Tween(posSrc).to({
                pos: 1
            }, 5000);
            tweenBack.easing(TWEEN.Easing.Sinusoidal.InOut);
            // 通过chain函数,我们可以让这两个补间首尾相连。这样在启动动画之后,程序就会在这两个补间之间循环。
            tween.chain(tweenBack);
            tweenBack.chain(tween);

            // 遍历粒子系统的所有顶点,并用补间提供的位置更新顶点的位置。
            var onUpdate = function() {
                var count = 0;
                var pos = this.pos;

                loadedGeometry.vertices.forEach(function(e) {
                    var newY = ((e.y + 3.22544) * pos) - 3.22544;
                    pointCloud.geometry.vertices[count++].set(e.x, newY, e.z);
                });

                pointCloud.sortParticles = true;
            };

            tween.onUpdate(onUpdate);
            tweenBack.onUpdate(onUpdate);


            var gui = new dat.GUI();


            var loader = new THREE.PLYLoader();

            loader.load("../assets/models/test.ply", function(geometry) {
                loadedGeometry = geometry.clone();

                var material = new THREE.PointCloudMaterial({
                    color: 0xffffff,
                    size: 0.4,
                    opacity: 0.6,
                    transparent: true,
                    blending: THREE.AdditiveBlending,
                    map: generateSprite()
                });

                pointCloud = new THREE.PointCloud(geometry, material);
                pointCloud.sortParticles = true;
                // 补间动画会在模型加载完毕时启动,所以我们在末尾调用start()函数
                tween.start();
                scene.add(pointCloud);
            });


            render();

            // from THREE.js examples
            function generateSprite() {

                var canvas = document.createElement('canvas');
                canvas.width = 16;
                canvas.height = 16;

                var context = canvas.getContext('2d');
                var gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
                gradient.addColorStop(0, 'rgba(255,255,255,1)');
                gradient.addColorStop(0.2, 'rgba(0,255,255,1)');
                gradient.addColorStop(0.4, 'rgba(0,0,64,1)');
                gradient.addColorStop(1, 'rgba(0,0,0,1)');

                context.fillStyle = gradient;
                context.fillRect(0, 0, canvas.width, canvas.height);

                var texture = new THREE.Texture(canvas);
                texture.needsUpdate = true;
                return texture;

            }

            function render() {
                stats.update();
                // 告知three.js库什么时候应该刷新已知的所有补间,为此可以调用TWEEN.update()
                TWEEN.update();
                requestAnimationFrame(render);
                webGLRenderer.render(scene, camera);
            }

            function initStats() {

                var stats = new Stats();
                stats.setMode(0); // 0: fps, 1: ms

                // Align top-left
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.left = '0px';
                stats.domElement.style.top = '0px';

                document.getElementById("Stats-output").appendChild(stats.domElement);

                return stats;
            }
        }
        window.onload = init;
    </script>
</body>

</html>
上一篇:[leetcode/lintcode 题解] 腾讯面试题:一和零


下一篇:Typescript(三)类型注解和类型推断