当前位置: 首页 > news >正文

uniapp中使用canvas和requestAnimationFrame显示粒子动画

实现效果

  1. 在canvas中显示根据帧率(fps)和粒子数量(numbers)生成随机颜色大小以及速度的粒子(particles)。
  2. 帧率和粒子数量可随时更改,更改完后视图也会更新。
  3. 添加开始动画和停止动画按钮。

[video(video-wMeXRCFD-1744358613881)(type-csdn)(url-https://live.csdn.net/v/embed/473194)(image-https://i-blog.csdnimg.cn/img_convert/7d4067546c4c2acdeacb9f3d71416e0c.jpeg)(title-粒子动画效果)]

实现思路

粒子

使用Math.random()获取粒子颜色、大小以及xy轴的速度并存到数组里

// 定义粒子类
function Particle(x, y, speedX, speedY, radius, color) {this.x = x;this.y = y;this.speedX = speedX;this.speedY = speedY;this.radius = radius;this.color = color;
}
// 创建粒子
createParticles() {for (let i = 0; i < this.numbers; i++) {const x = Math.random() * canvas.width;const y = Math.random() * canvas.height;const speedX = Math.random() * 4 - 2;const speedY = Math.random() * 4 - 2;const radius = Math.random() * 5 + 1;const color = this.getRandomColor();this.particles.push(new Particle(x, y, speedX, speedY, radius, color));}
}
// 随机生成颜色
getRandomColor() {const letters = '0123456789ABCDEF';let color = '#';for (let i = 0; i < 6; i++) {color += letters[Math.floor(Math.random() * 16)];}return color;
}

使用ctx.arc方法绘制圆形粒子

// 绘制粒子
Particle.prototype.draw = function() {ctx.beginPath();ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);ctx.fillStyle = this.color;ctx.fill();ctx.closePath();
}

动画

给粒子添加更新位置方法,并在requestAnimationFrame中调用。
根据fps获取没此更新位置的时间,再与当前时间至上一次更新位置的时间差做比较就一块实现随刷新率更新粒子。

// 更新粒子的位置
Particle.prototype.update = function() {this.x += this.speedX;this.y += this.speedY;// 如果粒子超出画布边界,则改变速度方向if (this.x + this.radius < 0 || this.x - this.radius > canvas.width) {this.speedX = -this.speedX;}if (this.y + this.radius < 0 || this.y - this.radius > canvas.height) {this.speedY = -this.speedY;}
}
// 更新粒子位置
updateParticles() {this.particles.forEach((particle) => {particle.update();});
}
// 开始动画
startAnimation() {this.now = this.now || Date.now();if ((Date.now() - this.now) > (1000 / (this.fps || 1))) {this.now = Date.now();this.updateParticles();}this.raf = requestAnimationFrame(this.startAnimation);
}

问题点

  • 点击多次开始动画按钮,需要判断动画是否已经开始
    requestAnimationFrame方法会返回一个id,判断id不存在再调用startAnimation方法就行
  • 改变粒子数量应该初始化再生成粒子数组
    使用watch监听numbers判断是否有动画,有就停止动画。再依次调用重置参数方法,初始化方法,开始动画方法。
  • uniapp的canvas获取不到ctx
    有两种方法:
    第一种,canvas添加属性canvas-id,然后调用uni.createCanvasContext方法就可以创建canvas绘图上下文。
    第二种,直接获取canvas元素的childNodes拿到原生canvas元素再使用getContext。

整体代码

代码重要参数如下

  • canvas - 存储uniapp的canvas元素用以获取宽高等参数
  • ctx - 原生canvas的绘图上下文对象
  • raf - 帧函数的id,用以关闭动画等
  • now - 记录渲染时间
  • fps - 控制每秒渲染次数
  • numbers - 控制粒子数量
  • particles - 存储粒子信息
let canvas = null;
let ctx = null;// 定义粒子类
function Particle(x, y, speedX, speedY, radius, color) {this.x = x;this.y = y;this.speedX = speedX;this.speedY = speedY;this.radius = radius;this.color = color;
}// 更新粒子的位置
Particle.prototype.update = function() {this.x += this.speedX;this.y += this.speedY;// 如果粒子超出画布边界,则改变速度方向if (this.x + this.radius < 0 || this.x - this.radius > canvas.width) {this.speedX = -this.speedX;}if (this.y + this.radius < 0 || this.y - this.radius > canvas.height) {this.speedY = -this.speedY;}
};// 绘制粒子
Particle.prototype.draw = function() {ctx.beginPath();ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);ctx.fillStyle = this.color;ctx.fill();ctx.closePath();
};export default {data() {return {raf: 0, // 帧函数now: 0, // 当前时间fps: 60, // 帧率numbers: 100, // 粒子数量particles: [], // 粒子数组}},watch: {numbers: {handler(newVal) {this.raf && this.stopAnimation()this.reset()this.init()this.startAnimation()}}},mounted() {this.$nextTick(() => {this.init()})},methods: {// 初始化init() {canvas = document.querySelector('#canvasParticles').getBoundingClientRect() //获取 canvas 组件ctx = document.querySelector('#canvasParticles').childNodes[0].getContext('2d') //获取 canvas 绘图上下文this.createParticles();this.drawParticles();},reset() {this.raf = 0this.now = 0this.particles = []},// 创建粒子createParticles() {for (let i = 0; i < this.numbers; i++) {const x = Math.random() * canvas.width;const y = Math.random() * canvas.height;const speedX = Math.random() * 4 - 2;const speedY = Math.random() * 4 - 2;const radius = Math.random() * 5 + 1;const color = this.getRandomColor();this.particles.push(new Particle(x, y, speedX, speedY, radius, color));}},// 更新粒子位置updateParticles() {this.particles.forEach((particle) => {particle.update();});},// 开始动画startAnimation() {this.now = this.now || Date.now();if ((Date.now() - this.now) > (1000 / (this.fps || 1))) {this.now = Date.now();this.updateParticles();}this.raf = requestAnimationFrame(this.startAnimation);},// 绘制粒子drawParticles() {ctx.clearRect(0, 0, canvas.width, canvas.height);this.particles.forEach((particle) => {particle.draw();});requestAnimationFrame(this.drawParticles);},// 停止动画stopAnimation() {cancelAnimationFrame(this.raf);this.raf = 0},// 随机生成颜色getRandomColor() {const letters = '0123456789ABCDEF';let color = '#';for (let i = 0; i < 6; i++) {color += letters[Math.floor(Math.random() * 16)];}return color;},}
}

本来还想把fps最大值设置成屏幕刷新率,但是我在uniapp官网没找到获取屏幕刷新率的方法,如果有大佬找到获取屏幕刷新率的方法还请告知。

http://www.jsqmd.com/news/360549/

相关文章:

  • 基于Matlab的工件测量系统
  • 2026年性价比高的屋面板品牌厂家排名,选购指南来了 - 工业品牌热点
  • 详细介绍:分布式虚拟 Actor 技术在码头生产调度中的应用研究
  • 前端实现速度线
  • 2026年实盘股票配资平台权威榜单:强监管背景下的十大正规安全机构解析 - 资讯焦点
  • 南通诺丁山婚礼艺术中心费用多少,行业口碑排名值得关注 - 工业设备
  • 2026年河北纯碱批发商综合评估与选择指南 - 2026年企业推荐榜
  • 大模型微调后,如何判断它是不是“变聪明”了?这套评估方法论请收好。
  • 康王和海飞丝哪个好?两大酮康唑、二硫化硒品牌对比 - 博客万
  • flv.js使用记录
  • 回森APP客服服务咨询AI流量赋能,重塑智能高效与便捷体验新标杆 - 资讯焦点
  • 上传图片修改透明边距并下载下来
  • 2026年AI分布式推理平台推荐:臻乐尔科技服务有限公司,AI互联/网关/模型调用全场景覆盖 - 品牌推荐官
  • 2026年复卷机专业厂家推荐:苏州富日智能装备有限公司,双轴/分切/全自动复卷机全系供应 - 品牌推荐官
  • 2026年兰州中考/高考冲刺班推荐:领航学校全系覆盖,助力学子升学之路 - 品牌推荐官
  • 高性价比的2+2国际本科院校怎么选择,四川外国语大学是优选 - 工业品网
  • 拒绝沟通碎片化,打造专属的安全深度定制通讯平台
  • SGS实测认证!2026控油蓬松去屑洗发水精品榜第一,头屑油塌全拜拜! - 资讯焦点
  • 媒介宣发效率低?Infoseek 用 AI 重构企业内容传播新路径
  • Agent Loop:大模型 “能做事” 的核心机制
  • 2026年夹管浮筒专业厂家推荐:宁波柏泰塑料科技,多规格/高强度/耐腐蚀浮筒全解析 - 品牌推荐官
  • 2026年美容院加盟品牌怎么选?多品牌经营模型对比分析版 - 资讯焦点
  • 上海地区小型焊工学校推荐,哪家品牌靠谱且口碑好? - myqiye
  • 2026年H型钢国际标准供应商推荐:上海钢贤电子商务英标/欧标/美标/韩标/澳标/日标/俄标/国标H型钢全覆盖 - 品牌推荐官
  • 2026年实盘股票配资平台排名及十大正规安全公司排行榜 - 资讯焦点
  • 2026微型风扇厂家推荐:嘉兴顺电子科技,型号全/规格多/厂家直销,覆盖多场景散热需求 - 品牌推荐官
  • BXMya COM0034 2RCA023019A0004C PCB卡
  • 科研党收藏!更贴合专科生的降AI率网站,千笔AI VS PaperRed
  • NMN哪个牌子口碑产品最好?2026年十大NMN品牌硬核拆解:成分、技术、口碑效果大公开 - 资讯焦点
  • cozykaka 联合日本脊椎科研团队发布亚洲人专用护颈枕,布局睡眠健康市场 - 资讯焦点