You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

p5.js音频可视化项目粒子无法在画布正常显示问题求助

p5.js音频可视化粒子异常问题修复方案

首先梳理你代码里存在的核心问题,对应修复即可解决界面冻结、粒子不显示的问题:

问题1:界面冻结的根源

你在draw()函数里每帧都往particles数组新增一个粒子,没有上限控制,运行几秒后数组就会膨胀到上万个元素,渲染压力激增导致界面卡住。

问题2:粒子看不见的核心原因

Particle类的show()方法中fill(random)写法错误:random是p5的方法,需要调用执行返回数值才能作为颜色参数,当前写法等于没有传入有效颜色值,粒子相当于完全透明。

问题3:粒子无发射效果

当前粒子只有初始固定位置,没有速度属性和位置更新逻辑,生成后就固定在原地,不会出现从圆环向外发射的效果。

问题4:其他影响运行的问题

  • 开头的require语句是vscode的本地类型提示代码,在浏览器运行p5项目时需要删除,否则会触发引用报错
  • 波形映射索引逻辑错误:map(i, 0, width, 0 , wave.length-1)中i的取值范围是0到180,却映射了0到画布宽度的范围,会导致索引取值异常,圆环波形显示不准
  • 歌曲暂停时没有关闭循环,依然会每帧新增粒子,加剧卡顿

修复后完整代码

var song
var fft
var img
var particles = []
// 粒子最大数量限制,避免内存溢出
const MAX_PARTICLES = 200

function preload(){
  song = loadSound('Clair de Lune With Rain.mp3')
  img = loadImage('rain.jpg')
}

function setup() {
  createCanvas(windowWidth, windowHeight);
  angleMode(DEGREES)
  imageMode(CENTER)
  img.filter(BLUR, 2)
  fft = new p5.FFT()
  // 初始暂停避免还没点击就生成粒子
  noLoop()
}

function draw() {
  background(0)
  stroke(255)
  strokeWeight(3)
  noFill()

  translate(width/2, height/2)

  image(img, 0, 0, width, height)

  fft.analyze()
  amp = fft.getEnergy(20,200)

  var wave = fft.waveform()

  for (var t = -1; t <= 1; t += 2){
    beginShape()
    for(var i = 0; i <= 180; i+= 0.3){
      // 修正索引映射范围
      var index = floor(map(i, 0, 180, 0, wave.length-1))
      
      var r = map(wave[index], -1, 1, 150, 350)
      
      var x = r*sin(i) * t
      var y = r*cos(i)
      vertex(x,y)
    }
    endShape()
  }

  // 新增粒子前判断数量上限,超出就删除最早的粒子
  if(particles.length < MAX_PARTICLES){
    var p = new Particle(amp)
    particles.push(p)
  }else{
    particles.shift()
  }

  for(var i=0; i<particles.length; i++){
    particles[i].update()
    particles[i].show()
  }

}

function mouseClicked(){
  if (song.isPlaying()){
    song.pause()
    noLoop()
  }
  else{
    song.play()
    loop()
  }
}

class Particle{
  constructor(amp){
    // 初始位置在对应音量的圆环半径上
    this.pos = p5.Vector.random2D().mult(map(amp,0,255,150,350))
    // 初始速度和位置同方向,实现向外发射效果
    this.vel = this.pos.copy().mult(0.005)
    // 透明度参数,实现粒子渐隐效果
    this.alpha = 255
  }

  update(){
    this.pos.add(this.vel)
    this.alpha -= 2
  }

  show(){
    noStroke()
    // 传入有效颜色参数,带透明度
    fill(255, this.alpha)
    ellipse(this.pos.x, this.pos.y, 4)
  }
}

内容的提问来源于stack exchange,提问作者Camille Ragland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:45:04