PixiJS - 修正 sprite 為透明背景時的 hitArea

將你的 sprite hitArea 套上完美的 polygons 吧!

 

PixiJS 很好玩,你一定要試試!

 

1. 前言

PixiJS  是個很龐大的 2D 渲染引擎,使用後,你會發現更多美麗的事物。

 

 

 

2. 動機

最近使用 PixiJS 時,在 sprite 的滑鼠事件上遇到了點問題。

 

情境說明:

 我們隨意找一張圖,下圖為 PixiJS 範例圖。

 

該圖大小為 119x181 且為透明背景的可愛河童。

注意!請不要跟我爭辯他到底是河童西洋梨還是青蛙

 

如果你為它寫一個 pointertap 觸碰事件,會發生什麼事?

const app = new PIXI.Application({
  width: 200,
  height: 200,
});
document.body.appendChild(app.view);

const sprite = PIXI.Sprite.from('https://pixijs.io/examples/examples/assets/flowerTop.png');
sprite.buttonMode = true;
sprite.interactive = true;

sprite.addListener('pointertap', () => {
  alert('Hola');
});

app.stage.addChild(sprite);
  • buttonMode:為了方便辨識,在此設定讓滑鼠移入可觸發範圍時的指標為 pointer 樣式

 

點選了河童,看起來沒問題!

 

但接下來,你試著將滑鼠移動到右下角的 「黑色區域 ...!?

居然夠觸發觸碰事件,而且滑鼠指標也呈現 pointer 樣式。

 

 

為什麼會這樣?

因為 sprite 預設 hitArea 為圖片本身的大小,包含了那些透明區域。

在理想上,當然會希望僅在 「看得見」的地方 trigger

 

因此,如何鎖定在看得見的圖片是個問題!

接下來開始撰寫解決的辦法!

 

 

 

2. 工具

目前找到的工具是 PhysicsEditor,不過他只有七天的試用期。

如果有長期需求,當然建議可以給他買下去,約台幣 $800/year 不到~

 

安裝完畢後啟動,試著加入圖片吧!

[ Add sprites ]

image

 

接著使用如同魔術棒的輪廓偵測工具,捕捉圖形邊框。

Shape tracer ]

image

 

由於我們使用 PixiJS,在右側 Exporter 中,請選擇 Phaser (P2)

[ Exporter ]

image

 

你知道嗎?Phaser 是一套完整性高的 2D 網頁遊戲引擎。

 

最後將多邊形匯出成 JSON 格式。

Publish ]

image

 

仔細看看它的 JSON 結構:

它是由數個多邊形組合而成的喲!

{ 
    
    "flowerTop": [
        {
            "shape": [ 27.5,145, 32.5,138, 30.5,152, 27.5,149 ]
        },
        {
            "shape": [ 41.5,176, 32.5,138, 89.5,141, 92.5,150, 90.5,152, 61.5,176, 54,180.5, 44,180.5 ]
        },
    ]
}
  • flowerTop:根據你的圖片而命名。
  • shape:該集合為其中一個多邊形的座標點。

 

 

 

3. 套件

接下來可使用套件 hitarea-shapes 將該輪廓套至 sprite 中。

 

3.1 安裝

npm install --save pixi.js hitarea-shapes

# 或者

yarn add pixi.js hitarea-shapes

 

當然,你也可以在 html 中使用 CDN

<script src="https://unpkg.com/hitarea-shapes"></script>

 

如果你不想使用該套件,你可以參考 pixi-poly 是如何實踐出輪廓問題的。

因為 hitarea-shapes 是筆者參考並調整一些程式碼後發佈出來的~

 

 

3.2 載入模組與多邊形

如果你是以模組化架構開發,那就直接 import 或 require 進來~

import HitAreaShapes from 'hitarea-shapes';
import data from 'flowerTop.json';

 

如果你的環境選擇使用 cdn,也沒有 babel

那你可以參考 hiarea-shapes example,先用 fetch 將多邊形 JSON 檔案載入。

然後再實例一個 HitAreaShapes

 

 

3.3 實例與套用

直接把 sprite.hitArea 設為剛剛建立好的實例即可!

// Your sprite
// ...

const hitAreaShapes = new HitAreaShapes(data);

sprite.hitArea = hitAreaShapes;

 

 

 

3.4 結果

再次看看網頁結果!

當滑鼠在黑色區域進行觸碰 (click/tap) ,並不會 trigger 囉~

同時指標也不會呈現 pointer

 

 

 

4. 後記

大家也來學學 PixiJS 吧~

本篇方法也許不是最好,誤打誤撞學習道路上有你有我。

也歡迎提出更棒的做法!!

 

 

有勘誤之處,不吝指教。ob'_'ov