mcpField
P
pixijs-scene-container

pixijs-scene-container

github.com/pixijs開発3586.0k 回インストール4 週間前に更新
リポジトリ

pixijs-scene-container について

PixiJS 開発者向けに、Containerを使ったv8シーングラフの構成を解説するスキルです。子要素の管理、変換、ソート、境界、イベント、ライフサイクル操作を扱います。

主な機能

  1. 01シーンオブジェクトのグループ化とサブツリー変換
  2. 02子要素の順序、追加、再親化の管理
  3. 03変換、境界、座標変換の解説
  4. 04ソートとレンダーグループの説明
  5. 05イベント、描画コールバック、破棄の解説

活用シーン

  1. 01スプライトなどのリーフオブジェクトのグループ化
  2. 02シーン階層と描画順の整理
  3. 03ローカル座標とグローバル座標間の変換
  4. 04シーンのサブツリーの削除または破棄

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pixijs/pixijs-skills --skill pixijs-scene-container

インストール後、Claude Code で/pixijs-scene-containerを入力して読み込まれたか確認します。

詳細

Containerは、PixiJS v8のシーングラフにおける汎用ノードです。子を保持し、サブツリー全体に変換、アルファ、色調、ブレンドモードを適用します。作成するすべての表示オブジェクトは、分岐を構築するContainerか、その中にネストするリーフ(Sprite、Graphics、Text、Mesh)のいずれかです。

pixijs-scene-core-conceptsの内容を理解していることを前提とします。

クイックスタート

const group = new Container({
  label: "hero-group",
  x: 200,
  y: 150,
  sortableChildren: true,
});

const body = new Sprite(await Assets.load("body.png"));
const head = new Sprite(await Assets.load("head.png"));
head.position.set(0, -40);
head.zIndex = 1;

group.addChild(body, head);
group.pivot.set(group.width / 2, group.height / 2);
group.scale.set(1.5);

app.stage.addChild(group);

関連スキル: pixijs-scene-core-concepts(シーングラフの基本概念、マスキング、レイヤー、レンダーグループ)、pixijs-scene-sprite / pixijs-scene-graphics / pixijs-scene-text / pixijs-scene-mesh(コンテナー内に入れるリーフオブジェクト)、pixijs-events(eventMode、ヒットテスト)、pixijs-math(Matrix、toGlobal/toLocalの詳細)、pixijs-performance(cacheAsTexture、カリング、レンダーグループ)。

基本パターン

コンストラクターオプション
const container = new Container({
  label: "world",
  x: 100,
  y: 50,
  scale: 2,
  rotation: Math.PI / 4,
  alpha: 0.8,
  visible: true,
  tint: 0xffaa00,
  blendMode: "add",
  sortableChildren: true,
  isRenderGroup: true,
  origin: { x: 0, y: 0 },
  boundsArea: new Rectangle(0, 0, 1920, 1080),
});

Containerのすべてのオプション(position、scale、tint、label、filters、zIndexなど)はここでも有効です。詳しくはskills/pixijs-scene-core-concepts/references/constructor-options.mdを参照してください。

ContainerコンストラクターはassignWithIgnoreを使用して、オプションオブジェクト内のすべてのフィールドをインスタンスに一括コピーします。ただし、children、parent、effectsは除きます。Containerの公開プロパティはどれもコンストラクターオプションとして指定できます。cullable、cullArea、mask、filterArea、eventMode、hitAreaなどが該当します。上記のオプション一覧では、よく使われるものをまとめています。全項目については、上記の共通リファレンスを参照してください。

isRenderGroup: trueを指定すると、コンテナーが独自のレンダーグループに昇格し、変換が子ごとにCPU上で再計算されるのではなく、GPU上で適用されます。大規模な静的ワールドやUIレイヤーなど、安定したサブツリーで使用してください。多用は避けてください。ほとんどのシーンではレンダーグループを明示的に設定する必要はなく、多すぎるとパフォーマンスが低下します。昇格する前にプロファイリングしてください。詳しくはpixijs-scene-core-concepts/references/scene-management.mdを参照してください。

sortableChildren: trueを指定すると、次のレンダリング時に子がzIndex順に並べ替えられます。詳しくは以下のzIndexを参照してください。

originは、v8で正式に導入された変換ヘルパーです。コンテナーを移動させずに回転や拡大縮小の中心として機能するObservablePointです。pivotは親空間におけるローカル原点の投影位置をずらすため、変更するとオブジェクトが移動します。一方、originは位置をそのまま保ち、指定したローカル座標を中心に回転や拡大縮小を行います。PointData、単一の数値(両軸に適用)、またはcontainer.origin.set(x, y)による実行時の設定を受け付けます。同じコンテナーにpivotとoriginの両方を設定すると効果が重なり、推奨されません。どちらか一方を選んでください。

boundsAreaを設定すると、getBounds()は子を再帰的に計測する代わりに、固定の矩形を返します。安価で予測可能な子を何百個も持つコンテナーでは、パフォーマンスの向上につながります。

cullableとcullAreaは有効なコンストラクターオプションです(assignWithIgnoreの処理でほかのフィールドと同様にコピーされます)。ただし、カリングの設定はシーングラフではなくパフォーマンスに関する内容のため、pixijs-performanceで説明しています。

リーフとコンテナー
const parent = new Container();
const sprite = new Sprite(texture);

parent.addChild(sprite);

子を持つのは、Containerと、子を保持する目的のサブクラス(RenderLayerなど)だけにしてください。PixiJS v8では、慣例としてSprite、Graphics、Text、Mesh、ParticleContainerのパーティクル、DOMContainerのコンテンツはリーフです。オブジェクトをグループ化する必要がある場合は、常にContainerで囲んでください。レイアウトロジックはコンテナーに持たせ、リーフは純粋な視覚データとして保ちます。リーフに子を追加すると非推奨の警告がログに記録され、将来的にはエラーになる予定です。

子の追加と削除
const parent = new Container();

parent.addChild(a, b, c);
parent.addChildAt(d, 0);
parent.swapChildren(a, b);
parent.setChildIndex(c, 0);

parent.removeChild(b);
parent.removeChildAt(0);
parent.removeChildren();

parent.removeChildren(0, 2);

addChild は任意の数の子を受け取り、最初の子を返します。子は配列の順序で描画されます。インデックス 0 が最初(背面)に描画され、最後のインデックスが最後(前面)に描画されます。addChildAt は指定したインデックスに挿入し、setChildIndex は既存の子を移動し、swapChildren は 2 つの子の位置を入れ替えます。

removeChildren(beginIndex?, endIndex?) は範囲を削除し、削除した配列を返します。

すでに同じコンテナーに属している子を指定して addChildAt を呼び出すと、その子は新しいインデックスに移動します。親子関係は変わらないため、added / childAdded / removed / childRemoved イベントは発生しません。イベントが発生するのは、子が別の親(または親なし)から移動してくる場合のみです。

ワールド変換を維持したまま再親化し(子が視覚的に飛び跳ねないようにし)たい場合は、reparentChild / reparentChildAt を使用します。子を同じ位置で入れ替え、古い子のローカル変換を引き継ぐには、replaceChild を使用します。

変換プロパティ
const obj = new Container();

obj.x = 100;
obj.y = 200;
obj.position.set(100, 200);

obj.scale.set(2);
obj.scale = 2;

obj.rotation = Math.PI / 4;
obj.angle = 45;

obj.pivot.set(50, 50);
obj.skew.set(0.1, 0.2);

obj.alpha = 0.5;
obj.tint = 0xff0000;
obj.visible = false;
obj.renderable = false;
  • position、scale、pivot、skew は ObservablePoint です。scale = 2 のように設定すると、両方の軸に値が設定されます。
  • rotation はラジアン、angle は度単位です。これらは同じ値を指すエイリアスで、常に同期します。
  • pivot は、親空間の position に対応するローカル空間の点を設定します。これを変更すると、コンテナーの位置と回転の両方が変わります。
  • alpha と tint は子孫にも乗算されます。blendMode はこのコンテナーの描画命令に適用されます。
  • visible = false にすると、レンダリングと変換の更新がスキップされます。renderable = false にすると、レンダリングはスキップされますが、変換は更新されます(描画せずに getBounds() やヒットテストを行う場合に使用します)。
zIndex と sortableChildren
const world = new Container({ sortableChildren: true });

const ground = new Sprite(groundTexture);
ground.zIndex = 0;

const player = new Sprite(playerTexture);
player.zIndex = 10;

const ui = new Sprite(uiTexture);
ui.zIndex = 100;

world.addChild(ground, player, ui);

sortableChildren が true の場合、次のレンダリング前にコンテナーの子が zIndex の順に並べ替えられます。子の zIndex を変更すると、親は自動的に並べ替えが必要な状態に設定されます。必要なものだけを並べ替えてください。sortableChildren を無効のままにしておくほうが効率的です。完全に手動で制御したい場合は、zIndex の値を変更したあとに container.sortChildren() を呼び出します。

階層構造から切り離して描画順を制御する場合(子は変換用の論理的な親を維持しつつ、別の z で描画する場合)は、RenderLayer を使用します。pixijs-scene-core-concepts/references/scene-management.md を参照してください。

境界と座標変換
const bounds = container.getBounds();
console.log(bounds.x, bounds.y, bounds.width, bounds.height);

const rect = container.getBounds().rectangle;

const local = new Point(10, 20);
const world = container.toGlobal(local);
const backToLocal = container.toLocal(world);

const selfPos = container.getGlobalPosition();

getBounds() は Bounds オブジェクト(Rectangle ではありません)を返します。このオブジェクトは x、y、width、height と、実際の Rectangle を必要とする API 向けの .rectangle ゲッターを公開します。シグネチャーは getBounds(skipUpdate?: boolean, bounds?: Bounds) です。強制的な変換の更新をスキップするには、最初の引数に true を渡します。新しいオブジェクトの割り当てを避けるには、2 番目の引数に任意の Bounds インスタンスを渡します。

toGlobal(point) は、このコンテナーのローカル空間内の点をシーンルート空間に変換します。toLocal(point, from?) は、別のコンテナーのローカル空間から(from を省略した場合はグローバル空間から)変換します。getGlobalPosition() は parent.toGlobal(this._position) の省略形です。

サイズ設定
const sprite = new Sprite(texture);

sprite.setSize(200, 100);
const { width, height } = sprite.getSize();

setSize は、1 回の操作でコンテナーの境界が指定されたピクセルサイズに収まるように scale を調整します。.width と .height を個別に設定することもできますが、代入のたびに境界が再計算されます。両方の軸を変更する場合は、setSize を使用してください。

コンテナーイベント
const parent = new Container();

parent.on("childAdded", (child, container, index) => {
  console.log("added at", index, child.label);
});

parent.on("childRemoved", (child, container, index) => {
  console.log("removed from", index);
});

const child = new Container();
child.on("added", (newParent) => console.log("entered", newParent.label));
child.on("removed", (oldParent) => console.log("left", oldParent.label));
child.on("visibleChanged", (visible) => console.log("visible:", visible));
child.on("destroyed", (destroyed) => console.log("gone", destroyed.label));

parent.addChild(child);
イベント発生する対象引数
childAdded子を受け取る親(child, container, index)
childRemoved子を失う親(child, container, index)
added追加された子(parent)
removed切り離された子(parent)
destroyed破棄されたコンテナー(container)
visibleChangedvisible の値が変わったコンテナー(visible)

これらは Container の EventEmitter 側で発行されます。pixijs-events のポインターイベントと混同しないでください。

destroyed は内部クリーンアップの後、リスナーが削除される前に発生します。そのため、ハンドラーの実行時には、position、scale、pivot、origin、skew、parent はすでに null に設定され、children は空になっています(長さは 0 ですが、配列への参照自体は null になりません)。必要なデータは、ハンドラー内ではなく、destroy() を呼び出す前にコンテナーから取得してください。

onRender によるフレームごとの更新
const container = new Container();

container.onRender = (renderer) => {
  container.rotation += 0.01;
};

container.onRender = null;

onRender はコンテナーのレンダリング中、毎フレーム実行され、アクティブな Renderer を受け取ります。特定のコンテナーに関連付けられた軽量なアニメーションやフレームごとの更新に使用してください。v7 では updateTransform をオーバーライドするこのパターンが使われていましたが、v8 では毎フレーム実行されなくなりました。コールバックを解除するには、onRender = null を設定してください。

親からの検索と削除
const player = world.getChildByLabel("player");
const enemies = world.getChildrenByLabel(/enemy-\d+/, true);

const bounds = hud.getLocalBounds();

oldSprite.removeFromParent();
  • getChildByLabel(label, deep?) — 文字列または RegExp に最初に一致するものを取得します。再帰検索するには true を渡します。
  • getChildrenByLabel(label, deep?, out?) — 一致するものをすべて取得します。再利用可能な出力配列を任意で指定できます。
  • getLocalBounds() — 親の変換を無視した、このコンテナー独自の座標空間での境界です。自己完結型のレイアウト計算では getBounds() より低コストです。
  • removeFromParent() — 現在の親から this を切り離します(すでに親がない場合は何もしません)。
破棄
container.destroy();

container.destroy({
  children: true,
  texture: true,
  textureSource: true,
});

console.log(container.destroyed);

デフォルトでは、destroy() はこのコンテナーを親から切り離し、自身の状態を破棄します。{ children: true } を渡すと、すべての子孫を再帰的に破棄します。サブツリー全体を破棄する場合は、通常この呼び出しを使います。texture: true と textureSource: true を指定すると、さらに葉の子が参照する GPU リソースも破棄されます(その子専用に読み込んだテクスチャを持つスプライトで便利です)。cacheAsTexture が有効な場合は、破棄する前に container.cacheAsTexture(false) で無効にしてください。

よくある間違い

[CRITICAL] 葉となるシーンオブジェクトへの子の追加

誤り:

const sprite = new Sprite(texture);
const overlay = new Sprite(overlayTexture);
sprite.addChild(overlay);

正しい例:

const group = new Container();
const sprite = new Sprite(texture);
const overlay = new Sprite(overlayTexture);
group.addChild(sprite, overlay);

Sprite、Graphics、Text、Mesh は葉です。これらに子を追加すると、現在は非推奨の警告がログに出力され、将来のバージョンではエラーになります。グループ化が必要な場合は、必ず Container でラップしてください。

[HIGH] getBounds() が Rectangle を返すと想定する

誤り:

const rect = container.getBounds();
rect.contains(x, y); // TypeError: contains is not a function

正しい例:

const rect = container.getBounds().rectangle;
rect.contains(x, y);

const bounds = container.getBounds();
console.log(bounds.width, bounds.height);

v8 では、getBounds() は Bounds インスタンスを返します。基本的なゲッター(x、y、width、height)は使用できますが、.contains() などの Rectangle 固有のメソッドを使う場合や、Rectangle を必要とする API に渡す場合は、.rectangle プロパティを参照してください。

[HIGH] cacheAsTexture の代わりに cacheAsBitmap を使用する

誤り:

container.cacheAsBitmap = true;

正しい例:

container.cacheAsTexture(true);

cacheAsBitmap(v7 のプロパティ)は、v8 で cacheAsTexture()(メソッド)に名前が変更されました。destroy() を呼び出す前に、必ず cacheAsTexture(false) で無効にしてください。

[MEDIUM] container.label の代わりに container.name を使用する

v8 では、name は label に名前が変更されました。古いプロパティも非推奨のエイリアスとして引き続き機能します。子を名前で検索するには、v8 では getChildByLabel を使います。

[MEDIUM] 同じコンテナーに pivot と origin の両方を設定する

pivot は親空間におけるローカル原点の投影位置をずらします(回転の中心を変更することで、オブジェクトの位置も副作用として変化します)。origin は移動させずに、回転/スケールの中心を変更します。同じコンテナーに両方を設定すると、予期しない相乗効果が生じるため、どちらか一方を選んでください。

API リファレンス

コメント