DEV Community

張旭豐
張旭豐

Posted on

讓粒子學會呼吸:p5.js 互動視覺的第一堂課

cover

一群暖色粒子在深色背景裡來回呼吸


上一個作品教我們的事

在 TeamLab 那片花海裡,我們發現一個秘密:
讓東西「慢慢反應」,比「立刻反應」更像活的。

感測器可以偵測你站在哪裡。
但「慢慢知道你在哪裡」,感覺像這個房間真的有在注意你。

今天我們把這個原理,變成一個你自己做出來的東西。


這個效果厲害在哪

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

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

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


第一步:讓粒子回家

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

lerp() 是什麼?
lerp(a, b, t) = 從 a 到 b,取 t% 的距離。

t = 0.05 的時候,粒子每次只走 5% 的路,很慢、很溫柔。


第二步:偵測滑鼠距離

function draw() {
  for (let p of particles) {
    let d = dist(mouseX, mouseY, p.x, p.y);  // 滑鼠到粒子的距離

    if (d < 100 && d > 1) {                 // 100px 內、且至少離1px(防止除以零)
      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();
  }
}
Enter fullscreen mode Exit fullscreen mode

dist() 是什麼?
dist(x1, y1, x2, y2) = 兩點之間的直線距離。

為什麼用 (p.x - mouseX) / d
這是「從滑鼠指向粒子的單位向量」。施在粒子身上,就是把粒子推開。


第三步:加呼吸節奏

let breathPhase = 0;

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

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

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

    if (d < 100 && d > 1) {               // 100px 內、且至少離1px(防止除以零)
      let force = 0.05 * (100 - d) / 100;
      p.x += (p.x - mouseX) / d * force;
      p.y += (p.y - mouseY) / d * force;
    }

    p.returnHome();

    // 呼吸時變亮,吐氣時變暗
    let alpha = map(breath, -1, 1, 150, 255);
    fill(255, 180, 120, alpha);
    ellipse(p.x, p.y, 4);
  }
}
Enter fullscreen mode Exit fullscreen mode

阿哲可以怎麼玩?

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

庭庭:這個原理可以用在哪裡

「慢慢知道你在哪裡」這個原理,博物館互動牆最常用。

展品感測到你靠近不會瞬間反應,而是像有生命一樣「正在注意你」。
這個延遲不是缺點,是設計。因為讓你感覺被看見。


小傑:如果想做得更正式

讓粒子排列成特定形狀(文字、logo),
滑鼠靠近時整個形狀像水母一樣散開,
這就是一個可以在展覽使用的互動裝置。

演算法關鍵:用二維陣列控制每個粒子的 home 位置,
這樣可以預先定義「正常時」的排列形狀。


下一個練習

把滑鼠改成「一陣風」——

不只是排斥,而是讓粒子沿著滑鼠移動方向飄走。
你移動越快,粒子被吹得越遠。

這個原理做出來,就是「互動風場」。


知識圖譜連結

Top comments (0)