超解压,实现粒子的万有引力与斥力效果

简介: 超解压,实现粒子的万有引力与斥力效果

前言


前面小包实现一个使用粒子构成 “战场小包” 文字炫酷效果,给小包打开粒子世界的大门,粒子世界真的是炫酷,简单的组合变换可以产生超多炫彩效果,今天小包带大家实现粒子的吸力与斥力效果,可以试玩一下,超级解压和快乐。


体验地址: 粒子万有引力与斥力


实现粒子


首先来实现全屏随机粒子分布,本文章共生成 2500 个粒子,位置 (x,y) 通过随机数生成,粒子形状通过 fillRect 绘制。


// 创建粒子类
class Particle {
  constructor() {
    // rand 是封装的生成 (n,m) 之间随机数的函数
    // x, y 粒子位置
    this.x = rand(0, canvas.width);
    this.y = rand(0, canvas.height);
    // vx, vy 粒子在x, y 轴的移动速度
    this.vx = rand(-1, 1);
    this.vy = rand(-1, 1);
    // 粒子大小
    this.r = rand(1, 3);
    // 粒子颜色
    this.col = `rgba(${Math.round(rand(150, 200))}, ${Math.round(
      rand(100, 255)
    )}, ${Math.round(rand(180, 255))},${Math.random() + 0.2})`;
  }
}
// 生成粒子
function initParticle() {
    for (var i = 0; i < part_num; i++) {
      P.push(new Particle());
    }
}
复制代码


image.png

满屏幕的粒子生成之后,接下来就来做粒子的效果吧。


万有引力效果


要实现万有引力效果,首先需要一个引力中心,初始位置为中心位置,当鼠标开始移动时,鼠标位置为引力中心。为了看起来更明显,通过 canvas 在引力中心处绘制一个十字架。


// X, Y 为引力中心位置
// X, Y 初始化
X = window.innerWidth / 2;
Y = window.innerHeight / 2;
// 绘制十字架
ctx.beginPath();
ctx.moveTo(X, Y - 10);
ctx.lineTo(X, Y + 10);
ctx.moveTo(X - 10, Y);
ctx.lineTo(X + 10, Y);
ctx.stroke();
// 移动鼠标时,修改引力中心位置
window.onmousemove = function (e) {
    X = e.clientX;
    Y = e.clientY;
};
复制代码


引力中心确定后,规定粒子移动方式为沿半径向引力中心靠近,越近速度越快。初始化粒子时,提供 vx,vy 属性为粒子分别沿 x,y 轴移动的速度,因此可以通过修改 vx,vy 属性使粒子不断接近引力中心。


在实现上述效果之前,先来复习一下三角函数的知识:


image.png

从上面图中可以得出,r*cos, r*sinr 分别在 x,y 轴上的投影,如果将 r 换成非常微小的长度,r*cos, r*sin 即为单位时间内粒子在 x,y 轴上即将移动的距离,也就是速度 vx,vy 。因此我们需要求解出粒子到引力中心的角度 angle


var dx = p.x - X, // 水平距离
    dy = p.y - Y, // 垂直距离
    dist = Math.sqrt(dx * dx + dy * dy), // 到引力中心的距离
    angle = Math.atan2(dy, dx); // 角度
复制代码


前端中的坐标系与数学中坐标系略有差异,x 轴正方向相同,但 y 轴正方向向下,各个象限的余弦与正弦大小如下:


image.png

复习完上面知识后,接下来就可以计算粒子移动方式了。(粒子越靠近引力中心速度越快)

在坐标系中取三个粒子,我们来实际演练一下:


image.png

粒子 cos/sin dx/dy len*cos/len*sin
A 正/负 正/负 正/负
C 负/负 负/负 负/负
D 正/正 正/正 正/正


dxdy 分别为粒子距离引力中心的长度在 x,y 轴上的投影,存在正负值,例如点 A ,dxA > 0, dyA < 0 ,因此如果粒子 A 想靠近引力中心 B ,需设置 vx < 0, vy > 0 ,来减少 A 与 B 之间的距离。


从表格中我们可以得知, len*coslen*sin 正好与 dxdy 同号,因此设置 -len*cos-len*sin 为粒子粒子的移动速度,就能使粒子 A 不断靠近引力中心 B(len 为任意长度)


// 粒子越靠近引力中心,dist越小,一方面可以保证粒子速度越来越快,另一方面也达成len不断修改的要求
p.vx -= (20 / (p.r * dist)) * Math.cos(angle);
p.vy -= (20 / (p.r * dist)) * Math.sin(angle);
p.x += p.vx;
p.y += p.vy;
复制代码


image.png

斥力效果


如果光有引力效果,耍一会大部分粒子都被吸引到中间,显得四周空空旷旷的,玩久了也有几分单调。那咱们就给添加个排斥效果,有吸力,有斥力,效果齐活了。


斥力效果的效果为点击鼠标,粒子沿圆形往四周扩散,为保证扩散效率,设置大扩散半径


有了引力的实现基础,粒子向四周只需保证 len*coslen*sin 正好与 dxdy 同号即可。


p.vx += (250 / (p.r * dist)) * Math.cos(angle);
p.vy += (250 / (p.r * dist)) * Math.sin(angle);
复制代码


image.png


粒子的斥力效果是不是很解压,但也能发现一个比较明显的问题,很多粒子被排斥到页面之外,页面中的粒子越来越少了,这可不好玩啊,因此添加对边界处理逻辑。


边界处理


边界处理逻辑不难实现,当粒子到达边界时,例如碰到垂直方向的上边界,那么意味着粒子的 vy 是负值,修改其为异号,那么粒子就可以反弹回来,其余方向处理类似。


function bounce(b) {
  // 左边界
  if (b.x < b.r) {
    b.x = b.r;
    b.vx *= -1;
  }
  // 右边界
  if (b.x > canvas.width - b.r) {
    b.x = canvas.width - b.r;
    b.vx *= -1;
  }
  // 上边界
  if (b.y - b.r < 0) {
    b.y = b.r;
    b.vy *= -1;
  }
  // 下边界
  if (b.y > canvas.height - b.r) {
    b.y = canvas.height - b.r;
    b.vy *= -1;
  }
}
复制代码

image.png

源码仓库


源码地址: 粒子的万有引力与斥力


体验地址: 粒子的万有引力与斥力


如果感觉有帮助的话,别忘了给小包点个 ⭐ 。




相关文章
|
Cloud Native 架构师 Java
谷歌架构师分享gRPC与云原生应用开发Go和Java为例文档
随着微服务和云原生相关技术的发展,应用程序的架构模式已从传统的单体架构或分层架构转向了分布式的计算架构。尽管分布式架构本身有一定的开发成本和运维成本,但它所带来的收益是显而易见的。
|
2月前
|
JavaScript Java 关系型数据库
基于springboot的图书馆座位预约系统
针对高校图书馆座位紧张与管理低效问题,本研究设计并实现了一套基于Spring Boot、Vue.js与MySQL的智能预约系统。系统通过移动端实现座位实时查询、预约、签到及违规管理,提升资源利用率与用户体验。采用Java语言开发,结合前后端分离架构,支持高并发访问,解决传统人工管理排队久、监管难等问题。对比国内外现有方案,本系统在智能化分配、稳定性与可扩展性方面更具优势,助力智慧校园建设,具有良好的应用推广价值。
|
3月前
|
人工智能 自然语言处理 安全
AI助教系统:基于大模型与智能体架构的新一代教育技术引擎
AI助教系统融合大语言模型、教育知识图谱、多模态交互与智能体架构,实现精准学情诊断、个性化辅导与主动教学。支持图文语音输入,本地化部署保障隐私,重构“教、学、评、辅”全链路,推动因材施教落地,助力教育数字化转型。(238字)
|
7月前
|
算法 安全 Java
2025 校招必看:Java 开发面试核心知识点深度解析及最新笔面试题汇总
本文针对2025校招Java开发面试,系统梳理了Java基础、集合框架、多线程并发、JVM等核心知识点,并附带最新笔面试题。内容涵盖封装、继承、多态、异常处理、集合类使用、线程同步机制、JVM内存模型及垃圾回收算法等。同时深入探讨Spring、数据库(MySQL索引优化、Redis持久化)、分布式系统(CAP理论、分布式事务)等相关知识。通过理论结合实例解析,帮助考生全面掌握面试要点,提升实战能力,为成功拿下Offer奠定坚实基础。
759 3
|
监控 数据可视化 数据挖掘
ERP系统中的销售预测与市场分析
【7月更文挑战第25天】 ERP系统中的销售预测与市场分析
846 2
|
JavaScript
Vue3按钮(Button)
这是一个高度可定制的按钮组件,支持多种属性设置,包括按钮类型、形状、图标、尺寸、背景透明度、波纹颜色、跳转地址、打开方式、禁用状态、加载状态及指示符样式等。预览图展示了不同配置下的按钮样式变化。组件通过Vue实现,并提供了丰富的自定义选项以适应各种场景需求。
936 1
Vue3按钮(Button)
|
Web App开发 搜索推荐 Unix
Linux系统之MobaXterm远程连接centos的GNOME桌面环境
【10月更文挑战第21天】Linux系统之MobaXterm远程连接centos的GNOME桌面环境
2458 5
Linux系统之MobaXterm远程连接centos的GNOME桌面环境
|
XML Java Android开发
Android RecyclerView用代码动态设置item的selector
Android RecyclerView用代码动态设置item的selector
270 0
|
分布式计算 DataWorks 监控
DataWorks操作报错合集之遇到“OSERROR: argument list too long”的错误,该如何处理
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
224 1
|
缓存 小程序 安全
微信PC端小程序无法加载数据
某些小程序在PC端小程序打开会出现白屏或无法加载数据的情况,本篇文章整理了几种常见情况的解决方案。
2165 1

热门文章

最新文章