惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
月光博客
月光博客
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
Jina AI
Jina AI
小众软件
小众软件
U
Unit 42
云风的 BLOG
云风的 BLOG
Stack Overflow Blog
Stack Overflow Blog
雷峰网
雷峰网
博客园 - Franky
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
宝玉的分享
宝玉的分享
B
Blog
C
Check Point Blog
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
量子位
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News
酷 壳 – CoolShell
酷 壳 – CoolShell

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
【互動藝術 DIY】用 p5.js 做一塊會呼吸的粒子背景(無程式背...
張旭豐 · 2026-06-28 · via DEV Community

張旭豐

【互動藝術 DIY】用 p5.js 做一塊會呼吸的粒子背景

先問自己:阿哲會想動手嗎?

看完這個效果,阿哲可能會想:

「那如果我把粒子排成自己的名字,滑鼠靠近時會散開嗎?」

這就是正確的方向——讓讀者想自己動手改參數,而不是背程式碼。

這個方法厲害在哪?

p5.js 官網有很多炫技的粒子效果,但大部分只是給你看「很厲害」。

這次不一樣——我要教你用最少程式碼,做出最有呼吸感的互動

秘密是:用「距離」控制行為,用「lerp」讓移動變溫柔。

教學順序

  1. 先建立粒子:讓一群點組成畫面
  2. 教動畫:用 sin() 做出呼吸節奏
  3. 教距離感:用 dist() 偵測滑鼠
  4. 教溫柔散開:用 lerp() 柔和移動,不是瞬移
  5. 最後加美感:透明度、殘影、暖色

第一步:讓粒子回家

class Particle {
  constructor(x, y) {
    this.homeX = x;        // 記住家的位置
    this.homeY = y;
    this.x = x;
    this.y = y;
  }

  // 讓粒子回家的力量
  returnHome() {
    this.x = lerp(this.x, this.homeX, 0.05);  // 每次移動5%的距離
    this.y = lerp(this.y, this.homeY, 0.05);
  }

  show() {
    noStroke();
    fill(255, 180, 120, 200);   // 暖橙色
    ellipse(this.x, this.y, 4);
  }
}

第二步:偵測滑鼠距離

function draw() {
  for (let p of particles) {
    let d = dist(mouseX, mouseY, p.x, p.y);

    if (d < 100) {
      // 滑鼠靠近時,輕輕推開
      let force = 0.05 * (100 - d) / 100;
      p.x += (p.x - mouseX) / d * force;
      p.y += (p.y - mouseY) / d * force;
    }

    p.returnHome();
    p.show();
  }
}

第三步:加呼吸節奏

let breathPhase = 0;

function draw() {
  breathPhase += 0.02;
  let breath = sin(breathPhase);   // -1 ~ +1 來回循環

  background(10, 8, 5);            // 暖暗色背景

  for (let p of particles) {
    let d = dist(mouseX, mouseY, p.x, p.y);

    if (d < 100) {
      let force = 0.05 * (100 - d) / 100;
      p.x += (p.x - mouseX) / d * force;
      p.y += (p.y - mouseY) / d * force;
    }

    p.returnHome();
    p.show(breath);   // 把呼吸相位傳進去
  }
}

function show(breath) {
  noStroke();
  // 呼吸時變亮,吐氣時變暗
  let alpha = map(breath, -1, 1, 150, 255);
  fill(255, 180, 120, alpha);
  ellipse(this.x, this.y, 4);
}

第四步:殘影效果

function draw() {
  // 不要每幀清掉背景,而是蓋一層半透明黑色
  fill(10, 8, 5, 30);
  rect(0, 0, width, height);

  // ... 其餘粒子邏輯
}

這樣粒子移動時會留下淡淡的光跡——很有沉浸式裝置的 feel。

阿哲可以怎麼玩?

參數 預設值 改成... 效果
感知半徑 100px 50px 只有非常靠近才有反應
回家速度 0.05 0.02 超級慢,像在水裡
回家速度 0.05 0.2 快一點回覆
粒子數量 200 50 稀疏的星塵感
粒子颜色 暖橙 淡粉 更柔和的感覺

延伸練習

  1. 把粒子排成自己的名字:讓粒子組成「阿哲」或英文字母輪廓,滑鼠靠近時文字散開,離開後慢慢聚回來。

  2. 滑鼠不是破壞者,是一陣風:不只是排斥,而是讓粒子沿著滑鼠移動方向飄走。

  3. 做一個會呼吸的光圈:粒子圍成圓形,隨 sin() 擴張收縮。滑鼠靠近時,圓形像水母一樣被推開。

知識圖譜連結