iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 2
2
Modern Web

再談 PixiJS,那些先前不一定有提到的部分與地雷系列 第 2

[Re:PixiJS - Day02] PixiJS 物件的排列、寬高特性

寫在第二天的是覺得很容易踩到的麻煩點:排列寬高


為了重現麻煩點,設定了一個情境:

創造三個容器,裡頭各放了一個 100x100 的色塊。
並讓三個容器水平緊鄰

目標:

物件結構

...看起來似乎不難?

1. 先做出三個容器,此時不指定寬高:

const boxContainer1 = new PIXI.Container();
boxContainer1.name = "boxContainer1";
app.stage.addChild(boxContainer1);

const boxContainer2 = new PIXI.Container();
boxContainer2.name = "boxContainer2";
app.stage.addChild(boxContainer2);

const boxContainer3 = new PIXI.Container();
boxContainer3.name = "boxContainer3";
app.stage.addChild(boxContainer3);

2. 因為 PixiJS 不像 CSS 一樣可以用 float,要手動算位置:

第一個方塊的 x0
第二個方塊的 x 是 第一個方塊的 x + 第一個方塊的寬度
第三個方塊的 x 是 第二個方塊的 x + 第二個方塊的寬度

boxContainer1.x = 0;
boxContainer2.x = boxContainer1.x + boxContainer1.width;
boxContainer3.x = boxContainer2.x + boxContainer2.width;

3. 容器裡各放一個 100x100 的色塊:

const graphic1 = new PIXI.Graphics();
graphic1.beginFill(0xff0000); // 填入紅色
graphic1.drawRect(0, 0, 100, 100);
graphic1.endFill();
boxContainer1.addChild(graphic1);

const graphic2 = new PIXI.Graphics();
graphic2.beginFill(0xff9900); // 填入橘色
graphic2.drawRect(0, 0, 100, 100);
graphic2.endFill();
boxContainer2.addChild(graphic2);

const graphic3 = new PIXI.Graphics();
graphic3.beginFill(0xff0000); // 填入紅色
graphic3.drawRect(0, 0, 100, 100);
graphic3.endFill();
boxContainer3.addChild(graphic3);

好像沒問題了,打開網頁看
層級沒問題,可是方塊 ...疊起來了!?

把各個容器的座標 x寬度印出來看看:

寬度正確,可是座標 x 是錯的,為何?
(沒有唬爛所以附上 Demo):

問題發生點在這:

boxContainer1.x = 0;
boxContainer2.x = boxContainer1.x + boxContainer1.width;
boxContainer3.x = boxContainer2.x + boxContainer2.width;

把這段往後搬,至少搬到
boxContainer3.addChild(graphic3); 之後

boxContainer1.addChild(graphic1); // 往前搬
boxContainer2.addChild(graphic2);
boxContainer3.addChild(graphic3);

boxContainer1.x = 0;
boxContainer2.x = boxContainer1.x + boxContainer1.width;
boxContainer3.x = boxContainer2.x + boxContainer2.width;

// boxContainer1.addChild(graphic1); // 移除,往前搬
// boxContainer2.addChild(graphic2);
// boxContainer3.addChild(graphic3);

結果正確!

PIXI 非 CSS,寬高屬性為取值當下的數值
當容器建立但內容為空的時候,這時取得的寬高為0

box1 的寬度0,x 是0
box2 的寬度0,x 是0 // box1 的x座標0 加上 box1 的寬度0
box3 的寬度0,x 是0 // box2 的x座標0 加上 box2 的寬度0

小結:

PixiJS 容器會被子物件撐開,可是要在放入子物件後再取值


類似問題之二

容器放了一隻兔子
兔子不縮放,但容器寬度(scale.x)設定為 1.5 倍:

const container = new PIXI.Container();
app.stage.addChild(container);

const bunny = PIXI.Sprite.from('assets/basics/bunny.png');
container.addChild(bunny);

// 為避免還沒讀完兔子就指定容器寬度會有問題,直接設定 1000 毫秒後再更動容器的寬度

setTimeout(function(){
	container.scale.x = 1.5;
}, 1000);

結構為:

umm...更動容器的寬度,可是兔子也變寬啦!

(左邊是容器寬度放大 1.5 倍的兔子,右邊是原始大小的兔子)
Demo

CSS改容器寬高,不會影響到內容
可是這結果很像是...容器整個設定了 transform: scale(1.5, 1); ?

就 PixiJS 來說很合理

直接改動容器的寬度,等同直接改容器的 scale.x

container.scale.x = 1.5; // 整個容器一起改變,包含容器內的內容

這也是與 CSS 很不同的部分:

父容器變大時,不會多出空間可用,而是讓子物件一起放大。

本日總結:

PixiJS 沒有 margin、padding、flex 等好用的方法,
要讓 PixiJS 排列成像 HTML / CSS 時,會滿辛苦的

上一篇
[Re:PixiJS - Day01] 再談 PixiJS
下一篇
[Re:PixiJS - Day03] 可視物件的深度 - childIndex / zIndex
系列文
再談 PixiJS,那些先前不一定有提到的部分與地雷45

尚未有邦友留言

立即登入留言