1.此模块是未完成品,希望广大程序员能够帮我指出该怎么改写一下以满足我的需求,我想要做的是音频可视化的粒子特效模块可以绑定到指定的区域中,但是现在受限于自身的数学水平,实在是没招了,以下贡献出我的所有代码,希望有大佬可以指出该怎么改写可以满足我的要求。
现在主要BUG:每个粒子生成后他的移动角度是全随机,我希望可以做成围绕大圆发散的移动角度,也就是说如果把这个大圆的中点作为直角坐标系的原点我希望在第一象限的粒子只会往第一象限移动,其他以此类推。。
2.代码
class cirlular{
constructor(mycanvas, _this) {
const ctx = uni.createCanvasContext(mycanvas);
this.ctx = ctx;
let height = 0;
let width = 0;
this.radius = 100; // 大圆的半径
// 圆粒子所在位置以及移动方位
this.circleArray = [];
const query = uni.createSelectorQuery().in(_this);
query.select('#particleCanvas').fields({ node: true, size: true }).exec((res) => {
height = res[0].height;
width = res[0].width;
})
this.height = height;
this.width = width;
this.numParticles = 3000; // 初始小粒子的数量
this.initParticles();
this.initdraw();
}
/**
* 渲染画面
* @param {}
* @return {*}
*/
initdraw() {
this.ctx.draw(true);
}
// 初始化粒子
initParticles() {
const centerX = this.width / 2;
const centerY = this.height / 2;
const angleIncrement = (2 * Math.PI) / this.numParticles; // 每个小粒子之间的角度增量
this.ctx.arc(centerX, centerY, this.radius, 0, 2 * Math.PI);
this.ctx.setFillStyle('#ffffff');
this.ctx.fill();
for (let i = 0; i < this.numParticles; i++) {
const angle = i * angleIncrement; // 计算当前小粒子的角度
const x = centerX + this.radius * Math.cos(angle); // 计算小粒子的X坐标
const y = centerY + this.radius * Math.sin(angle); // 计算小粒子的Y坐标
// 初始化小粒子,包括位置、速度、透明度、生命周期等信息
const particle = {
x: x,
y: y,
dx: Math.random() * 2 - 1, // 随机X轴的速度
dy: Math.random() * 2 - 1, // 随机Y轴的速度
opacity: 1, // 初始透明度
lifespan: Math.floor(Math.random() * 100), // 随机生命周期
};
this.circleArray.push(particle);
}
}
// 更新和渲染粒子
updateAndRenderParticles() {
for (let i = this.circleArray.length - 1; i >= 0; i--) {
const particle = this.circleArray[i];
particle.x += particle.dx;
particle.y += -particle.dy;
particle.opacity -= 0.01; // 透明度逐渐减小
particle.lifespan--;
if (particle.opacity <= 0 || particle.lifespan <= 0) {
// 如果透明度为0或生命周期结束,从数组中移除粒子
this.circleArray.splice(i, 1);
// 添加新的粒子在起始位置,继续运动
this.addNewParticle();
} else {
// 绘制小粒子
this.ctx.beginPath();
this.ctx.arc(particle.x, particle.y, 0.3, 0, 2 * Math.PI);
this.ctx.setFillStyle(`rgba(255, 0, 0, ${particle.opacity})`);
this.ctx.fill();
}
}
}
// 添加新的粒子在起始位置,继续运动
addNewParticle() {
const centerX = this.width / 2;
const centerY = this.height / 2;
// const radius = 60; // 大圆的半径
const angle = Math.random() * (2 * Math.PI); // 随机角度
const x = centerX + this.radius * Math.cos(angle); // 计算小粒子的X坐标
const y = centerY + this.radius * Math.sin(angle); // 计算小粒子的Y坐标
// 1 , -1 右下 1 ,1 右上 -1 ,-1 左下 -1 ,1 左上
const newParticle = {
x: x,
y: y,
dx: Math.random() * 2 - 1 , // 随机X轴的速度 ,可能是要这里修改一下
// dx: -1,
dy: Math.random() * 2 - 1 , // 随机Y轴的速度,还有这里,但是实在不懂怎么改
// dy: 1,
opacity: 1, // 初始透明度
lifespan: Math.floor(Math.random() * 100), // 随机生命周期
};
this.circleArray.push(newParticle);
}
// 主循环
startAnimation() {
this.animationInterval = setInterval(() => {
this.ctx.clearRect(0, 0, this.width, this.height);
this.updateAndRenderParticles();
this.ctx.draw();
}, 20); // 16毫秒对应约60帧每秒
}
}
module.exports = cirlular;