zoukankan      html  css  js  c++  java
  • ThreeJS实现波纹粒子效果

      今天我们来用ThreeJS的库实现一个波纹粒子效果,我们用到的ThreeJS的库有CanvasRenderer.js,OrbitControls.js,Projector.js,stats.min.js和three.js。这些库都是不可或缺的,我们先来看看实现的效果,如下图所示。

      我们再来看看项目结构是怎么样的,项目结构如下图所示。

    我们的效果全部写在了index.html里,现在我们直接贴出index.html的代码,同学们可以直接拿来运行,代码如下。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>演示页面</title>
        <script src="three.js"></script>
        <script src="Projector.js"></script>
        <script src="CanvasRenderer.js"></script>
        <script src="stats.min.js"></script>
        <script src="OrbitControls.js"></script>
    </head>
    <body>
    </body>
    <script>
        var SEPARATION = 200,
            AMOUNTX = 60,
            AMOUNTY = 60;
        var container, stats;
        var camera, scene, renderer, controls;
        var particles, particle, count = 0;
        var windowHalfX = window.innerWidth / 2;
        var windowHalfY = window.innerHeight / 2;
        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
    
        function init() {
            container = document.createElement('div');
            document.body.appendChild(container);
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
            scene = new THREE.Scene();
    
            /**
             * 设置光源
             * */
            //点光源
            var point = new THREE.PointLight(0xffffff);//白光
            point.position.set(1200, 1200, 1200);//点光源位置
            scene.add(point);//点光源添加进场景
            //环境光
            var ambient = new THREE.AmbientLight(0x999999);//白光
            scene.add(ambient);//环境光添加进场景
    
            //模型
            var cubeGeometry = new THREE.CubeGeometry(1000, 1000, 1000);
            var cubeMaterial = new THREE.MeshLambertMaterial({
                color:0xffff00
                //side:THREE.DoubleSide
            });//材质对象
            var cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial);//网格模型对象
            cubeMesh.translateY(500);
            scene.add(cubeMesh);//正方体网格模型添加到场景中
    
            //粒子
            particles = new Array();
            var PI2 = Math.PI * 2;
            var material = new THREE.SpriteCanvasMaterial({
                color: 0xffffff,
                program: function(context) {
                    context.beginPath();
                    context.arc(0, 0, 0.5, 0, PI2, true);
                    context.fill();
                }
            });
    
            var i = 0;
            for (var ix = 0; ix < AMOUNTX; ix++) {
                for (var iy = 0; iy < AMOUNTY; iy++) {
                    particle = particles[i++] = new THREE.Sprite(material);
                    particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2);
                    particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2);
                    scene.add(particle);
                }
            }
    
            /**
             * 创建渲染器对象
             * */
            renderer = new THREE.CanvasRenderer();
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            container.appendChild(renderer.domElement);
    
            window.addEventListener('resize', onWindowResize, false);
    
            //交互控制器
            /**
             * 鼠标键盘事件监听器
             * */
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.1;
            controls.screenSpacePanning = true;
            controls.minDistance = 0;
            controls.maxDistance = 5000;
            controls.maxPolarAngle = 2*Math.PI;
    
            /**
             * 模型拾取
             * */
            mouse.x = -10000;
            mouse.y = -10000;
    
            function onMouseMove( event ) {
                // calculate mouse position in normalized device coordinates
                // (-1 to +1) for both components
                mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
                mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
            }
    
    
            window.addEventListener( 'mousemove', onMouseMove, false );
        }
    
        function pickUp() {
            // update the picking ray with the camera and mouse position
            raycaster.setFromCamera( mouse, camera );
            // calculate objects intersecting the picking ray
            var intersects = raycaster.intersectObjects( scene.children );
            for ( var i = 0; i < intersects.length; i++ ) {
                intersects[ i ].object.material.color.set( 0xff00ff );
            }
            if(intersects.length === 0){
                scene.children[2].material.color.set( 0xffff00 );
                for(var i=3; i<scene.children.length; i++){
                    scene.children[i].material.color.set( 0xffffff );
                }
            }
            renderer.render( scene, camera );
        }
    
    
        function onWindowResize() {
            windowHalfX = window.innerWidth / 2;
            windowHalfY = window.innerHeight / 2;
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
    
        var rad = 0;
        function render() {
            camera.position.set(2600, 500, 2600);
            camera.up = new THREE.Vector3(0, 1, 0);
            camera.lookAt(new THREE.Vector3(0, 500, 0));
    
            var i = 0;
            for (var ix = 0; ix < AMOUNTX; ix++) {
                for (var iy = 0; iy < AMOUNTY; iy++) {
                    particle = particles[i++];
                    particle.position.y = (Math.sin((ix + count) * 0.2) * 500) +
                        (Math.sin((iy + count) * 0.2) * 500);
                    particle.scale.y = (Math.sin((ix + count) * 0.3) + 1) * 3 +
                        (Math.sin((iy + count) * 0.3) + 1) * 3;
                    particle.scale.x = (Math.sin((ix + count) * 0.3) + 1) * 3 +
                        (Math.sin((iy + count) * 0.3) + 1) * 3;
                }
                scene.children[2].translateY(Math.cos(ix + count/2)*5);
            }
            //模型旋转
            scene.children[2].rotateY(Math.PI/180);
            camera.position.x = 2600*Math.cos(Math.PI/180*rad);
            camera.position.z = -2600*Math.sin(Math.PI/180*rad);
            //点光源位置
            scene.children[0].position.x = 1200*Math.cos(Math.PI/180*rad+Math.PI*0.1);
            scene.children[0].position.z = -1200*Math.sin(Math.PI/180*rad+Math.PI*0.1);
            
            controls.update();
            renderer.render(scene, camera);
            count += 0.1;
            rad += 0.2;
        }
    
        function animate() {
            requestAnimationFrame(animate);
            render();
            pickUp();
        }
    
        init();
        animate();
    </script>
    </html>

      我们分析一下段代码,首先我们看到requestAnimationFrame,这是主循环,我们在init()初始化函数中往scene场景中添加了particle粒子,这些粒子是在XoZ平面上均匀网格散布的。然后我们主循环每次render()都改变粒子的Y坐标,修改的规则是通过sin函数进行Y轴向扰动。每次重绘我们都修改Y坐标,就实现了粒子的波动特效。
      代码很简单,希望能帮助大家做出一套粒子波动的背景特效。鲫鱼非常愿意和大家讨论学习WebGL和ThreeJS的技术,欢迎大家留言,谢谢。本文系原创,如需引用请注明出处:https://www.cnblogs.com/ccentry/p/10125686.html                       

  • 相关阅读:
    ActiveSync合作关系对话框的配置
    WINCE对象存储区(object store)
    Wince 隐藏TASKBAR的方法
    Wince输入法换肤换语言机制
    poj 3080 Blue Jeans 解题报告
    codeforces A. Vasily the Bear and Triangle 解题报告
    hdu 1050 Moving Tables 解题报告
    hdu 1113 Word Amalgamation 解题报告
    codeforces A. IQ Test 解题报告
    poj 1007 DNA Sorting 解题报告
  • 原文地址:https://www.cnblogs.com/ccentry/p/10125686.html
Copyright © 2011-2022 走看看