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

如何用HTML、JavaScript、p5.js实现霉菌状晃动扩散文字效果?

需求与问题描述

我想用HTML、JavaScript和p5.js实现文字霉菌/细胞式晃动+扩散效果——文字边缘像霉菌生长一样不规则晃动,同时有逐渐扩散的视觉表现。我不清楚这类效果的具体名称,尝试了自己写的p5.js代码,但没达到预期,希望得到实现建议;如果原效果难度太高,类似的替代方案也可以接受。

附尝试的p5.js代码:

<!DOCTYPE html>
<html>
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
</head>
<body>
    <script>
        const MAX = 1000;
        let particles = [];
        let list = [];
        let axis;
        let count = 0;
        let typedText = 'Macro';
        let inputText = [];
        let graphics;
        function setup() {
            createCanvas(1200, 600);
            colorMode(RGB, 255, 255, 255);
            frameRate(30);
            noStroke();
            noCursor();
            graphics = createGraphics(width, height);
            graphics.textFont("Arial", 300);
            graphics.fill(0);
            graphics.textAlign(CENTER, CENTER);
            graphics.text(typedText, width / 2, height / 2 - 70);
            typedText = "";
            inputText = [];
            count = 0;
            list = new Array(width * height);
            graphics.loadPixels();
            for(let y = 0; y <= height - 1; y++) {
                for(let x = 0; x <= width - 1; x++) {
                    let index = (x + y * graphics.width) * 4;
                    if(graphics.pixels[index] < 128) {
                        list[y * width + x] = 0;
                    } else {
                        list[y * width + x] = 1;
                    }
                }
            }
            graphics.updatePixels();
            particles = [];
        }
        function draw() {
            if (count < MAX) {
                let i = 0;
                while(i < 3) {
                    axis = createVector(int(random(100, width - 300)), int(random(100, height - 300)));
                    if(list[int(axis.y * width + axis.x)] == 0) {
                        particles.push(new Particle(axis.x, axis.y));
                        i++;
                        count++;
                    }
                }
            }
            background(239);
            for (let i = 0; i < particles.length; i++) {
                let p = particles[i];
                fill(20);
                p.display();
                p.update();
            }
        }
        function keyReleased() {
            if (keyCode == ENTER) {
                typedText = inputText.join('');
                setup();
            } else {
                inputText.push(key);
            }
        }
        class Particle {
            constructor(x, y) {
                this.location = createVector(x, y);
                this.velocity = createVector(0, 0);
                this.scale = random(0.35, 0.9);
                this.radius = this.scale * 45;
                this.border = 15;
            }
            update() {
                let noiseX = noise(this.location.x * 0.005, this.location.y * 0.005);
                let noiseY = noise(this.location.y * 0.005, this.location.x * 0.005);
                this.velocity.x = map(noiseX, 0, 1, -0.5, 0.5);
                this.velocity.y = map(noiseY, 0, 1, -0.5, 0.5);
                this.location.add(this.velocity);
                // Check if the particle is out of the text area
                if(list[int((this.location.y + this.velocity.y) * width + int(this.location.x + this.velocity.x))] == 1) {
                    this.velocity.mult(-1);
                }
            }
            display() {
                ellipse(this.location.x, this.location.y, this.radius, this.radius);
            }
        }
    </script>
</body>
</html>
实现建议与改进方案

一、现有代码的核心问题

你的代码用粒子模拟文字区域,但离目标效果有两个关键差距:

  • 粒子仅在文字内部随机生成,没有沿文字边缘扩散生长的逻辑,无法体现霉菌/细胞的蔓延感
  • 粒子的运动是全局噪声驱动,没有和文字轮廓绑定,缺少“附着在文字上晃动”的视觉关联

二、针对性改进方案(贴合原效果)

1. 提取文字边缘的种子点

放弃随机生成粒子,改为从文字轮廓的边缘像素提取初始粒子:

  • 在setup()的像素遍历阶段,只标记文字边缘像素(即周围有空白像素的文字区域像素)作为粒子生成点
  • 可以通过检测当前像素上下左右是否有list值为1(空白)的像素来判断边缘

2. 让粒子沿边缘“扩散生长”

修改粒子生成逻辑:

  • 初始只在文字边缘生成少量粒子
  • 每帧让部分粒子在自身周围(文字内部)生成新的子粒子,模拟霉菌繁殖扩散
  • 给子粒子添加生长延迟,让扩散有先后顺序,更自然

3. 绑定晃动效果到文字轮廓

调整粒子运动逻辑:

  • 粒子的噪声运动范围限制在文字内部,且靠近边缘的粒子晃动幅度更大(模拟边缘的不规则蠕动)
  • 可以给粒子添加“向文字内部/边缘偏移”的微小力,避免粒子乱跑

三、简化替代方案(快速实现类似效果)

如果觉得粒子扩散逻辑太复杂,可以用噪声扰动文字轮廓的方式快速实现:

  1. 在setup()中生成文字的像素蒙版
  2. 每帧绘制文字时,对每个文字像素的位置添加Perlin噪声偏移:
function draw() {
  background(239);
  graphics.loadPixels();
  for(let y=0; y<height; y++) {
    for(let x=0; x<width; x++) {
      let idx = (x + y*width)*4;
      if(graphics.pixels[idx] < 128) {
        // 添加噪声偏移
        let offsetX = noise(x*0.02, y*0.02, frameCount*0.01)*10 -5;
        let offsetY = noise(x*0.02+100, y*0.02, frameCount*0.01)*10 -5;
        fill(20);
        rect(x+offsetX, y+offsetY, 1, 1);
      }
    }
  }
}
  1. 对边缘像素加大偏移量,内部像素减小偏移,模拟晃动+局部扩散的视觉效果

四、关键技巧总结

  • 用Perlin噪声实现自然的随机晃动,通过frameCount作为噪声第三个参数实现动画
  • 文字蒙版是核心,所有效果都要基于蒙版判断文字区域/边缘
  • 扩散效果可以通过“粒子繁殖”或“边缘像素逐步向外扩张”实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:24:53