iT邦幫忙

2024 iThome 鐵人賽

DAY 20
1
Modern Web

創意前端設計:用 Vue.js 打造 30 個互動實用功能系列 第 20

Day20 Vue.js 動效分類實戰 (12) 極致品牌特輯 - 使用 p5.js 打造前所未見的個性化視覺效果

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20241004/20124462p2rpFlRr6D.jpg


讓你的品牌圖像不再只是靜態,打造充滿創意與互動的專屬視覺盛宴

你有沒有想過,讓你心愛的品牌 logo 或圖片不只是乖乖躺在頁面上,而是像魔法一樣,飛散、組合,最後化身為獨一無二的動態文字呢?🤩

今天我們來玩點不一樣的,用 Vue.js 搭配 p5.js,打造一個屬於你自己的個性化視覺效果,讓你的網站不再是單純的圖片展示,而是充滿創意、互動和樂趣!
而且不會與別人類似!
這不僅僅是一次技術挑戰,還是一次讓你的設計充滿創意的過程。
準備好展開這趟動態視覺之旅了嗎?

Let's go!🚀


設計核心概念:

在設計中,我們不再滿足於靜態的圖像展示,互動感和個性化成為提升使用者體驗的關鍵。
品牌設計也是如此,透過動畫和視覺動效,品牌的形象不僅變得更加生動,還能傳達更多情感和信息。

這裡我們的核心概念有三個:

  1. 圖像與文字結合:讓圖片中的元素自由飛散,然後重新組合成文字,讓圖像和文字之間形成有趣的互動。
  2. 粒子化處理:將圖像轉化為小顆粒,每個粒子都是一部分圖片,然後我們可以操控這些粒子的運動,讓它們飛散或者重組。
  3. 視覺互動與體驗:我們的點陣粒子在點擊後會飛散開來,模擬一個動態的散開效果,隨後重新組合成文字,讓整個互動過程更有趣、更具吸引力。

img


核心實作程式碼

這次我們的目標是使用 Vue.jsp5.js,將一張圖片轉換成點陣粒子,並實現點擊畫布後,粒子飛散再重新組合成文字的效果。
接下來,我們會逐步剖析這個實作的每個核心部分,並解釋其設計原因和技術細節。

  • 安裝
npm install p5
  • p5.js TypeScript 型別定義
npm install @types/p5 --save-dev

實作過程與程式碼詳細解說

這次我們的目標是使用 Vue.jsp5.js,將一張圖片轉換成點陣粒子,並實現點擊畫布後,粒子飛散再重新組合成文字的效果。接下來,我們會逐步剖析這個實作的每個核心部分,並解釋其設計原因和技術細節。

https://ithelp.ithome.com.tw/upload/images/20241004/20124462QeqeHtXsnY.png


1. 初始化畫布與圖片載入

在 Vue 的 onMounted 階段,我們利用 p5.js 來初始化畫布並載入圖片,這是整個粒子效果的基礎。

const canvasContainer = ref<HTMLDivElement | null>(null);

onMounted(() => {
    const initP5 = () => {
        const sketch = (p: p5) => {
            p.preload = () => {
                img = p.loadImage('https://i.imgur.com/rGmeexe.png');
            };

            p.setup = () => {
                const canvas = p.createCanvas(window.innerWidth, window.innerHeight);
                canvas.parent(canvasContainer.value as HTMLDivElement); 
                img.loadPixels();  // 載入圖片的像素數據
                p.noStroke();      // 去除粒子的邊框

                const scaleFactor = 0.65;
                createParticleDotGrid(p, scaleFactor); // 建立粒子點陣
                createTextParticles(p, "Sunny.Cat", 100, p.height / 2); // 建立文字粒子
            };
        };
        new p5(sketch);
    };
    initP5();
});

解說:

  • canvasContainer:這個是用來放置 p5.js 畫布的容器。我們使用 Vue 的 ref 來存取 DOM 元素。
  • onMounted:在 Vue 元件掛載後,我們初始化 p5.js 畫布。使用 p5.jscreateCanvas 方法來設定畫布大小,並將其掛載到 canvasContainer 中。
  • img.loadPixels():這個方法是關鍵,它會讀取圖片的像素數據,使我們能夠操作圖片中的每個像素,並將它們轉換成粒子。

我們首先載入圖片並設定畫布,之後將圖片轉換為粒子點陣,並準備生成文字粒子。


2. 粒子類別設計

我們使用 Particle 類別來表示圖片中的每一個像素粒子。
這些粒子可以在畫布上顯示、隨機飛散,並移動到指定的文字位置。

class Particle {
    pos: p5.Vector;             // 粒子當前位置
    originalPos: p5.Vector;      // 粒子原始位置
    col: p5.Color;               // 粒子的顏色
    vel: p5.Vector;              // 粒子的速度向量
    targetPos: p5.Vector | null = null;  // 粒子的目標位置

    constructor(x: number, y: number, col: p5.Color) {
        this.pos = new p5.Vector().set(x, y);  // 粒子位置
        this.originalPos = this.pos.copy();    // 保存原始位置
        this.col = col;                        // 粒子的顏色
        this.vel = p5.Vector.random2D().mult(5);  // 隨機速度,讓粒子可以隨機飛散
    }

    // 顯示粒子
    display(p: p5) {
        p.fill(this.col);
        p.noStroke();
        p.ellipse(this.pos.x, this.pos.y, particleSize, particleSize);  // 使用圓形表示粒子
    }

    // 粒子飛散效果
    scatter(p: p5) {
        this.pos.add(this.vel);  // 根據速度向量更新位置
        this.display(p);         // 顯示粒子
    }

    // 移動粒子到目標位置(文字組合)
    moveToText(p: p5) {
        if (!this.targetPos) {
            let randomTarget = p.random(textParticles);
            this.targetPos = p.createVector(randomTarget.x, randomTarget.y);  // 隨機選擇一個文字粒子的位置作為目標
        }

        let direction = p5.Vector.sub(this.targetPos, this.pos);  // 計算目標位置與當前位置的向量差
        this.pos.add(direction.mult(0.2));  // 更新粒子位置,逐漸移向目標
        this.display(p);
    }
}

解說:

  • Particle 類別:每個粒子都是一個獨立的物件,它擁有位置、顏色、速度等屬性。
    這樣的設計方便我們管理和控制每個粒子的行為。

  • scatter 方法:當使用者點擊畫布時,粒子會根據隨機速度飛散開來,產生隨機運動效果。

  • moveToText 方法:這是粒子在飛散後的動作,會逐步移動到指定的目標位置(文字的某個字母像素點)。


3. 圖片轉換為粒子點陣

https://ithelp.ithome.com.tw/upload/images/20241004/20124462WCZnDyJUf8.png
這個函數將圖片的像素轉換為粒子,每個粒子代表圖片中的一個像素點。

const createParticlesFromImage = (p: p5, offsetX: number, scaleFactor: number, flipHorizontal: boolean) => {
    for (let y = 0; y < img.height; y += particleSize * 1.5) { 
        for (let x = 0; x < img.width; x += particleSize * 1.5) { 
            const index = (x + y * img.width) * 4;
            const r = img.pixels[index];
            const g = img.pixels[index + 1];
            const b = img.pixels[index + 2];

            let posX = flipHorizontal ? img.width - x : x;
            posX = posX * scaleFactor + offsetX; // 調整水平位置
            const posY = y * scaleFactor;        // 調整垂直位置

            const particle = new Particle(posX, posY, p.color(r, g, b));
            particles.push(particle);  // 將粒子存入 particles 數組
        }
    }
};

解說:

  • 縮放與水平翻轉:根據 scaleFactor 對圖片進行縮放,並根據 flipHorizontal 決定是否翻轉粒子的水平位置,使粒子排列更加豐富。
  • 粒子生成:我們根據圖片中的每個像素顏色生成對應的粒子,並存入 particles 數組,這些粒子將在畫布上展示。

4. 文字粒子生成

https://ithelp.ithome.com.tw/upload/images/20241004/20124462I5XBdQQmPs.png

這裡我們創建文字粒子,將它們作為粒子飛散後重新排列的目標位置。

const createTextParticles = (p: p5, text: string, _x: number, y: number) => {
    const textCanvas = p.createGraphics(p.width, p.height); // 使用 p5.js 創建一個隱藏的畫布來生成文字
    textCanvas.pixelDensity(1);
    textCanvas.background(255);
    textCanvas.textAlign(p.CENTER, p.CENTER);
    textCanvas.fill(0);
    textCanvas.textSize(100);
    textCanvas.text(text, p.width / 2, y);  // 在隱藏的畫布上繪製文字

    textCanvas.loadPixels();
    for (let i = 0; i < textCanvas.width; i += particleSize) {
        for (let j = 0; j < textCanvas.height; j += particleSize) {
            const index = (i + j * textCanvas.width) * 4;
            const r = textCanvas.pixels[index];
            if (r < 128) {  // 找出黑色部分(即文字部分)的像素點
                textParticles.push({ x: i, y: j }); // 將文字的像素點記錄為粒子的目標位置
            }
        }
    }
};

解說:

  • createGraphics:我們使用隱藏的 p5.Graphics 來繪製文字,不會在實際畫布上顯示,只用來捕捉文字的像素點。
  • loadPixels:這個方法會讀取文字圖像的像素數據,我們只保留文字的黑色部分,並將其作為粒子的目標位置。

5. 觸發動畫與互動控制

當使用者點擊畫布時,粒子會先飛散,隨後逐漸移動並組成文字。

p.mousePressed = () => {
    if (!

isScattered && !isFormingText) {
        isScattered = true;
        setTimeout(() => {
            isScattered = false;
            isFormingText = true;
        }, 2000);
    }
};

解說:

  • mousePressed:當使用者點擊畫布時,觸發粒子飛散效果,並在 2 秒後開始組成文字。
  • isScatteredisFormingText:這兩個變數控制著粒子的狀態,確保粒子在不同階段有不同的動作。

玩轉視覺粒子動效

img

  1. 如何將圖片轉換為粒子效果:學會使用 p5.jsloadPixels 方法將圖片的像素轉化為粒子,並以點陣形式呈現在畫布上,實現圖像粒子化的效果。

  2. 粒子飛散與重新組合的動畫:通過使用隨機速度讓粒子隨機飛散,並且在飛散後逐漸移動到指定的文字位置,實現動畫效果,提升網頁的互動性和趣味性。

  3. 結合 Vue.js 與 p5.js 進行互動設計:透過 Vue.js 的元件化設計與 p5.js 的動畫功能,學會如何將畫布動畫與網頁結合,並且實現點擊觸發的互動動畫設計。

這三個重點可以幫助讀者掌握粒子動畫的製作流程,並靈活運用於不同的網頁設計中。


通過這次的實作,我們成功讓靜態圖片「活」了起來,變成了會飛散、會組合的點陣粒子動畫!
這不僅讓網站變得更有趣、更有吸引力,也為個性化展示打開了一扇創意的大門。

是不是覺得自己也能做出一個酷炫的專屬動畫呢?😉

無論是要為自己的作品加點魔法,還是想讓網頁充滿驚喜,只要勇敢嘗試,創意無限!
相信你在不斷挑戰自我的過程中,也會發現更多靈感和可能性!

加油吧,讓你的技術和創意一起翱翔!🚀🌟


上一篇
Day19 Vue.js 動效分類實戰 (11) 進階背景特輯 - 用 GSAP 打造你的專屬海洋世界
下一篇
Day21 Vue.js 動效分類實戰 (12) 狂野動物幻燈片特輯 - 自訂 Slider,滑出不一樣的驚豔視覺!
系列文
創意前端設計:用 Vue.js 打造 30 個互動實用功能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言