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

p5.js Perlin噪声场拖尾效果异常:无法限制拖尾长度

解决粒子拖尾效果的问题

问题核心原因

你使用了WEBGL渲染模式,p5.js在WEBGL下的background()方法逻辑和2D模式不同,直接设置alpha值不会产生叠加半透明的效果。而移除background()后,画布不会被清空,粒子会持续绘制导致无限延伸。

解决方案

要实现渐变消失的拖尾效果,需要在每帧开头用低透明度的背景矩形覆盖画布,配合clear()方法重置WEBGL的渲染状态:

  1. 在draw函数最开头添加清除和半透明背景绘制的代码
  2. 调整背景色的alpha值控制拖尾的淡出速度(值越小拖尾越长,越大消失越快)

修改后的完整代码

import React from 'react';
import { ReactP5Wrapper } from "@p5-wrapper/react";
import "../../App.css";

const Flow = () => {
    let w, h, nums;
    let zOff = 0;
    let scl = 0.005;
    let speed = 2;
    let particles = [];
    let cursor;

    const setup = (p5, canvasParentRef) => {
        w = p5.windowWidth;
        h = p5.windowHeight;
        nums = 2000;
        p5.frameRate(60);
        p5.createCanvas(w, h, p5.WEBGL).parent(canvasParentRef);

        for (let i = 0; i < nums; i++) {
            particles.push(p5.createVector(p5.random(w), p5.random(h)));
        }

        cursor = p5.createVector(p5.mouseX, p5.mouseY);
    }

    const draw = (p5) => {
        // --- 修改部分:添加半透明背景实现拖尾 ---
        const bgColor = getComputedStyle(document.documentElement).getPropertyValue('--main-bg-color').trim();
        const bgColorValues = bgColor.match(/\d+/g);
        const r = parseInt(bgColorValues[0]);
        const g = parseInt(bgColorValues[1]);
        const b = parseInt(bgColorValues[2]);
        
        // WEBGL模式下先清除画布
        p5.clear();
        // 设置带alpha的背景色,alpha=20(可根据需求调整)
        p5.fill(r, g, b, 20);
        // 绘制覆盖整个画布的矩形,对应translate后的坐标
        p5.rect(-w/2, -h/2, w, h);
        // --- 修改结束 ---

        p5.stroke(getComputedStyle(document.documentElement).getPropertyValue('--main-text-color'));
        p5.translate(-w / 2, -h / 2);
        p5.strokeWeight(3);
        cursor.set(p5.mouseX, p5.mouseY);

        for (let i = 0; i < nums; i++) {
            let p = particles[i];
            let distance = p5.dist(p.x, p.y, cursor.x, cursor.y);

            if (distance < 50) {
                let dir = p5.createVector(p.x, p.y);
                dir.sub(cursor);
                dir.normalize();
                let repulsion = 3;
                dir.mult(repulsion);
                p.add(dir);
            }

            let n = p5.noise(p.x * scl, p.y * scl, zOff);
            let angle = p5.TWO_PI * n;
            p.x += Math.cos(angle) * speed;
            p.y += Math.sin(angle) * speed;

            if (!onScreen(p, w, h)) {
                p.x = p5.random(p5.windowWidth);
                p.y = p5.random(p5.windowHeight);
            }

            p5.point(p.x, p.y);
        }

        zOff += 0.002;
    }

    const onScreen = (v, w, h) => {
        return v.x >= 0 && v.x <= w && v.y >= 0 && v.y <= h;
    }

    const windowResized = (p5) => {
        w = p5.windowWidth;
        h = p5.windowHeight;
        p5.resizeCanvas(w, h);
    };

    return (
        <ReactP5Wrapper sketch={p => {
            p.setup = () => setup(p);
            p.draw = () => draw(p);
            p.windowResized = () => windowResized(p);
        }}
        />
    )
}

export default Flow;

关键细节说明

  • p5.clear():WEBGL模式下必须调用,否则之前的渲染内容会残留导致异常
  • 背景alpha值:推荐在10-50之间调整,数值越小拖尾痕迹保留越久
  • 矩形绘制:因为使用了translate(-w/2, -h/2),所以矩形的起始坐标要设为(-w/2, -h/2)才能覆盖整个画布

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 06:26:03