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

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

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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>演示页面</title>
  6. <script src="three.js"></script>
  7. <script src="Projector.js"></script>
  8. <script src="CanvasRenderer.js"></script>
  9. <script src="stats.min.js"></script>
  10. <script src="OrbitControls.js"></script>
  11. </head>
  12. <body>
  13. </body>
  14. <script>
  15. var SEPARATION = 200,
  16. AMOUNTX = 60,
  17. AMOUNTY = 60;
  18. var container, stats;
  19. var camera, scene, renderer, controls;
  20. var particles, particle, count = 0;
  21. var windowHalfX = window.innerWidth / 2;
  22. var windowHalfY = window.innerHeight / 2;
  23. var raycaster = new THREE.Raycaster();
  24. var mouse = new THREE.Vector2();
  25.  
  26. function init() {
  27. container = document.createElement('div');
  28. document.body.appendChild(container);
  29. camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
  30. scene = new THREE.Scene();
  31.  
  32. /**
  33. * 设置光源
  34. * */
  35. //点光源
  36. var point = new THREE.PointLight(0xffffff);//白光
  37. point.position.set(1200, 1200, 1200);//点光源位置
  38. scene.add(point);//点光源添加进场景
  39. //环境光
  40. var ambient = new THREE.AmbientLight(0x999999);//白光
  41. scene.add(ambient);//环境光添加进场景
  42.  
  43. //模型
  44. var cubeGeometry = new THREE.CubeGeometry(1000, 1000, 1000);
  45. var cubeMaterial = new THREE.MeshLambertMaterial({
  46. color:0xffff00
  47. //side:THREE.DoubleSide
  48. });//材质对象
  49. var cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial);//网格模型对象
  50. cubeMesh.translateY(500);
  51. scene.add(cubeMesh);//正方体网格模型添加到场景中
  52.  
  53. //粒子
  54. particles = new Array();
  55. var PI2 = Math.PI * 2;
  56. var material = new THREE.SpriteCanvasMaterial({
  57. color: 0xffffff,
  58. program: function(context) {
  59. context.beginPath();
  60. context.arc(0, 0, 0.5, 0, PI2, true);
  61. context.fill();
  62. }
  63. });
  64.  
  65. var i = 0;
  66. for (var ix = 0; ix < AMOUNTX; ix++) {
  67. for (var iy = 0; iy < AMOUNTY; iy++) {
  68. particle = particles[i++] = new THREE.Sprite(material);
  69. particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2);
  70. particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2);
  71. scene.add(particle);
  72. }
  73. }
  74.  
  75. /**
  76. * 创建渲染器对象
  77. * */
  78. renderer = new THREE.CanvasRenderer();
  79. renderer.setPixelRatio(window.devicePixelRatio);
  80. renderer.setSize(window.innerWidth, window.innerHeight);
  81. container.appendChild(renderer.domElement);
  82.  
  83. window.addEventListener('resize', onWindowResize, false);
  84.  
  85. //交互控制器
  86. /**
  87. * 鼠标键盘事件监听器
  88. * */
  89. controls = new THREE.OrbitControls(camera, renderer.domElement);
  90. controls.enableDamping = true;
  91. controls.dampingFactor = 0.1;
  92. controls.screenSpacePanning = true;
  93. controls.minDistance = 0;
  94. controls.maxDistance = 5000;
  95. controls.maxPolarAngle = 2*Math.PI;
  96.  
  97. /**
  98. * 模型拾取
  99. * */
  100. mouse.x = -10000;
  101. mouse.y = -10000;
  102.  
  103. function onMouseMove( event ) {
  104. // calculate mouse position in normalized device coordinates
  105. // (-1 to +1) for both components
  106. mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  107. mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  108. }
  109.  
  110. window.addEventListener( 'mousemove', onMouseMove, false );
  111. }
  112.  
  113. function pickUp() {
  114. // update the picking ray with the camera and mouse position
  115. raycaster.setFromCamera( mouse, camera );
  116. // calculate objects intersecting the picking ray
  117. var intersects = raycaster.intersectObjects( scene.children );
  118. for ( var i = 0; i < intersects.length; i++ ) {
  119. intersects[ i ].object.material.color.set( 0xff00ff );
  120. }
  121. if(intersects.length === 0){
  122. scene.children[2].material.color.set( 0xffff00 );
  123. for(var i=3; i<scene.children.length; i++){
  124. scene.children[i].material.color.set( 0xffffff );
  125. }
  126. }
  127. renderer.render( scene, camera );
  128. }
  129.  
  130. function onWindowResize() {
  131. windowHalfX = window.innerWidth / 2;
  132. windowHalfY = window.innerHeight / 2;
  133. camera.aspect = window.innerWidth / window.innerHeight;
  134. camera.updateProjectionMatrix();
  135. renderer.setSize(window.innerWidth, window.innerHeight);
  136. }
  137.  
  138. var rad = 0;
  139. function render() {
  140. camera.position.set(2600, 500, 2600);
  141. camera.up = new THREE.Vector3(0, 1, 0);
  142. camera.lookAt(new THREE.Vector3(0, 500, 0));
  143.  
  144. var i = 0;
  145. for (var ix = 0; ix < AMOUNTX; ix++) {
  146. for (var iy = 0; iy < AMOUNTY; iy++) {
  147. particle = particles[i++];
  148. particle.position.y = (Math.sin((ix + count) * 0.2) * 500) +
  149. (Math.sin((iy + count) * 0.2) * 500);
  150. particle.scale.y = (Math.sin((ix + count) * 0.3) + 1) * 3 +
  151. (Math.sin((iy + count) * 0.3) + 1) * 3;
  152. particle.scale.x = (Math.sin((ix + count) * 0.3) + 1) * 3 +
  153. (Math.sin((iy + count) * 0.3) + 1) * 3;
  154. }
  155. scene.children[2].translateY(Math.cos(ix + count/2)*5);
  156. }
  157. //模型旋转
  158. scene.children[2].rotateY(Math.PI/180);
  159. camera.position.x = 2600*Math.cos(Math.PI/180*rad);
  160. camera.position.z = -2600*Math.sin(Math.PI/180*rad);
  161. //点光源位置
  162. scene.children[0].position.x = 1200*Math.cos(Math.PI/180*rad+Math.PI*0.1);
  163. scene.children[0].position.z = -1200*Math.sin(Math.PI/180*rad+Math.PI*0.1);
  164.  
  165. controls.update();
  166. renderer.render(scene, camera);
  167. count += 0.1;
  168. rad += 0.2;
  169. }
  170.  
  171. function animate() {
  172. requestAnimationFrame(animate);
  173. render();
  174. pickUp();
  175. }
  176.  
  177. init();
  178. animate();
  179. </script>
  180. </html>

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

ThreeJS实现波纹粒子效果的更多相关文章

  1. 超炫的HTML5粒子效果进度条 VS 如何规范而优雅地code

    最近瞎逛的时候发现了一个超炫的粒子进度效果,有多炫呢?请擦亮眼镜!   // _this.ch){ _this.particles.splice(i, 1); } }; this.Particle.p ...

  2. 简直要逆天!超炫的 HTML5 粒子效果进度条

    我喜欢粒子效果作品,特别是那些能够应用于实际的,例如这个由 Jack Rugile 基于 HTML5 Cavnas 编写的进度条效果.看着这么炫的 Loading 效果,即使让我多等一会也无妨:)你呢 ...

  3. CodePen 作品秀:Canvas 粒子效果文本动画

    作品名称——Shape Shifter,基于 Canvas 的粒子图形变换实验.在页面下方的输入框输入文本,上面就会进行变换出对应的粒子效果文本动画. CodePen 作品秀系列向大家展示来自 Cod ...

  4. iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

    一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // re ...

  5. 能产生粒子效果的CAEmitterLayer

    能产生粒子效果的CAEmitterLayer 下雪效果: // // RootViewController.m // Cell // // Copyright (c) 2014年 Y.X. All r ...

  6. cocos基础教程(8)粒子效果

    简介 粒子系统是指计算机图形学中模拟特定现象的技术,它在模仿自然现象.物理现象及空间扭曲上具备得天独厚的优势,为我们实现一些真实自然而又带有随机性的特效(如爆炸.烟花.水流)提供了方便. 粒子属性 一 ...

  7. 用仿ActionScript的语法来编写html5——第八篇,图片处理+粒子效果

    用仿ActionScript的语法来编写html5系列开发到现在,应该可以做出一些东西了,下面先来研究下图片的各种效果预览各种效果看下图效果和代码看这里,看不到效果的请下载支持html5的浏览器 ht ...

  8. iOS 开发之粒子效果

    本文由糖炒小虾.Benna翻译 ,校对:sai.u0u0.iven.子龙山人 iOS 5中的UIKit粒子系统教程 Ray的话:这是第15篇.也是最后一篇<iOS 5 盛宴>中的iOS 5 ...

  9. cocos2d粒子效果

    第9章 粒子效果 游戏开发者通常使用粒子系统来制作视觉特效.粒子系统能够发射大量细小的粒子并对他们进行渲染,而且效率要远高于渲染同样数目的精灵.粒子系统可以模拟下雨.火焰.雪.爆炸.蒸气拖尾以及其他多 ...

随机推荐

  1. 【Jenkins持续集成】好用的插件集合

    1. Promoted Builds Plugin 这个插件在job构建成功后,依据设置条件(仅手动执行/成功时执行等),执行操作(操作和构建过程基本类似),这样我们就可以在构建之后有机会执行拉分支. ...

  2. 关于前端惰性加载(jquery_lazyload)的使用和原理分析

    1.前言 有时我们会有这样的需求,当网页有很多张图片的时候,我们不希望一次性就把图片加载完,而是希望当浏览器滑动到指定位置的时候再加载,这样可以节省带宽,它也能帮助减轻服务器负载.那么这种需求就需要利 ...

  3. BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  4. 也谈SpringCloud:假如 《复仇者联盟4》是一个微服务

    前言   <复仇者联盟4>(下文<妇联4>) 将于4月24号上映了,漫威迷们是不是迫不及待了.我虽然不是漫威迷,没有看过相关漫画,但是电影确实一步都不落.不过我在想一个问题:假 ...

  5. composer设置国内镜像

    使用composer时,输入命令执行后半天没有反应,并最后是失败的消息. 如下载项目中的框架文件时: composer install 一直没有反应 [注]添加参数-vvv可尽可能多的输出执行信息,帮 ...

  6. 动态验证码处理UI自动化获取处理

    解决思路两种:1.直接linux catalina.out读取:一分每10s轮询出现新的直接读取返回<br>2.缓存注入cookie,先手动登录获取session 然后通过注入user,p ...

  7. 使用CSS3的“transition ”属性控制长宽度的缓慢变化

    有时候我们可能会想要改变某个资源信息的长宽度,比如改变某个div的宽度,而且需要让这个宽度缓慢改变,而不是突然就改变了.这时候你可能会想到使用jquery的animate()函数,不过这个方法既得引用 ...

  8. HDU 2141 Can you find it? (二分)

    题目链接: Can you find it? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/ ...

  9. python 爬虫 发送每天天气

    #!/usr/bin/python# -*- coding: UTF-8 -*-import requests,bs4,smtplib,sysimport smtplib, sysfrom email ...

  10. .Net文档下载

    public static void DownLoadFile(string fileName, HttpResponse Response, HttpServerUtility Server) { ...