PixiJS 連連看遊戲畫面中的聲音按鈕

← INSIGHTS & PERSPECTIVES | 前端開發

PixiJS 按鈕製作基礎:Sprite 互動、ButtonBase 與靜音切換

說明 PixiJS 按鈕如何開啟互動事件、抽出 ButtonBase 父類別,並實作聲音開關按鈕與 Howler 靜音功能。

PixiJS 按鈕製作的核心是讓 Sprite 進入可互動狀態,再把重複的貼圖、座標、事件與觸發邏輯抽成 ButtonBase。本文保留 2018 年 PixiJS 專案常見的 interactivebuttonModemousedowntouchstart 寫法,並補充現代 PixiJS 建議使用 pointer events 與 eventMode 的差異(PixiJS 官方文件,2026 年 8 月存取)。

PixiJS Sprite 如何開啟按鈕互動?

PixiJS Sprite 預設不是按鈕,必須先開啟互動模式並綁定事件。舊版 PixiJS 常用 interactivebuttonMode,現代 PixiJS 則建議用 pointer events 統一滑鼠、觸控與觸控筆。

PixiJS 是用於建立 2D WebGL 與 Canvas 互動畫面的 JavaScript 渲染函式庫。一般 Sprite 只負責顯示圖片;如果每個顯示物件都預設做 hit test,畫面上物件一多就會增加互動偵測成本,所以按鈕要明確 opt-in。

我當時的筆記中的基本按鈕設定如下:

// Opt-in to interactivity
sprite.interactive = true;

// Shows hand cursor
sprite.buttonMode = true;

// Pointers normalize touch and mouse
sprite.on('pointerdown', onClick);
sprite.on('click', onClick); // mouse-only
sprite.on('tap', onClick); // touch-only

現代 PixiJS 文件建議以 eventMode = 'static' 讓固定互動物件發出事件,並優先使用 pointerdownpointeruppointerupoutside 等 pointer events 處理跨裝置輸入(PixiJS Events Guide,2026 年 8 月存取)。維護舊專案時,先確認專案使用的 PixiJS 版本,再決定保留 interactive 或改成 eventMode

為什麼要抽出 ButtonBase 父類別?

ButtonBase 的價值是把每個按鈕都需要的貼圖、座標、互動狀態與事件綁定集中管理。連連看專案有多個按鈕時,具體按鈕只要覆寫 trigger(),不用重複寫相同事件。

在連連看專案裡,聲音按鈕、重新開始按鈕、提示按鈕的功能不同,但都需要設定貼圖、可點擊狀態、手形游標、座標、錨點,以及按下與放開事件。把這些共用邏輯放進 ButtonBase,後續要加入縮放效果、音效或 disabled 狀態時,也只需要改一個地方。

我當時的筆記的 ButtonBase.ts 如下:

import Sprite = PIXI.Sprite;
import {Loader} from "../core/Loader";

export class ButtonBase extends Sprite{

    constructor(_id:string, textureID:string, _x:number, _y:number) {
        super();
        this.texture = Loader.resources[_id].textures[textureID];
        this.interactive = true;
        this.buttonMode = true;
        this.x = _x;
        this.y = _y;
        this.anchor.set(0.5);

        //按下效果
        this.on("mousedown", this.mouseDownEffect.bind(this));
        this.on("mouseup", this.mouseUpEffect.bind(this));
        this.on("mouseout", this.mouseOutEffect.bind(this));
        this.on("touchstart", this.mouseDownEffect.bind(this));
        this.on("touchend", this.mouseUpEffect.bind(this));

        this.on("mouseup", this.trigger.bind(this));
        this.on("touchend", this.trigger.bind(this));
    }
    public trigger(){
    }
    public mouseDownEffect():void{
    }
    public mouseUpEffect():void{
    }
    public mouseOutEffect():void{
    }
}

anchor.set(0.5) 會把 Sprite 的錨點設在圖片中心,讓位置與縮放比較符合按鈕互動直覺;PixiJS Sprite 文件也說明,anchor 的 (0.5, 0.5) 代表以紋理中心作為原點(PixiJS Sprite API,2026 年 8 月存取)。

SoundBtn 如何實作聲音開關按鈕?

SoundBtn 繼承 ButtonBase 後,只需要管理靜音狀態、呼叫聲音管理器,並依狀態切換貼圖。按鈕的互動事件留在父類別,聲音開關行為留在子類別。

SoundBtn 的資訊增益在於「按鈕狀態」與「遊戲音訊狀態」分開處理。SoundBtn 保存 isMuteSoundMgr 負責真正呼叫音訊函式庫;這樣未來若要把按鈕圖片改成文字、或把 Howler 換成別的音訊方案,影響範圍會比較小。

我當時的筆記的 SoundBtn.ts 如下:

import {ButtonBase} from "./ButtonBase";
import {Loader} from "../core/Loader";
import {SoundMgr} from "../core/SoundMgr";


export class SoundBtn extends ButtonBase {
    private isMute: boolean = false;
    constructor() {
        super('Button','Sound_On',50,170);
        this.updateImage();

    }
    public trigger(){
        this.isMute = !this.isMute;
        SoundMgr.mute(this.isMute);
        this.updateImage();
    }
    updateImage = ()=>{
        if (this.isMute){
            this.texture = this.texture = Loader.resources['Button'].textures['Sound_Off'];
        } else{
            this.texture = this.texture = Loader.resources['Button'].textures['Sound_On'];
        }
    }

}

這段程式保留了我當時的稿件寫法。實務整理時可以順手把 this.texture = this.texture = ... 改成單次指定,但文章先保留當時的範例,讓讀者能對照 2018 年專案內容。

GameScene 要在哪裡加入按鈕?

GameScene 適合集中把背景、按鈕與其他遊戲物件加進 stage。按鈕類別負責自身行為,場景類別只負責建立物件與加入顯示清單。

因為除了聲音按鈕之外,遊戲場景通常還會有背景、角色、牌面、分數與倒數計時器。把場景組裝放進 GameScene.draw(),可以避免 Main 或入口檔同時承擔載入、畫面建立與互動邏輯。

我當時的筆記的 GameScene.ts 如下:

import {Loader} from "../core/Loader";
import {application} from "../Main";
import {SoundBtn} from "./SoundBtn";

export class GameScene {

    public static draw(){
        //加入背景
        application.stage.addChild(PIXI.Sprite.from(Loader.resources["background"].texture));
        //加入按鈕
        application.stage.addChild(new SoundBtn());
    }
}

這個分層方式雖然簡單,但對小型遊戲很實用:ButtonBase 管互動事件,SoundBtn 管聲音按鈕行為,GameScene 管畫面放哪些物件。

SoundMgr 如何用 Howler 做靜音功能?

SoundMgr 可以提供全域靜音入口,讓按鈕不直接依賴 Howler 的細節。Howler 的 Howler.mute(true) 會全域靜音,Howler.mute(false) 會解除靜音。

Howler.js 是瀏覽器音訊函式庫,常用於遊戲音效與背景音樂。Howler 官方 README 說明,Howler.mute(muted) 是全域方法,參數為 true 時靜音所有聲音,參數為 false 時解除全域靜音(Howler.js README,2026 年 8 月存取)。

我當時的筆記在 SoundMgr.ts 加上的靜音功能如下:

static isMute: boolean = false;
public static mute(value:boolean):void {
    this.isMute = value;
    if (this.isMute) {
        //禁聲
        Howler.mute(true);
    } else {
        //出聲
        Howler.mute(false);
    }
}

如果專案後續有更多聲音設定,可以讓 SoundMgr 繼續統一管理音量、暫停、恢復與音效分類,避免 UI 按鈕散落直接呼叫 Howler

PixiJS 按鈕基礎實作流程是什麼?

PixiJS 按鈕基礎流程可以拆成五步:開啟 Sprite 互動、建立 ButtonBase、建立具體按鈕、加入場景、串接功能管理器。這個流程適合先做出可點擊 UI,再逐步加入動畫與狀態控制。

步驟檔案責任
1ButtonBase.ts設定 texture、座標、anchor、互動事件
2SoundBtn.ts切換 isMute,更新按鈕貼圖
3GameScene.ts把背景與按鈕加入 application.stage
4SoundMgr.ts呼叫 Howler.mute() 控制全域聲音
5後續擴充加入按下動畫、disabled、防連點與 pointer events

今日成果如下,畫面左側可以看到聲音按鈕已加入連連看遊戲場景:

PixiJS 連連看遊戲畫面中的聲音按鈕

這篇筆記另附線上 demo 與檔案下載,但來源連結不是 HTTPS,本文為了維持外部連結安全性與 GEO 寫作規範,未把非 HTTPS 連結放進正式參考資料。

常見問題

QPixiJS Sprite 為什麼預設不能點擊?

PixiJS Sprite 預設主要負責渲染圖片,不會主動做互動 hit test。開啟互動偵測會增加事件判斷成本,所以 PixiJS 讓開發者針對需要點擊的物件明確設定互動模式。

QPixiJS 舊版的 interactive 和新版的 eventMode 差在哪裡?

interactive = true 是舊版 PixiJS 常見寫法;現代 PixiJS 使用 eventMode 控制互動模式。固定按鈕通常可設為 eventMode = 'static',移動或動畫中的互動目標才需要考慮 dynamic

QPixiJS 按鈕要用 mouse event、touch event 還是 pointer event?

新專案建議優先使用 pointer events,因為 pointer events 可統一滑鼠、觸控與觸控筆。維護舊專案時可以先保留 mousedownmouseuptouchstarttouchend,再規劃版本升級。

QButtonBase 裡的 trigger() 為什麼是空的?

ButtonBase.trigger() 是留給子類別覆寫的按鈕行為入口。父類別只處理共同互動流程,子類別例如 SoundBtn 再決定按下後要靜音、換圖或執行其他功能。

QPixiJS 按鈕為什麼要設定 anchor.set(0.5)?

anchor.set(0.5) 會把 Sprite 的原點設在圖片中心。按鈕縮放、旋轉或定位時,以中心作為原點通常比左上角更符合 UI 互動效果。

QHowler.mute(true) 會停止播放聲音嗎?

Howler.mute(true) 會把 Howler 管理的聲音全域靜音,但靜音不等於停止播放。若要停止並重設播放位置,通常要另外使用 stop 類方法。

參考資料

延伸閱讀

最後更新

2026-08-28

關於作者

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2018-11-02