本着瞎折腾的学习态度,在闲暇之余就是要搞点奇奇怪怪的事情。文中如有哪不对的地方,还请大家指出。

本文项目github地址:https://github.com/SmallStoneSK/particle-effect

本文原创转载地址:https://blog.csdn.net/u013588817/article/details/78056140


index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Particle 粒子特效</title><style>* {margin: 0;padding: 0;overflow: hidden;}html, body {width: 100%;height: 100%;background-color: #292d35;}</style>
</head>
<body><canvas id="canvas"></canvas><script src="ParticleEffect.js"></script><script>window.onload = function() {ParticleEffect.run();// test();};// 实时获取窗口大小 和 从缓存中获取窗口大小 的性能对比function test() {var cache = {width: 1024, height: 780};function test(executeFunc, times) {var start, end, num = times;start = new Date();while(times--) {executeFunc();}end = new Date();console.log(executeFunc.name + ' executes ' + num + 'times and takes ' + (end.getTime() - start.getTime()) / 1000 + 's.');}function getWindowSizeRealTime() {return {width: window.innerWidth || document.documentElement.clientWidth,height: window.innerHeight || document.documentElement.clientHeight};}function getWindowSizeFromCache() {return cache;}[1000, 10000, 100000, 1000000].forEach(function(times) {test(getWindowSizeRealTime, times);test(getWindowSizeFromCache, times);});}</script>
</body>
</html>

ParticleEffect.js

// 粒子特效
var ParticleEffect = {ctx: null,canvas: null,particles: [],mouseCoordinates: {x: 0, y: 0},config: {id: 'canvas',                   //count: 100,                     // 默认创建粒子数量radius: 1,                      // 默认粒子半径vxRange: [-1, 1],               // 默认粒子横向移动速度范围vyRange: [-1, 1],               // 默认粒子纵向移动速度范围scaleRange: [.5, 1],            // 默认粒子缩放比例范围lineLenThreshold: 125,          // 默认连线长度阈值color: 'rgba(255,255,255,.2)'   // 默认粒子、线条的颜色},init: function(newConfig) {// 更新config配置newConfig && Object.keys(newConfig).forEach(function(key) {_this.config[key] = newConfig[key];});var _this = this;this.canvas = document.getElementById(this.config.id);this.ctx = this.canvas.getContext('2d');// 只有在浏览器支持canvas的情况下才有效if(this.ctx) {Utils.updateWindowSize();var windowSize = Utils.getWindowSize();// 设置canvas宽高this.canvas.width = windowSize.width;this.canvas.height = windowSize.height;// 生成粒子var times = this.config.count;this.particles = [];while(times--) {this.particles.push(new Particle({x: Utils.rangeRandom(this.config.radius, windowSize.width - this.config.radius),y: Utils.rangeRandom(this.config.radius, windowSize.height - this.config.radius),vx: Utils.rangeRandom(this.config.vxRange[0], this.config.vxRange[1]),vy: Utils.rangeRandom(this.config.vyRange[0], this.config.vyRange[1]),color: this.config.color,scale: Utils.rangeRandom(this.config.scaleRange[0], this.config.scaleRange[1]),radius: this.config.radius}));}// 监听鼠标的mouseMove事件,记录下鼠标的x,y坐标window.addEventListener('mousemove', this.handleMouseMove.bind(this), false);// 监听窗口大小改变事件window.addEventListener('resize', this.handleWindowResize.bind(this), false);// 兼容requestAnimationFrameUtils.supportRequestAnimationFrame();window.requestAnimationFrame(this.draw.bind(this));}},move: function() {var windowSize = Utils.getWindowSize();this.particles.forEach(function(item) {// 更新粒子坐标item.x += item.vx;item.y += item.vy;// 如果粒子碰到了左墙壁或右墙壁,则改变粒子的横向运动方向if((item.x - item.radius < 0) || (item.x + item.radius > windowSize.width)) {item.vx *= -1;}// 如果粒子碰到了上墙壁或下墙壁,则改变粒子的纵向运动方向if((item.y - item.radius < 0) || (item.y + item.radius > windowSize.height)) {item.vy *= -1;}});},draw: function() {var _this = this;var lineLenThreshold = this.config.lineLenThreshold;var windowSize = Utils.getWindowSize();// 每次重新绘制之前,需要先清空画布,把上一次的内容清空this.ctx.clearRect(0, 0, windowSize.width, windowSize.height);// 绘制粒子this.particles.forEach(function(item) {item.draw(_this.ctx);});// 绘制粒子之间的连线for(var i = 0; i < this.particles.length; i++) {for(var j = i + 1; j < this.particles.length; j++) {var distance = Math.sqrt(Math.pow(this.particles[i].x - this.particles[j].x, 2) + Math.pow(this.particles[i].y - this.particles[j].y, 2));if(distance < lineLenThreshold) {// 这里我们让距离远的线透明度淡一点,距离近的线透明度深一点this.ctx.strokeStyle = this.translateColors(this.config.color, (1 - distance / lineLenThreshold));this.ctx.beginPath();this.ctx.moveTo(this.particles[i].x, this.particles[i].y);this.ctx.lineTo(this.particles[j].x, this.particles[j].y);this.ctx.closePath();this.ctx.stroke();}}}// 绘制粒子和鼠标之间的连线for(i = 0; i < this.particles.length; i++) {distance = Math.sqrt(Math.pow(this.particles[i].x - this.mouseCoordinates.x, 2) + Math.pow(this.particles[i].y - this.mouseCoordinates.y, 2));if(distance < lineLenThreshold) {this.ctx.strokeStyle = this.translateColors(this.config.color, (1 - distance / lineLenThreshold));this.ctx.beginPath();this.ctx.moveTo(this.particles[i].x, this.particles[i].y);this.ctx.lineTo(this.mouseCoordinates.x, this.mouseCoordinates.y);this.ctx.closePath();this.ctx.stroke();}}// 粒子移动,更新相应的x, y坐标this.move();// 循环调用draw方法window.requestAnimationFrame(this.draw.bind(this));},handleMouseMove: function(event) {var x, y;event = event || window.event;if(event.pageX || event.pageY) {x = event.pageX;y = event.pageY;} else {x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;}this.mouseCoordinates = {x: x, y: y};},handleWindowResize: function() {Utils.updateWindowSize();var windowSize = Utils.getWindowSize();this.canvas.width = windowSize.width;this.canvas.height = windowSize.height;},translateColors: function(colorStr, ratio) {var r, g, b, a = 1, colorValues;if(colorStr[0] === '#') {                   // 传的是#RRGGBB形式r = parseInt(colorStr.slice(1, 3), 16);g = parseInt(colorStr.slice(3, 5), 16);b = parseInt(colorStr.slice(5, 7), 16);} else if(colorStr.startsWith('rgb(')) {     // 传的是rgb(r,g,b)形式colorStr = colorStr.slice(4, colorStr.length - 1);colorValues = colorStr.split(',');r = parseInt(colorValues[0].trim());g = parseInt(colorValues[1].trim());b = parseInt(colorValues[2].trim());} else if(colorStr.startsWith('rgba(')) {    // 传的是rgba(r,g,b,a)形式colorStr = colorStr.slice(5, colorStr.length - 1);colorValues = colorStr.split(',');r = parseInt(colorValues[0].trim());g = parseInt(colorValues[1].trim());b = parseInt(colorValues[2].trim());a = parseFloat(colorValues[3].trim());}return 'rgba(' + r + ',' + g + ',' + b + ',' + a * ratio + ')';},run: function(config) {this.init(config);}
};/*** Particle 粒子类*/
function Particle(attr) {// 粒子属性this.x = attr.x;            // 粒子在画布中的横坐标this.y = attr.y;            // 粒子在画布中的纵坐标this.vx = attr.vx;          // 粒子的横向运动速度this.vy = attr.vy;          // 粒子的纵向运动速度this.color = attr.color;    // 粒子的颜色this.scale = attr.scale;    // 粒子的缩放比例this.radius = attr.radius;  // 粒子的半径大小// 绘制方法if(typeof Particle.prototype.draw === 'undefined') {Particle.prototype.draw = function(ctx) {// canvas画圆方法ctx.beginPath();ctx.fillStyle = this.color;ctx.strokeStyle = this.color;ctx.arc(this.x, this.y, this.radius * this.scale, 0, 2 * Math.PI, false);ctx.closePath();ctx.fill();}}
}// 工具
var Utils = {_windowSize: {width: 0,height: 0},getWindowSize: function() {return this._windowSize;},updateWindowSize: function() {this._windowSize.width = this.getWindowWidth();this._windowSize.height = this.getWindowHeight();},getWindowWidth: function() {return window.innerWidth || document.documentElement.clientWidth;},getWindowHeight: function() {return window.innerHeight || document.documentElement.clientHeight;},rangeRandom: function(min, max) {const diff = max - min;return min + Math.random() * diff;},supportRequestAnimationFrame: function() {if(!window.requestAnimationFrame) {window.requestAnimationFrame = (window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame ||window.oRequestAnimationFrame ||window.msRequestAnimationFrame ||function (callback) {setInterval(callback, 1000 / 60)});}}
};

手把手教你系列 - Particle粒子特效(完整代码部分)相关推荐

  1. 手把手教你系列 - Particle粒子特效(上)

    本着瞎折腾的学习态度,在闲暇之余就是要搞点奇奇怪怪的事情.文中如有哪不对的地方,还请大家指出.本文项目github地址:https://github.com/SmallStoneSK/particle ...

  2. 用java写2468游戏_自己写游戏——东渡教你用Java编写2048完整代码

    原标题:自己写游戏--东渡教你用Java编写2048完整代码 2048作为一款益智类的小游戏,相信很多人都玩过,小编今天就教教大家怎么用Java代码给它完美重现,下面是用eclipse开发的2048完 ...

  3. 手把手教你制作一个带特效的全景图片

    一个好的产品才会令人印象深刻,全景图也是这样.这篇文章教你制作一个带特效的全景图片,让你的全景图片"靓"起来. 第一步.准备一张2:1的全景图片.如果不知道全景图是怎么制作的话,可 ...

  4. html如何设置图片循环旋转动画效果,如何使用css3实现图片自动旋转的特效(完整代码)...

    在介绍如何使用css3实现旋转图片特效的基础上,重点介绍了具体的步骤.这篇论文内容紧凑,希望大家能有所收获. 在浏览网页的过程中,你会遇到一种特殊的效果,叫做图片旋转:不同的图片会根据时间的变化在同一 ...

  5. 手把手教你使用curl2py自动构造爬虫代码并进行网络爬虫

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 白头搔更短,浑欲不胜簪. 大家好, ...

  6. AST实战|手把手教你还原ob混淆:ob混淆代码特征

    ob混淆过的代码有那些特征? 特征一: 大数组 + 移位自执行函数 + 解密字符串函数. 下面的代码是一个之前我在官网上混淆的一个例子: ‍ 可以看到,大数组为变量 _0x33fc,移位自执行函数体比 ...

  7. python selenium右键另存为_手把手教你系列练习篇之1python+ selenium自动化测试(详细教程)...

    1.简介 相信各位小伙伴或者同学们通过前面已经介绍了的Python+Selenium基础篇,通过前面几篇文章的介绍和练习,Selenium+Python的webUI自动化测试算是 一只脚已经迈入这个门 ...

  8. 手把手教你系列 - RN如何实现一个ExpandableList(可展开列表)组件

    看到一篇功能强大的博文转载下来慢慢品味 转载地址:https://blog.csdn.net/u013588817/article/details/78369331?locationNum=8& ...

  9. 50行代码教AI实现动作平衡 | 附完整代码

    作者 | Mike Shi 译者 | linstancy 责编 | Jane 出品 | AI科技大本营(id:rgznai100) [导读]本文将为大家展示如何通过 Numpy 库和 50行 Pyth ...

最新文章

  1. 科学互驳:大脑细胞活到老,长到老?
  2. 漂亮好用的ASP.NET图表控件 免费的
  3. python tqdm包_python tqdm库的使用
  4. 腾讯发布全球首个面向移动端的VVC标准视频解码器,手机即可看4K超高清VVC视频...
  5. cmd运行php文件以及环境配置出现的问题、 php.exe不是内部或外部命令,也不是可运行的程序 或批处理文件、PHP startup: Unable to load dynamic library
  6. 力算未来丨一张图看懂华为“鲲鹏+昇腾”双引擎
  7. HTML前端开发之路——Transition
  8. sql server insert 锁表_SQL Server的insert执行的秘密(下) 带外键的insert分析
  9. 语音识别结合应用场景 各位大咖也有一些精彩论点
  10. 教你炒股票15:没有趋势,没有背驰
  11. 201771010112罗松《面向对象程序设计(java)》第六周学习总结
  12. 一些情况及问题的说明
  13. c语言中shift f12组合建,C++学习1-(C语言基础、VS快捷键)
  14. 华为emui10.0系统是鸿蒙吗,暂时忘记鸿蒙!华为EMUI 10.0发布时间确认:这才是主角...
  15. 机器学习预测机动车摇号:神秘的第七位
  16. windows企微应用双开/多开
  17. linux查看hive账户权限,Linux用户和权限管理
  18. VR旅游应用案例解析,世界那么大用VR去看看!
  19. 《赢在用户-Web人物角色创建和应用实践指南》
  20. 破窗效应(Break Pane Law)

热门文章

  1. 盘点 | 2023年最值得学的编程语言TOP 5,Python再度夺冠!
  2. ERP系统一般业务流程
  3. 【嵌入式算法】空间向量夹角公式及其应用
  4. 自学B站小甲鱼数据结构课程-C语言实现基础数据结构-栈-的例子
  5. 软件流程和管理(二):SDLCs — Process Formal
  6. 谁该承担中国SaaS贫瘠生态的一点责任
  7. 四川农业大学计算机专业课程资料
  8. 如何把项目上传到码云平台?
  9. 北大c语言百度云资源,北大C语言讲义.pdf
  10. 百度地图在地图上添加多个点,并调整地图层级及中心点至合适位置大小