PixiJS - 修正 sprite 為透明背景時的 hitArea
將你的 sprite hitArea 套上完美的 polygons 吧!
將你的 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 ]
接著使用如同魔術棒的輪廓偵測工具,捕捉圖形邊框。
[ Shape tracer ]
![]()
由於我們使用 PixiJS,在右側 Exporter 中,請選擇 Phaser (P2)。
[ Exporter ]
![]()
你知道嗎?Phaser 是一套完整性高的 2D 網頁遊戲引擎。
最後將多邊形匯出成 JSON 格式。
[ Publish ]
![]()
仔細看看它的 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




