PerfectVector
著者: Irene Kim2 分で読める

PixiJSのSVG読み込み:Graphicsとテクスチャを選ぶ

PixiJSへSVGを形状またはテクスチャとして読み込みます。2つのサイズでアイコンを試し、解像度とグループ変換の欠落を納品前に確認します。

目次

PixiJSでは、SVGを2つの方法で使えます。Graphics.svg()は対応する描画形状を解析し、SVGをテクスチャとして読み込む方法はSpriteに表示用のピクセルを与えます。大きく拡大縮小する画像には形状を選び、想定表示サイズに合うラスターで十分な素材にはテクスチャを選びます。PixiJSのSVGガイドは両方の方法を説明しています。

選ぶ前に、同じファイルを両方の方法で試してください。今回の小さなエンブレムは、どちらでも穴と色を保持しましたが、形状の方法ではグループの移動変換が欠落しました。テクスチャはブラウザーの配置に一致しましたが、拡大するとぼやけました。これらは別の問題で、対処法も異なります。

シーンに必要なものを決める

要件最初に試す方法承認時の確認
サイズが変わる単純なアイコンGraphics.svg(svgText)曲線、穴、変換、描画が元データと一致するか
固定サイズの装飾画像SVGテクスチャとSprite最大表示サイズに十分なテクスチャのピクセル数か
同じ形状の複数インスタンス共有するGraphicsContext意図した共有描画データを使っているか
ノード編集やSVG書き出しSVGエディターと元ファイルを保持編集可能なマスターがPixiのシーン外に残るか

GraphicsオブジェクトはPixiの描画内容であり、元の要素IDを持つSVGのDOMツリーではありません。Graphicsガイドが説明するように、そのコンテキストはインスタンス間で共有できます。個々の元パスを編集したり、後で別のSVGを書き出したりする必要がある場合は、元SVGを保持します。どちらの方法も、最終的には画面にピクセルを描画します。

曲線、穴、変換をテストする

この例はPixiJS 8.21.0、96 × 96のSVG、レンダラーの解像度1、解像度1で読み込んだSVGテクスチャを使います。小さい版は元サイズで描画し、大きい版は倍率3を使います。独自のエンブレムには2色のパスと、各方向に8 SVG単位移動したグループがあります。穴を作るため、内側の輪郭は外側と逆向きに巻いています。

同じ独自SVGを3つのレンダラーで比較
元サイズと3倍サイズでのブラウザーSVG、PixiJS Graphics、SVGテクスチャの比較。Graphicsは左上にずれ、拡大したテクスチャの端はぼやけています。
レンダラー解像度1のPixiJS 8.21.0です。両方のPixiの方法で穴と2色が保持されます。Graphicsはグループの移動変換が欠落し、96 × 96のテクスチャは配置が一致しますが3倍でぼやけます。

3列すべてで、穴から市松模様が見えます。これは画像の背後の背景であり、穴に描いた白い形状ではありません。中央列のずれは両サイズで見えます。元サイズの8単位のずれは、倍率3では表示上の24ピクセルになります。

これらは、この元データとバージョンでの観察結果です。すべての穴、変換、グラデーション、書き出したSVGで同じ動作になるとは判断できません。

SVGの元データを保存する

ページの横にemblem.svgとして保存します。比較用に描いた独自画像であり、ベクター化した結果ではありません。

<svg xmlns="http://www.w3.org/2000/svg"
     width="96" height="96" viewBox="0 0 96 96">
  <g transform="translate(8 8)">
    <path fill="#145c61" d="M40 0
      C62 0 80 18 80 40 C80 62 62 80 40 80
      C18 80 0 62 0 40 C0 18 18 0 40 0 Z
      M40 20 C29 20 20 29 20 40 C20 51 29 60 40 60
      C51 60 60 51 60 40 C60 29 51 20 40 20 Z"/>
    <path fill="#e68546"
      d="M62 5 C74 9 80 21 78 34 L61 32
         C63 23 61 15 55 10 Z"/>
  </g>
</svg>

両方の方法を実行する

emblem.svgとともにHTTPで配信するHTMLページに、このスクリプトを置きます。固定したPixiビルドを読み込み、信頼できるSVGを取得して、元サイズと拡大版を2列に描きます。左列は形状、右列はテクスチャを使います。

<script type="module">
import { Application, Assets, Graphics, Sprite }
  from 'https://cdn.jsdelivr.net/npm/pixi.js@8.21.0/dist/pixi.mjs';
 
const app = new Application();
await app.init({
  width: 640, height: 420, resolution: 1,
  antialias: true, background: '#e7eeea', preference: 'webgl'
});
document.body.append(app.canvas);
 
const response = await fetch('emblem.svg');
if (!response.ok) throw new Error('SVG request failed');
const svgText = await response.text();
const texture = await Assets.load({
  src: 'emblem.svg', data: { resolution: 1 }
});
 
for (const [scale, y] of [[1, 12], [3, 120]]) {
  const geometry = new Graphics().svg(svgText);
  geometry.scale.set(scale);
  geometry.position.set(16, y);
  const sprite = new Sprite(texture);
  sprite.scale.set(scale);
  sprite.position.set(336, y);
  app.stage.addChild(geometry, sprite);
}
</script>

元のSVGもブラウザーで開いてください。エラーなしに読み込めたかだけでなく、外側の輪郭、開口部、アクセントの形、配置を比較します。

実際に見える不一致を直す

形状の位置がずれる

このテストでは、Graphics.svg()が包含するtranslate(8 8)を適用しませんでした。プロジェクトのバージョンの挙動を確認するには、バージョンを固定したSVGパーサーの実装が役立ちます。

この特定のファイルでは、形状の位置を設定する行を次に置き換えると、判明している1つの移動変換を補正できます。

geometry.position.set(16 + 8 * scale, y + 8 * scale);

欠落した移動は元データの座標系に属するため、補正にscaleを含めます。倍率3では各方向に24ピクセルの補正です。これは一般的な変換の平坦化処理ではありません。入れ子の回転、傾斜、パスごとに異なる変換があるファイルには、適切に準備した納品用SVGか、別の描画方法が必要です。書き出した納品ファイルを編集可能なマスターと比較してください。

拡大したテクスチャがぼやける

図のSVGテクスチャは96 × 96ピクセルです。スプライトを288 × 288へ拡大しても、元の曲線は読み直されません。ピクセル数を増やすには、解像度を上げた別のテクスチャを読み込みます。

const largeTexture = await Assets.load({
  src: 'emblem.svg?resolution=3',
  data: { resolution: 3 }
});

テストしたビルドでは、288 × 288ピクセルのソースが生成され、論理テクスチャサイズは96 × 96、ソース解像度は3でした。スプライトの作成時にlargeTextureを使います。クエリー文字列は、この実験に別のキャッシュキーを与えます。サーバーはそのURLでも同じSVGを配信する必要があります。PixiのAssetsガイドはURLベースのキャッシュを説明し、テクスチャガイドはテクスチャとソースを区別しています。

実際に使用するレンダラー解像度も含め、画面上の最大サイズに合わせて解像度を選びます。レンダラーの解像度だけを上げても、読み込み済みの低解像度テクスチャに細部は増えません。最小のアイコンサイズも確認してください。最終表示が小さすぎると、大きなソースでも小さな穴を読み取れるようにはできません。

細部が欠ける

ブラウザーで元データを確認してから、簡略化したコピーをPixiで試します。SVGを問題のある形状だけに減らし、グループ、描画、効果を1つずつ戻します。PixiのGraphicsドキュメントはSVGの一部に対応すると説明しています。読み込み成功は完全な互換性確認ではありません。

既知のサイズで画像を確実に保てる場合は、ラスターの納品用コピーを残します。単純な幾何学的シンボルなら、Pixiで形状を直接描くほうが管理しやすい場合があります。常に高速、あるいは省メモリーになるという未測定の主張で方法を選ばず、自分のシーンと対象デバイスでテストしてください。

読み込む前に元データを準備する

SVG内に配置したPNGがある場合、ファイル名の変更や形状としての読み込みで、失われたベクター輪郭が復元されるわけではありません。埋め込みラスターの確認事項で、先に元データを調べます。画像のベクター化ガイドでは、トレースが役立つ場面を説明しています。

平面的なPNGやJPGしか残っておらず、アイコンの編集可能な元形状が必要な場合に、PerfectVectorが適しています。画像をSVGへ変換し、SVGエディターで輪郭、別々の色、小さな開口部を確認してから、Pixiのテストを繰り返します。きれいなベクターマスターがすでにあれば直接使います。トレースはPixiの変換処理を直したり、テクスチャ解像度を設定したりはしません。

他のエンジンは、それぞれ独自の読み込み方法を採用します。GodotのSVG読み込みガイドでは、そこでのテクスチャとオーバーサンプリングを説明し、UnityのSVGガイドでは別の手順を扱います。SVGという拡張子だけを理由に、あるエンジンの設定を別のエンジンへ流用しないでください。

納品するアイコンを確認する

素材を承認する前に、想定する最小と最大のサイズで、ブラウザー描画した元データと比較します。対照的な背景上の開口部、グループ配置、必要な効果を確認します。Pixiのバージョン、レンダラー解像度、テクスチャソースのピクセル寸法、シーンの倍率を記録します。後でレイアウトや読み込み処理が変わっても同じ元データと比較できるよう、SVGマスターをプロジェクトに保持します。

ラスター画像しかない場合は、PerfectVectorで編集可能なSVGを準備し、輪郭と抜きの部分を確認してから、インターフェースで使うサイズで実際のPixi読み込み方法をテストしてください。

よくある質問

PixiJSへSVGを読み込むとベクター形状が維持されますか? 方法によります。Graphics.svgは対応する描画形状を解析します。SVGをテクスチャとして読み込むと、Spriteにラスターのソースを与えます。元データの編集や将来の書き出しのため、元SVGを別途保持してください。

PixiJSのSVGスプライトがぼやけるのはなぜですか? スプライトがテクスチャのピクセル寸法より大きく表示される場合があります。ソース解像度と想定する最大表示サイズを確認します。適切なサイズのテクスチャを読み込むか、対応する画像では形状の方法をテストしてください。

Graphics.svgはSVGのすべての機能を保持しますか? いいえ。SVGの一部に対応しています。このPixiJS 8.21.0の例では穴と2色は残りましたが、グループの移動変換は残りませんでした。自分で書き出したファイルを、ブラウザーの基準表示と比較してください。

参考資料

  1. PixiJSのSVGガイド — テクスチャと形状の読み込み方法、テクスチャ解像度を説明しています。
  2. PixiJSのGraphicsガイド — GraphicsContextの共有とSVG対応の範囲を説明しています。
  3. PixiJSのAssetsガイド — 素材の読み込みとURLベースのキャッシュを説明しています。
  4. PixiJSのテクスチャガイド — テクスチャとソースの関係を説明しています。
  5. PixiJS 8.21.0のSVGパーサー — 読み込みの差を調べるための、バージョンを固定した実装です。

ブログのその他の記事

編集しやすい
よりきれいなSVGから始めましょう