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                       

  • 相关阅读:
    文件处理(记录经典代码及相关逻辑)
    python与pip在widow下cmd命令行操作问题收集:python、pip不是内部或外部命令,也不是可运行程序
    python—函数中存在的部分问题
    python —匿名函数(lambda)
    Python—递归函数
    python-函数参数
    python代码运行过程
    String类练习
    String类的常用方法
    死锁与进程通信
  • 原文地址:https://www.cnblogs.com/ccentry/p/10125686.html
Copyright © 2011-2022 走看看