pixijs-scene-graphics について
PixiJS v8 開発者向けの Graphics スキルで、シーングラフ内のベクター図形、パス、スタイル設定を解説します。グラデーション、テクスチャ、切り抜き、SVG、描画コンテキストの共有も扱います。
主な機能
- 01図形と複雑なパスの描画
- 02塗り、線、グラデーション、パターンの適用
- 03cut() による穴の作成
- 04SVG のインポートとエクスポート
- 05GraphicsContext の共有
活用シーン
- 01UI グラフィックやベクター要素の描画
- 02グラデーションやテクスチャ付き図形の作成
- 03Graphics のマスクとしての利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pixijs/ pixijs-skills --skill pixijs-scene-graphicsインストール後、Claude Code で/pixijs-scene-graphicsを入力して読み込まれたか確認します。
詳細
Graphics は、PixiJS v8 シーングラフにおけるベクター描画用のリーフです。v8 の API は、図形を描画してからスタイルを設定するパターンに従います。rect や circle、moveTo などで図形またはパスを描画し、その後 fill や stroke を適用します。すべてのメソッドはチェーンできるよう this を返し、描画命令は複数のインスタンスで共有できる GraphicsContext に保持されます。
pixijs-scene-core-concepts の知識があることを前提としています。Graphics はリーフです。内部に子をネストしないでください。複数の Graphics オブジェクトをまとめるには、Container でラップします。
クイックスタート
const g = new Graphics();
g.rect(10, 10, 200, 100)
.fill({ color: 0x3498db, alpha: 0.8 })
.stroke({ width: 3, color: 0x2c3e50 });
g.circle(300, 60, 40).fill(0xe74c3c);
g.moveTo(50, 200)
.lineTo(200, 200)
.bezierCurveTo(250, 250, 100, 300, 50, 250)
.closePath()
.fill(0x6c5ce7);
app.stage.addChild(g);
関連スキル: pixijs-scene-core-concepts(シーングラフの基本)、pixijs-scene-container(グラフィックスを他のオブジェクトとグループ化)、pixijs-scene-core-concepts/references/masking.md(Graphics をステンシルマスクとして使用)、pixijs-filters(エフェクト)、pixijs-performance(バッチ処理、cacheAsTexture)。
コンストラクターオプション
すべての Container オプション(position、scale、tint、label、filters、zIndex など)もここで有効です。詳しくは skills/pixijs-scene-core-concepts/references/constructor-options.md を参照してください。
GraphicsOptions で追加される、リーフ固有のオプション:
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
context | GraphicsContext | new GraphicsContext() | 共有描画コンテキストです。コンテキストを渡すと、複数の Graphics ノード間でテッセレーション済みジオメトリが再利用され、GPU 処理の重複を避けられます。省略した場合、各 Graphics が新しいコンテキストを作成して所有します。 |
roundPixels | boolean | false | 画面上の最終的な x/y を最も近いピクセルに丸めます。滑らかなサブピクセル移動を犠牲にして、ピクセルアートスタイルの線をより鮮明に表示します。 |
コンストラクターには、唯一の引数として GraphicsContext インスタンスを渡すこともできます(new Graphics(ctx))。これは new Graphics({ context: ctx }) の省略形です。
基本パターン
形状を作成してから塗りつぶすワークフロー
const g = new Graphics();
g.rect(10, 10, 200, 100)
.fill({ color: 0x3498db, alpha: 0.8 })
.stroke({ width: 3, color: 0x2c3e50 });
g.circle(150, 200, 40).fill(0xe74c3c);
g.roundRect(300, 10, 150, 80, 12).fill(0x2ecc71);
g.poly([0, 0, 60, 0, 30, 50], true).fill(0x9b59b6);
g.star(400, 200, 5, 40, 20, 0).fill(0xf39c12);
g.ellipse(100, 350, 60, 30).fill(0x1abc9c);
fill() は FillInput を受け取ります。値は色番号/文字列、{ color, alpha, texture, matrix, textureSpace }、FillGradient、FillPattern、または Texture です。テクスチャで塗りつぶす場合、textureSpace で座標マッピングを制御します。
'local'(デフォルト):テクスチャを各形状の境界ボックスに合わせて拡大縮小します(0~1 の正規化座標)。'global':テクスチャの位置とスケールはGraphicsオブジェクトの座標系を基準とし、すべての形状で共有されます。- アトラスのサブテクスチャ:
'global'ではフレームの原点と回転が考慮されるため、フレームと同じサイズで描画した形状は、そのフレームのSpriteと一致します。'local'ではソース画像全体がマッピングされます。ソース内のフレーム領域を指定するmatrixを渡すか、先にフレームをrenderer.generateTexture()に渡してください。
FillInput はネストされた fill サブフィールドにも対応しています。FillStyle オプションオブジェクトの fill キーに FillGradient または FillPattern を含めると、外側のオブジェクトの color、alpha、texture、matrix の修飾子とともにグラデーションまたはパターンが適用されます。
stroke() は、色、FillGradient、FillPattern、またはすべての FillStyle キー(color、alpha、texture、matrix、fill、textureSpace)とストローク属性を組み合わせた StrokeStyle オブジェクトを受け取ります。
| 属性 | デフォルト | 説明 |
|---|---|---|
width | 1 | ストロークのピクセル幅です。 |
cap | 'butt' | 'butt'、'round'、'square' のいずれかです。開いたパスの端のスタイルです。 |
join | 'miter' | 'miter'、'round'、'bevel' のいずれかです。角のスタイルです。 |
miterLimit | 10 | マイター結合がベベルに切り替わるまでの延長距離の上限です。 |
alignment | 0.5 | 1 = 形状の内側、0.5 = 中央、0 = 外側です。 |
pixelLine | false | 1 ピクセル幅の線をピクセルグリッドに揃え、くっきりと描画します。Graphics 専用です。 |
ストロークには、fill: gradient または texture: tex を指定して、塗りつぶしと同じグラデーションやパターンを使用できます。
const grad = new FillGradient({
end: { x: 1, y: 0 },
colorStops: [
{ offset: 0, color: 0xff0000 },
{ offset: 1, color: 0x0000ff },
],
});
g.rect(0, 0, 200, 100).stroke({
width: 8,
fill: grad,
join: "round",
cap: "round",
});
fill() と stroke() は、同じ形状の後にどちらも呼び出せます。fill() の直後に stroke() を呼び出すと、同じパスが再利用されます。
高度な形状プリミティブ
g.regularPoly(100, 100, 50, 6, 0).fill(0x3498db);
g.roundPoly(250, 100, 50, 5, 10).fill(0xe74c3c);
g.chamferRect(350, 50, 100, 80, 15).fill(0x2ecc71);
g.filletRect(500, 50, 100, 80, 15).fill(0x9b59b6);
g.roundShape(
[
{ x: 50, y: 250, radius: 20 },
{ x: 150, y: 250, radius: 5 },
{ x: 150, y: 350, radius: 10 },
{ x: 50, y: 350, radius: 15 },
],
10,
).fill(0xf39c12);
cut() による穴あけ
g.rect(0, 0, 200, 200).fill(0x00ff00).circle(100, 100, 50).cut();
cut() は、現在のアクティブパスを、以前に描画された塗りつぶしまたはストロークから差し引きます。ルールは次のとおりです。
- 穴は対象の形状の完全に内側にある必要があります。レンダラーは穴を内側の境界として三角形分割するため、端に重なる穴や形状の外側にある穴は正しく描画されません。
cut()は直前の最大 2 つの命令を参照します。同じパスに対してfill()の後にstroke()を呼び出した場合、cut()を 1 回呼び出すと、まずストロークに穴が追加されます。2 回目のcut()で、その下にある塗りつぶしに穴が追加されます。cut()の後、アクティブパスはリセットされるため、moveTo、rectなどで次の形状を開始できます。cut()はストロークにも適用されます。g.rect(...).stroke(...).circle(...).cut()のようにすると、ストロークの輪郭に穴をあけられます。
cut() を呼び出す前にアクティブパスへ複数の形状を描画すると、1 回の cut() で複数の穴をあけられます。各形状は同じ穴パスに追加されます。
const g = new Graphics();
g.rect(350, 350, 150, 150).fill(0x00ff00);
// Draw three circles into the active path, then cut them all in one call
g.circle(375, 375, 25);
g.circle(425, 425, 25);
g.circle(475, 475, 25);
g.cut();
別々の塗りつぶし形状に穴をあける必要がある場合は、各形状に個別の fill() と対応する cut() を指定してください。
g.rect(0, 0, 100, 100).fill(0x3498db);
g.circle(50, 50, 20).cut(); // hole in the rect
g.rect(120, 0, 100, 100).fill(0xe74c3c);
g.circle(170, 50, 20).cut(); // hole in the second rect
すでに穴がある形状に cut() を呼び出すと、既存の穴パスを置き換えるのではなく、新しい穴が追加されます。これを使って穴を重ねて追加できます。
パスと複雑な形状
g.moveTo(50, 50)
.lineTo(200, 50)
.bezierCurveTo(250, 100, 250, 150, 200, 200)
.quadraticCurveTo(100, 250, 50, 200)
.closePath()
.fill({ color: 0x6c5ce7, alpha: 0.7 })
.stroke({ width: 2, color: 0xdfe6e9 });
パスメソッド:moveTo、lineTo、bezierCurveTo、quadraticCurveTo、arc、arcTo、arcToSvg、closePath。現在のパスを破棄して新しいパスを開始するには、beginPath() を呼び出します。
// arc(cx, cy, radius, startAngle, endAngle, counterclockwise?)
g.moveTo(80, 50)
.arc(50, 50, 30, 0, Math.PI)
.stroke({ width: 4, color: 0x2c3e50 });
// arcTo(x1, y1, x2, y2, radius) — rounded corner between two line segments
g.moveTo(150, 20)
.arcTo(200, 20, 200, 80, 20)
.lineTo(200, 80)
.stroke({ width: 2 });
// arcToSvg(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) — matches the SVG `A` command
g.moveTo(250, 50).arcToSvg(40, 20, 0, 1, 0, 330, 50).stroke({ width: 2 });
グラデーションとパターン
// Linear gradient
const linear = new FillGradient({
end: { x: 1, y: 0 },
colorStops: [
{ offset: 0, color: 0xff0000 },
{ offset: 1, color: 0x0000ff },
],
});
g.rect(0, 0, 200, 100).fill(linear);
// Radial gradient. Coordinates are normalized 0-1 in the default "local" space:
// inner circle at the center, outer circle reaching the edges.
const radial = new FillGradient({
type: "radial",
center: { x: 0.5, y: 0.5 },
innerRadius: 0,
outerCenter: { x: 0.5, y: 0.5 },
outerRadius: 0.5,
colorStops: [
{ offset: 0, color: 0xffffff },
{ offset: 1, color: 0x000000 },
],
});
g.circle(100, 100, 100).fill(radial);
// Pixel coordinates need textureSpace: "global"; the gradient then spans shapes.
const shared = new FillGradient({
type: "radial",
center: { x: 100, y: 100 },
outerRadius: 100,
textureSpace: "global",
colorStops: [
{ offset: 0, color: 0xffffff },
{ offset: 1, color: 0x000000 },
],
});
g.rect(0, 0, 200, 200).fill(shared);
const brick = await Assets.load("brick.png");
// Options-object form (preferred)
const pattern = new FillPattern({
texture: brick,
repetition: "repeat", // 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'
textureSpace: "global", // 'global' (default) | 'local'
});
// Legacy positional form is still supported
const pattern2 = new FillPattern(brick, "repeat");
g.rect(0, 120, 200, 100).fill(pattern);
FillGradient のデフォルトの type は 'linear' で、開始位置は {0,0}、終了位置は {0,1}(垂直方向)です。放射状グラデーションには、center/innerRadius と outerCenter/outerRadius を指定して type: 'radial' を設定します。rotation(ラジアン、デフォルトは 0)と scale(デフォルトは 1)を使うと楕円形になり、Graphics のみに適用されます。textureSpace のデフォルトは 'local'(正規化された 0〜1 の図形座標)です。図形間で共有されるピクセル座標を使うには、'global' を指定します。
FillPattern には、オプションオブジェクト({ texture, repetition?, textureSpace? })または従来の位置引数形式(new FillPattern(texture, repetition?))を指定します。repetition はタイルの繰り返しモードを選択します。textureSpace は、タイルを図形にどのように適用するかを制御します。
'global'(デフォルト):タイルはGraphicsの座標系全体で連続して繰り返されるため、隣接する図形は同じタイルグリッドを共有します。背景やシームレスなテクスチャに最適です。'local':1 つのタイルが各図形の境界に収まります。setTransformと組み合わせて、図形をタイルグリッドに分割できます。
FillPattern の textureSpace のデフォルトは 'global' であり、上記のテクスチャ塗りつぶしのデフォルト 'local' とは異なることに注意してください。
setTransform(matrix) は、指定した行列をパターンの変換に直接コピーし、タイルの拡大縮小、回転、オフセットを行います。引数を指定せずに setTransform() を呼び出すと、単位行列にリセットされます。
textureSpace と変換は、FillPattern 自体に設定してください。パターンをスタイルオブジェクト内で渡す場合(fill({ fill: pattern, textureSpace: "local" }))、パターン自身の値がスタイルの textureSpace と matrix に置き換わります。
テクスチャを直接描画する
const tex = await Assets.load("icon.png");
// Draw the whole texture at (x, y) with optional tint
g.texture(tex, 0xffffff, 20, 20);
// Draw a subregion (dx, dy, dw, dh)
g.texture(tex, 0xff0000, 100, 20, 64, 64);
Graphics.texture(texture, tint?, dx?, dy?, dw?, dh?) は、fill() を経由せずにテクスチャ付きの矩形を 1 つ描画するショートカットです。完全なスプライトのライフサイクルが不要なアイコンに便利です。
GraphicsContext の共有
const ctx = new GraphicsContext().rect(0, 0, 50, 50).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx);
g2.x = 100;
コンテキストを共有すると GPU ジオメトリの重複を避けられ、高コストなテッセレーションを 1 回だけ実行できます。構築後にコンテキストを割り当てることもできます:g.context = existingContext。
SVG のインポートとエクスポート
svg() を使用して、SVG マークアップをアクティブなコンテキストに解析します。
g.svg(`<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="red"/>
</svg>`);
svg() は、<path>(fill-rule="evenodd" の穴を含む)、<rect>、<circle>、<ellipse>、<line>、<polygon>、<polyline>、およびグループ化する <g> を解析します。スタイルは、属性またはインラインの style として指定された fill、stroke、stroke-width、fill-opacity、stroke-opacity、opacity から取得されます。<defs> 内の <linearGradient> と <radialGradient> の定義は FillGradient になり、url(#id) を通じて適用されます。gradientUnits は textureSpace に対応し、パーセント座標も使用できます。サポート対象外:transform 属性、<style> ブロック、stroke-linecap/stroke-linejoin/stroke-dasharray、gradientTransform、spreadMethod、stop-opacity、<text>、<image>、<use>、<clipPath>、<mask>、<pattern>。サポート対象外の要素は警告をログに記録してスキップされます。複雑な穴のあるジオメトリは、Pixi の三角形分割がパフォーマンス向けに最適化されているため、正確に描画されない場合があります。
graphicsContextToSvg を使用して、Graphics または GraphicsContext を自己完結型の SVG ドキュメント文字列にシリアライズします。
import { Graphics, graphicsContextToSvg } from "pixi.js";
const g = new Graphics()
.rect(0, 0, 100, 50)
.fill({ color: 0xff0000 })
.circle(150, 25, 25)
.stroke({ color: 0x0000ff, width: 4 });
const svgString = graphicsContextToSvg(g, 2);
graphicsContextToSvg(source, precision = 2) は、コンテキストの命令を読み取り、自動計算された viewBox を含む完全な <svg> 文字列を返す純粋関数です。Graphics または GraphicsContext を渡します。precision は、出力される座標の小数点以下の桁数を指定します。すべてのシェイプの後に塗りつぶしを行うプリミティブ(regularPoly/filletRect などの高度なものはシェイプパスにフォールバックします)、すべてのパスメソッド、ストローク属性(width、cap、join、miterLimit)、fill-opacity/stroke-opacity、および <defs> ブロックを使用した FillGradient(線形および放射状)をエクスポートします。穴は、fill-rule="evenodd" を指定した 1 つの <path> にまとめられます。FillPattern とテクスチャ塗りつぶしには SVG に相当するものがありません。パターンは塗りつぶしの単色の color にフォールバックし、texture() 命令は完全にスキップされます。エクスポートされたマークアップは、クリーンアップなしで g.svg(...) を通じてラウンドトリップできるため、シェイプをエクスポートして保存し、後から別の Graphics に再インポートできます。
GraphicsPath の再利用
const arrow = new GraphicsPath()
.moveTo(0, 0)
.lineTo(40, 0)
.lineTo(40, -10)
.lineTo(60, 10)
.lineTo(40, 30)
.lineTo(40, 20)
.lineTo(0, 20)
.closePath();
g.path(arrow).fill(0x3498db);
g.translateTransform(80, 0).path(arrow).fill(0xe74c3c);
Graphics.path(graphicsPath)(および GraphicsContext.path())は、事前に作成した GraphicsPath をアクティブなパスに追加します。一度作成すれば、何度でも描画できます。
描画時の変換
Graphics には、描画中に使用する独自の変換スタックがあります。これは、レンダリング出力に適用される Container の変換とは別です。描画メソッドは、Container.rotation、Container.scale、Container.position と名前が衝突しないように名称が変更されています。
| 描画変換 | Container の変換 |
|---|---|
g.rotateTransform(angle) | g.rotation |
g.scaleTransform(x, y?) | g.scale.set(x, y) |
g.translateTransform(x, y?) | g.position.set(x, y) |
g.setTransform(matrix) または setTransform(a,b,c,d,tx,ty) | g.setFromMatrix(matrix) |
g.transform(matrix) または transform(a,b,c,d,tx,ty) | 該当なし |
g.getTransform()/g.resetTransform() | 該当なし |
const g = new Graphics();
g.translateTransform(100, 100)
.rotateTransform(Math.PI / 4)
.rect(-25, -25, 50, 50)
.fill(0x3498db);
// The square is rotated 45 degrees as it is added to the geometry.
// Setting g.rotation later rotates the entire Graphics on screen.
描画変換は、コンテキストに追加される以降のすべてのシェイプおよびパスの命令に影響します。save()/restore() を使用して適用範囲を限定します。
状態の保存と復元
g.save();
g.translateTransform(100, 100);
g.rotateTransform(Math.PI / 4);
g.rect(0, 0, 50, 50).fill(0xff0000);
g.restore();
save() は描画変換、塗りつぶしスタイル、ストロークスタイルをスタックにプッシュし、restore() はそれらをポップします。Graphics は、基盤となる GraphicsContext の呼び出しに合わせて、save/restore を直接公開します。
setFillStyle / setStrokeStyle によるデフォルトスタイル
g.setFillStyle({ color: 0x3498db, alpha: 0.8 }).setStrokeStyle({
width: 2,
color: 0x2c3e50,
});
g.rect(0, 0, 100, 100).fill().stroke();
g.circle(150, 50, 40).fill().stroke();
setFillStyle() と setStrokeStyle() は、引数なしで後続の fill() / stroke() を呼び出したときに使われるデフォルトスタイルを設定します。fillStyle および strokeStyle のゲッター/セッターを使って、いつでも現在のスタイルを読み取ったり変更したりできます。起動時に GraphicsContext.defaultFillStyle と GraphicsContext.defaultStrokeStyle を変更すると、ライブラリ全体のデフォルトを上書きできます。
ヒットテスト
const g = new Graphics().star(100, 100, 5, 60, 30).fill(0xf39c12);
g.eventMode = "static";
g.on("pointermove", (e) => {
if (g.containsPoint(g.toLocal(e.global))) {
/* over the star, not just its bbox */
}
});
Graphics.containsPoint(pointInLocalSpace) は、穴を含め、コンテキスト内の塗りつぶされた図形とストロークされた図形すべてに対して、トポロジーを考慮したテストを実行します。グローバル座標のポインター座標は、まず toLocal() で変換してください。ストロークされた図形のヒットテストは、描画されたストロークを対象とします。ヒット領域はストロークの width と alignment(1 は内側、0.5 は中央、0 は外側)に沿い、ポリゴンの頂点順序には左右されません。
クローン、クリア、境界
const g = new Graphics().rect(0, 0, 100, 100).fill(0xff0000);
const shallow = g.clone(); // shares the same GraphicsContext
const deep = g.clone(true); // creates an independent context
console.log(g.bounds.width); // 100 - geometry bounds before transforms
g.clear(); // wipes active path, instructions, and transform; fill/stroke styles persist
clone()は、元のコンテキストを共有する新しいGraphicsを返します(低コストで、ジオメトリを再利用します)。コンテキストが変更されると、両方のオブジェクトが同時に更新されます。clone(true)はコンテキストも複製するため、新しいGraphicsを独立して編集できます。boundsは、Containerの変換前のジオメトリ境界を返します。レイアウトを決める際に便利です。clear()はコンテキストをリセットし、同じGraphicsを再利用できるようにします。ジオメトリをクリアする場合と安定した状態に保つ場合の判断については、以下のよくある間違いを参照してください。
GraphicsContext ユーティリティ
| メンバー | 動作 |
|---|---|
ctx.path(graphicsPath) | 事前に作成した GraphicsPath をアクティブパスに適用します。1 つのパスを複数のコンテキストやフレームで再利用できます。 |
ctx.beginPath() | コミット済みの命令には影響を与えず、現在のアクティブパスを破棄して新しいパスを開始します。 |
ctx.setFillStyle(style) / ctx.fillStyle | fill() を呼び出さずに、後続の図形で使用するデフォルトの塗りつぶしスタイルを設定または取得します。 |
ctx.setStrokeStyle(style) / ctx.strokeStyle | stroke() を呼び出さずに、後続の図形で使用するデフォルトのストロークスタイルを設定または取得します。 |
ctx.bounds | すべての塗りつぶし/ストローク/テクスチャ命令を対象とした、キャッシュ済みのジオメトリ境界です。 |
ctx.clear() | 命令、アクティブパス、描画変換を消去します。 |
ctx.clone() | 命令、アクティブパス、変換、スタイル、スタックを含めてディープコピーします。 |
ctx.containsPoint(point) | 塗りつぶされた図形とストロークされた図形すべて(穴を含む)に対して、トポロジーを考慮したヒットテストを実行します。 |
ctx.batchMode | 'auto'、'batch'、'no-batch' のいずれかです。このコンテキスト内の図形のバッチ処理を強制または無効にします。 |
ctx.customShader | デフォルトのグラフィックスシェーダーを上書きする Shader を割り当てます。 |
GraphicsContext.defaultFillStyle | 引数なしで fill() が呼び出され、塗りつぶしスタイルも設定されていない場合に使われる静的なフォールバックです。 |
GraphicsContext.defaultStrokeStyle | 引数なしで stroke() が呼び出され、ストロークスタイルも設定されていない場合に使われる静的なフォールバックです。 |
GraphicsContext は EventEmitter であり、update、destroy、unload イベントを発行します。ツールやプールでコンテキストのライフサイクルの変更に対応する必要がある場合は、ctx.on('update' | 'destroy' | 'unload', cb) でサブスクライブしてください。
よくある間違い
[CRITICAL] v7 の beginFill/drawRect/endFill を使用する
誤り:
const g = new Graphics().beginFill(0xff0000).drawRect(0, 0, 100, 100).endFill();
正しい例:
const g = new Graphics().rect(0, 0, 100, 100).fill(0xff0000);
v8 では、「スタイルを設定して、描画し、終了する」方式から「図形を描画してからスタイルを適用する」方式に変更されました。beginFill/endFill は存在しません。
[CRITICAL] 旧式の図形メソッド名を使用する
誤り:
g.drawCircle(50, 50, 25);
正しい例:
g.circle(50, 50, 25);
v8 では、すべての draw* メソッドの名前が変更されました:drawRect → rect、drawCircle → circle、drawEllipse → ellipse、drawPolygon → poly、drawRoundedRect → roundRect、drawStar → star。
[CRITICAL] stroke の代わりに lineStyle を使用する
誤り:
g.lineStyle(2, 0xffffff);
g.drawRect(0, 0, 100, 100);
正しい例:
g.rect(0, 0, 100, 100).stroke({ width: 2, color: 0xffffff });
lineStyle は削除されました。図形を描画した後に stroke() を使用してください。stroke のオプションオブジェクトでは、width、color、alpha、cap、join、alignment、miterLimit、pixelLine を指定できます。
[HIGH] 穴に beginHole/endHole を使用する
誤り:
g.beginFill(0x00ff00)
.drawRect(0, 0, 100, 100)
.beginHole()
.drawCircle(50, 50, 20)
.endHole()
.endFill();
正しい例:
g.rect(0, 0, 100, 100).fill(0x00ff00).circle(50, 50, 20).cut();
beginHole/endHole は cut() に置き換えられました。外側の図形を描画して塗りつぶし、その後に穴の図形を描画して cut() を呼び出してください。
[HIGH] GraphicsContext の代わりに GraphicsGeometry を使用する
誤り:
const geom = g.geometry;
const clone = new Graphics(geom);
正しい例:
const ctx = new GraphicsContext().rect(0, 0, 100, 100).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx);
v8 では、GraphicsGeometry が GraphicsContext に置き換えられました。.geometry プロパティはありません。
[HIGH] 共有 GraphicsContext を誤って破棄する
const ctx = new GraphicsContext().rect(0, 0, 50, 50).fill(0xff0000);
const g1 = new Graphics(ctx);
const g2 = new Graphics(ctx);
g1.destroy({ context: true }); // g2 is left holding a destroyed context
共有された GraphicsContext を破棄しても、それを使用する他の Graphics は破棄されませんが、破棄済みのコンテキストへの参照は保持されるため、正しく更新または描画されなくなります。コンストラクター経由でコンテキストを渡した場合、引数なしの destroy() はコンテキストを保持し、そのインスタンスを切り離します。明示するには destroy({ context: false }) を使用してください。共有しているすべてのインスタンスで使い終わってから、コンテキストを破棄してください。自己所有のコンテキスト(コンストラクター経由で渡されていないもの)は、引数なしの destroy() でも破棄されます。
[HIGH] 毎フレーム Graphics をクリアして再描画する
Graphics は動的ではなく、状態が安定した状態で使うように設計されています。毎フレーム clear() を呼び出して再描画すると、そのたびに GPU ジオメトリが再構築されます。動的なビジュアルには、次の方法を使用してください。
- 事前にレンダリングしたテクスチャとトランスフォームの変更を使用する
Sprite。 - 複雑で静的なグラフィックスには
cacheAsTexture(true)。 - リアルタイムで図形を変更する場合は、カスタムジオメトリを更新する
Meshを検討してください。
これは、毎フレームの再描画が一般的な HTML Canvas 2D とは逆です。PixiJS は図形を GPU の三角形にテッセレーションするため、初回の描画にはコストがかかりますが、その後のレンダリングは高速です。Graphics はキャンバスの描画呼び出しよりも、SVG 要素に近いものとして扱ってください。
[MEDIUM] Graphics の中に子要素を入れない
Graphics は allowChildren = false に設定されています。子要素を追加すると非推奨の警告がログに記録され、将来のバージョンではエラーになります。複数の Graphics を他のリーフ要素と一緒に配置する場合は、通常の Container でラップしてください。
const group = new Container();
group.addChild(graphics, sprite);