メインコンテンツまでスキップ

レイアウトグループ

レイアウトグループは、エレメントの子の位置とサイズを自動的に決めます。子は横一列、縦一列、または行が折り返す場合はグリッドに並びます。リスト、ツールバー、メニュー、インベントリなど、子が追加、削除、リサイズされても均等に並んだままであるべきものに使います。

3つのレイアウト。親の幅まで引き伸ばされた行が縦に並んだ列、4個と3個のボタンがそれぞれツールバーの幅を分け合う2つのツールバー、最後の行が中央揃えになった正方形のグリッド。どのレイアウトでも、最も明るい色の子が先頭です

レイアウトグループの作成​

レイアウトグループは、エレメントも持つエンティティに追加するコンポーネントで、そのエレメントは通常グループエレメントです。エレメントの矩形が、子を並べる領域になります。次のリストは、5つの行を上から順に積み重ね、それぞれをリストの幅まで引き伸ばします。

const list = new pc.Entity('list');
list.addComponent('element', {
type: pc.ELEMENTTYPE_GROUP,
anchor: [0.5, 0.5, 0.5, 0.5],
pivot: [0.5, 0.5],
width: 300,
height: 400
});
list.addComponent('layoutgroup', {
orientation: pc.ORIENTATION_VERTICAL,
spacing: [0, 10],
padding: [10, 10, 10, 10],
widthFitting: pc.FITTING_STRETCH
});
screen.addChild(list);

for (let i = 0; i < 5; i++) {
const row = new pc.Entity(`row ${i}`);
row.addComponent('element', {
type: pc.ELEMENTTYPE_IMAGE,
height: 60,
color: new pc.Color(0.23, 0.55, 1)
});
list.addChild(row);
}

アプリケーションを作成するときに、pc.LayoutGroupComponentSystemとpc.LayoutChildComponentSystemを登録してください。LayoutChildコンポーネントを使う子がなくても、レイアウトグループにはLayoutChildのコンポーネントシステムが必要です。

子の配置の仕組み​

レイアウトグループは、直接の子のうち、有効で、かつ有効なエレメントを持つものを、ヒエラルキー内の順序で並べます。レイアウトグループは各子に対して次のことを行います。

  • アンカーを設定します。 アンカーは、グループの左下隅を表す0, 0, 0, 0になります。子に指定したアンカーは、分割されているかどうかにかかわらず置き換えられます。
  • 位置を設定します。 レイアウトはピボットを考慮して子の矩形を配置するため、ピボットがどこにあっても矩形は同じ位置に置かれます。
  • 計算されたサイズを設定します。 これは、フィッティングやレイアウトチャイルドが子のサイズを変える場合に行われます。子のwidthとheightは設定した値のまま変わらず、サイズ計算の出発点になります。幅と高さを参照してください。

ヒエラルキーでそれより下にあるエンティティは影響を受けません。そのため、子は独自のコンテンツを持つことができ、子自身がレイアウトグループを持つこともできます。入れ子になったレイアウトグループは、最も外側のものから内側に向かって順にレイアウトされます。

子が追加、削除、有効化、無効化、リサイズされたとき、子のピボットが変わったとき、レイアウトグループのプロパティが変わったときには、同じフレームのうちに、描画の前にレイアウトが再計算されます。子を自分で動かしてもレイアウトは実行されず、次のレイアウトで元の位置に戻されます。レイアウトグループは、レイアウトのたびに子の範囲を渡してreflowを発火します。

list.layoutgroup.on('reflow', ({ bounds }) => {
// bounds.xとbounds.yは、グループの左下隅を基準とした子全体の左下隅の位置で、
// bounds.zとbounds.wは子全体の幅と高さ
console.log(`The children take up ${bounds.z} × ${bounds.w}`);
});

レイアウトグループのプロパティ​

向き​

Horizontalは、子を左から右へ横一列に並べます。Verticalは、上から下へ縦一列に並べます。

反転​

Reverse XとReverse Yは、それぞれの軸に沿った順序を反転します。Reverse Yはデフォルトでオンになっており、そのために列やグリッドの行が上から下へ並びます。下から上へ積み上げるにはこれをオフにし、右から左へ並べるにはReverse Xをオンにします。

アラインメント​

Alignmentは、子がグループを埋めていないときに、子全体をグループ内のどこに置くかを決めます。値は、左下隅を表す0, 0から右上隅を表す1, 1までです。デフォルトの0, 1では、子は左上に置かれます。グリッドでは各行の揃え方も決めるため、0.5, 1にすると、他の行より短い最後の行が中央に揃います。

パディング​

Paddingは、グループの縁の内側に空けておく余白で、左、下、右、上の順に指定します。

間隔​

Spacingは、隣り合う子の間隔です。x値は行の中の子同士の間隔で、y値は列の中の子同士の間隔とグリッドの行同士の間隔です。

フィッティング​

Width FittingとHeight Fittingは、グループに合わせてレイアウトグループが子のサイズを変えるかどうかを決めます。

フィッティング子の扱い
None自身のサイズのままになります
Stretchグループより小さい場合、グループを埋めるように拡大されます。最大サイズがあれば、それが上限です
Shrinkグループより大きい場合、グループに収まるように縮小されます。最小サイズがあれば、それが下限です
Both収まるように、拡大または縮小のどちらかが行われます

行の幅のように、レイアウトの方向に沿ったサイズでは、余ったスペースまたははみ出した分が子の間で配分されます。レイアウトチャイルドで異なる比率を与えない限り、配分は均等です。レイアウトと直交する方向では、各子が個別に、行の高さまたは列の幅に合わせて拡大または縮小されます。エンジンの定数はpc.FITTING_NONE、pc.FITTING_STRETCH、pc.FITTING_SHRINK、pc.FITTING_BOTHです。

折り返し​

Wrapをオンにすると、行からはみ出す子は新しい行を始めるため、グリッドになります。1行に収まる子の数はグループの幅で決まります。幅100単位の子3つを10単位の間隔で並べるには、幅が320単位以上のグループが必要です。垂直のレイアウトでは、代わりにグループの高さによって、各列に収まる子の数が決まります。

レイアウトチャイルド​

レイアウトグループの子に付けたLayoutChildコンポーネントは、レイアウトがその子のサイズを決める方法を変えます。

プロパティ効果
Min Width、Min Heightレイアウトが子に与える最小のサイズ
Max Width、Max Heightレイアウトが子に与える最大のサイズ。空欄の場合は制限なし
Fit Width Proportion、Fit Height Proportionレイアウトが拡大または縮小するときに、余ったスペースやはみ出した分をどう分けるか。拡大では、2の子は1の子の2倍のスペースを受け取ります。縮小では、比率が大きい子ほど削られる量が少なくなります。100単位の子2つ(比率2と1)を140単位に縮小すると、80と60になります
Exclude from Layout子をレイアウトの対象から外します。子は自身のアンカーと位置を保ちます

例えば、ツールバーを埋めるように拡大される横一列のボタンでは、最大幅を設定すると、そのうちの1つが大きくなるのを止められます。

button.addComponent('layoutchild', {
maxWidth: 120
});

レイアウトの例​

このページの冒頭の画像にあるレイアウトは、次のプロパティを使っています。

プロパティ縦のリストツールバーグリッド
OrientationVerticalHorizontalHorizontal
Alignment0, 10, 0.50.5, 1
Padding10, 10, 10, 1010, 10, 10, 100, 0, 0, 0
Spacing0, 1010, 010, 10
Width FittingStretchStretchNone
Height FittingNoneStretchNone
Wrapオフオフオン
  • 縦のリスト。 各行は高さだけを設定します。Width Fittingによって、行はパディングを除いたリストの幅まで引き伸ばされます。リーダーボードや設定メニューのような形です。
  • ツールバー。 両方の軸でStretchフィッティングを使うと、パディングを除いたツールバーの幅がボタンの間で分け合われ、ボタンの高さはパディングを除いたツールバーの高さになります。そのため、ボタンを追加または削除しても、各ボタンは均等な幅を保ちます。
  • グリッド。 子は100単位四方で、グループの幅は320単位なので、各行に3つずつ収まります。アラインメントが0.5, 1なので、グリッドは上端から始まり、埋まっていない最後の行も含めて各行が中央に揃います。
Layout Group

実行時のレイアウトの変更​

レイアウトグループのプロパティを変更すると、子が再びレイアウトされます。ベクトルを保持するプロパティには、新しいベクトルオブジェクトを代入する必要があります。

list.layoutgroup.spacing = new pc.Vec2(0, 20);
list.layoutgroup.padding = new pc.Vec4(20, 20, 20, 20);
list.layoutgroup.wrap = true;

子を追加、削除、有効化、無効化したときもグループが再びレイアウトされるため、リストは行を追加するにつれて伸びていきます。

const row = new pc.Entity('row');
row.addComponent('element', {
type: pc.ELEMENTTYPE_IMAGE,
height: 60
});
list.addChild(row);

レイアウトグループは、子に合わせて自身のエレメントのサイズを変えることはありません。スクロールビューのコンテンツのサイズをリストに合わせるには、reflowイベントの範囲を使います。

関連情報​