Pixi.js: 実際のSVGサポート

作成日 2017年06月29日  ·  30コメント  ·  ソース: pixijs/pixi.js

PixiがSVGのグラフィックス階層表現を作成できるのは素晴らしいことです(現在のようにテクスチャをロードするだけではありません)。

@psyrendust ^ねえ、あなたがPixiにしたものをPRできますか? :D

Stale 🙏 Feature Request

最も参考になるコメント

これは、webpackを使用してあなたが望むことを行うと思います。
https://github.com/blunt1337/pixi-svg-loader

全てのコメント30件

私が作成したこのライブラリを確認することをお勧めします。
https://github.com/bigtimebuddy/pixi-svg
https://bigtimebuddy.github.io/pixi-svg/example/

Pixiでの描画には制限があるため、すべてのsvg機能がサポートされているわけではありません。

@trusktrユースケースを

これは私が考えていたものだからです。 テクスチャアトラスを作成し、SVGからの変換と回転を使用して、スプライトの階層を作成することができます。

このアプローチで私が目にする問題の1つは、アンカーです(何かをアニメーション化する場合に備えて)。 たとえば、Inkscapeはカスタム属性としてアンカーを追加しますが、それらは標準のafaikにはありません。 私が言っていることの例:

2017-07-01 08_56_56-_new document 1 - inkscape

3つのパスのグループ(青い長方形の左上)のアンカーは、 inkscape:transform-center-xおよびinkscape:transform-center-yとして定義されます。

    <g
       id="g4512"
       inkscape:transform-center-x="-65.892627"
       inkscape:transform-center-y="43.567609"
       transform="rotate(-5.9407468,27.740957,88.735118)">
      <path
         inkscape:connector-curvature="0"
         id="rect4485"
         d="m 24.502618,78.898505 h 50.619309 c 3.986749,0 7.196297,3.209548 7.196297,7.196296 v 70.274069 c 0,3.98675 -3.209548,7.1963 -7.196297,7.1963 H 24.502618 c -3.986748,0 -7.196296,-3.20955 -7.196296,-7.1963 V 86.094801 c 0,-3.986748 3.209548,-7.196296 7.196296,-7.196296 z"
         style="opacity:1;fill:#005e92;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
      <path
         inkscape:connector-curvature="0"
         id="rect4485-4"
         d="m 66.160572,123.8869 h 50.619318 c 3.98675,0 7.1963,3.20955 7.1963,7.1963 v 70.27406 c 0,3.98675 -3.20955,7.19631 -7.1963,7.19631 H 66.160572 c -3.986734,0 -7.196284,-3.20956 -7.196284,-7.19631 V 131.0832 c 0,-3.98675 3.20955,-7.1963 7.196284,-7.1963 z"
         style="opacity:1;fill:#920000;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
      <path
         inkscape:connector-curvature="0"
         id="rect4485-3"
         d="m 106.60403,73.994048 h 50.61931 c 3.98675,0 7.1963,3.209548 7.1963,7.196296 v 70.274066 c 0,3.98675 -3.20955,7.19631 -7.1963,7.19631 h -50.61931 c -3.98675,0 -7.196288,-3.20956 -7.196288,-7.19631 V 81.190344 c 0,-3.986748 3.209538,-7.196296 7.196288,-7.196296 z"
         style="opacity:1;fill:#009228;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
    </g>

@bigtimebuddyの努力に感謝しますが、

これもチェックしてください:
https://css-tricks.com/rendering-svg-paths-in-webgl/

これは、webpackを使用してあなたが望むことを行うと思います。
https://github.com/blunt1337/pixi-svg-loader

@OSUblakeかっこいい、それは確かに私が意図したことをしているようだ。 お奨めします。 👍

@bigtimebuddyありがとう! あそこに新しい号を開きました。 完全なPixiシーングラフがあれば素晴らしいと思います。

@RanzQ

@trusktrユースケースを

ええ、でもプリミティブはスプライトではなくGraphicsオブジェクトになります。

このアプローチで私が目にする問題の1つは、アンカーです(何かをアニメーション化する場合に備えて)。 たとえば、Inkscapeはカスタム属性としてアンカーを追加しますが、それらは標準のafaikにはありません。 私が言っていることの例:

非標準のものをサポートしなくてもかまいません。標準化されたAPIだけで生活できます。 inkscape固有のものをサポートするためのプラグインが簡単に存在する可能性があります。

@bigtimebuddyの努力に感謝しますが、

なぜあなたはそれを正確に思いますか?

@OSUblake

これは、webpackを使用してあなたが望むことを行うと思います。
https://github.com/blunt1337/pixi-svg-loader

これは、Webpackに限定されていることと、ツール環境に限定されていることを除いて、かなりクールです。クライアントでは実行されません。 実行時にPixi.jsで使用できるAPIを探しています(ビルド時ではありません)。


私が欲しいのは(私はPixi.jsの専門家ではないので、スプライトを使用するような他の何かが良いかどうかアドバイスします)、生成に使用されたSVGDOMと同じ構造のDisplayObjectシーングラフを作成することですからのPixiツリー。 これは、私にとって、1つのプリミティブ(おそらく数百または数千)をアニメーション化するためだけにフレームごとにSVG全体を再レンダリングする必要なしに、操作とアニメーションに強力です。

オープンソースがまだ存在しない場合、私が行うと思うのは、 @ bigtimebuddyのpixi -svgまたは@saschagehlichのpixi -svg-graphicsを取得し、それらを変更(または同様の概念を使用)して作成することです。 Pixi Graphicsツリーは、単一のGraphicsオブジェクトに描画するだけでなく、SVGツリーをミラーリングします。

@trusktrなるほど、プリミティブベースのアニメーションの場合、 Sprites代わりにGraphicsオブジェクトを作成すると便利な場合があります。 しかし、私は解決策は、両方をサポートすることができると思い、 GraphicsシンプルSVGsためとSpritesより複雑なもののために。

私がそれが良い考えではないと思った理由は、カスタムSVGレンダラーを作成するために多くの努力がなされてきたという事実であり、私の経験では、彼らは常にサポートされていないもののこのTODOを持っていることになります。

使用できる機能と使用できない機能を知る必要があるため、これはアーティストにとって問題になります。 すでに優れたSVGレンダラーであるブラウザーがあります。 しかし、SVGに効果のない単純なプリミティブが含まれているだけの場合は、おそらくGraphicsオブジェクトとして解析しても問題ありません。

スプライトがより適切

SVGからテクスチャを作成するのは、 canvas2d

var path = new Path2D("M10 10 h 80 v 80 h -80 Z");
context.fill(path);

パスモーフィングのデモ
https://codepen.io/osublake/pen/oWzVvb

Googleのものは複雑なSVGパスを解析するのに問題があるので、私はより良いポリフィルに取り組むつもりでした。
https://github.com/google/canvas-5-polyfill

@RanzQ

すでに優れたSVGレンダラーであるブラウザーがあります。

しかし、それはとてもslooooooooowです。 GPUまたはCPUでレンダリングされますか? 私にとって、私が経験するパフォーマンスは、たとえばPixi.jsで描画された同様のものの速度とは比較できません。 ネイティブSVGエンジンがあまりにも多くの仕事をしているように私には思えます。

キャンバス2dでさえWebGLと比較して遅いです。 ここで、WebGLとCanvasの違いを比較してください: http

SVGを描画して、できるだけ速くしたいだけです。 これまでのところ、少なくとも概念的には、Pixi.jsやTwo.jsなどのWebGLAPIを使用してSVGを描画するのが最速の方法のようです。 現時点での唯一の欠点は、すべてのSVG機能が完全にサポートされているわけではないことです。

@OSUblake

SVGからテクスチャを作成するのは、canvas2dとPath2Dapiを使用すると非常に簡単です。

Canvas 2DはまだWebGLよりも著しく遅いので、2つの段落をリンクしたデモを参照してください。

パスモーフィングのデモ
https://codepen.io/osublake/pen/oWzVvb

クールなデモ! この場合、PathProxyで単純なパスをアニメーション化しています。 これはおそらくユースケースとしては十分に高速です。 しかし、100個のノードのようにSVGにたくさんのものを描画し、それらすべてをアニメーション化してから、その全体をテクスチャとして球の周りにラップさせたいと想像してみてください。

または、そのデモのパーティクルがSVGで実行され、SVG DOMノードをアニメーション化してから、キャンバスでdrawImageを使用してレンダリングをテクスチャとして取得し、最後に3Dwebglアプリのクワッドに配置することを想像してください。 遅すぎる!

そのパーティクルアニメーションはPixi経由でWebGLにあるため、デモは高速です。

Pixiを使用したSVGのレンダリングがサポートされている機能であり、SVG階層を反映した階層が作成された場合、変更をdisplay:none <svg>要素( display:noneにマップすることが可能になります。

ReactやAngularなどで操作できるDOMの利便性を提供しながら、Pixiの方が高速であるため、これがSVGを描画する最速の方法だと思います。操作できるSVG DOMツリーが欲しいのですが、誰がレンダリングしますかブラウザの遅いSVGエンジンよりも高速です。 多分私はあまりにも多くを求めています。 今日のテクノロジーでは、SVGレンダリングは一般的な基準では遅すぎるようです(ゲームエンジンの速度が必要です)。

@trusktr

しかし、それはとてもslooooooooowです。

つまり、ブラウザを使用してSVGテクスチャを描画できるということです。低速ですが、すべての機能をサポートしています。 もちろん、そのようなアニメーションはしません。 テクスチャアトラスを作成し、後でスプライトをアニメーション化することができます。 たとえば、2D脊椎キャラクターを作成したい場合は、それが最適な方法です。

これはあなたが求めているものの例だと思います: //github.com/bodymovin/bodymovin/issues/184

タスクは単純ではなく、たとえばそのアニメーションは、スプライトベースのPixiシーンをうまく再生する私の古いAndroid携帯電話でゆっくり再生するのに十分複雑です。 SVGバージョンとPixiバージョンに違いは見られません。 ただし、最適化の問題である可能性があります。

これもチェックしてください: https

したがって、私の意見では、SVGには2つの異なる種類のニーズがあります。 1つはSVG機能が少なく、プリミティブに分割され、もう1つはブラウザでレンダリングされたアトラスを備えています。たとえば、スプライトは<g>ノードです。

別のアプローチは、SVGよりも優れた相互運用可能なフォーマットまたはベクターグラフィックス用のツールを見つけることかもしれません。 スケーラブルなものが必要な場合は、 @ RanzQがすでに明確に示している理由からSVGにはPixiJSの制限があります。 SVGで利用可能なPixiの描画機能ではサポートされていない機能が非常に多いため、基本的な描画変換は二流になります。

私がお勧めするもう1つのアプローチは、PixiAnimate(https://github.com/jiborobot/pixi-animate-extension)です。これは、Adobe Animateのネイティブ拡張機能(免責事項、私が作成したもの)であり、正確なグラフィックスのエクスポートに適しています。 さらに、ネストされたシンボルとレイヤーを使用して、またはアニメーション化して、必要な階層を作成できます。

@bigtimebuddy Animateを使用してベクターグラフィックスからテクスチャアトラスを作成するワークフローはありますか? 私は、PixiシーンをUI支援で作成できるようなワークフローを探していました。

Animateの新しいリリースでアトラスを作成することは可能のようですが、この拡張機能を試しましたか: http

@RanzQ 、はいPixiAnimateは、TexturePackersアトラスの形式で個別の画像またはスプライトシートをエクスポートできます。 ただし、ベクターシェイプは自動的にテクスチャに変換されません。 Animateでこれを行うには、「ビットマップに変換」を使用する必要があります。

@trusktr

そのパーティクルアニメーションはPixi経由でWebGLにあるため、デモは高速です。

その通り。 メインレンダラーとしてキャンバスを使用することは提案していませんでした。 ジオメトリが変更されたときにのみテクスチャ/スプライトを生成します。 ほとんどのユースケースで十分に高速である必要があります。 これが、Two.jsがWebGLでパスレンダリングを行う方法だと思います。

また、Path2Dオブジェクトを使用すると、ブラウザーがパスのベクトルをキャッシュするため、キャンバスのパフォーマンスを向上させることができます。 これにより、キャンバスコンテキストと解像度が異なっていても、同じパスオブジェクトを複数回使用できます。

@OSUblake

その通り。 メインレンダラーとしてキャンバスを使用することは提案していませんでした。 ジオメトリが変更されたときにのみテクスチャ/スプライトを生成します。 ほとんどのユースケースで十分に高速である必要があります。 これが、Two.jsがWebGLでパスレンダリングを行う方法だと思います。

はい、これは良いアプローチのように聞こえます。 たとえば、 <circle>要素で変更される属性がcxcy場合、これは、作成せずに既存のメッシュまたはスプライトを変換することを最適化することを意味します。新しいもの。

Pixi、Two、およびネイティブSVGの比較は次のとおりです。

Pixiが著しく遅いのはなぜですか? フレームごとに描画コマンドに基づいて再計算(再テサレートまたは再ラスタライズ)するためですか?

Two.jsでは、Circleはx、y、およびradiusプロパティを持つオブジェクトです。 そのAPIを使用すると、xとyのみを変更する場合、円を再テスタレーション/再ラスター化する必要がないことは明らかです。

この最適化がPixiの描画コマンドスタイルでどのように行われるかは明らかではありません。

@trusktr

Pixiが著しく遅いのはなぜですか? フレームごとに描画コマンドに基づいて再計算(再テサレートまたは再ラスタライズ)するためですか?

いいえ。多くの三角形を作成しているだけで、GPUのパフォーマンスが低下しています。 線のスタイルなしで長方形を描くと、違いがわかります。 スプライトとしてレンダリングされるため、パフォーマンスが大幅に向上します。 10,000レクト。
https://codepen.io/osublake/pen/PjrbWq/

ラスタライズに距離フィールドを使用することを検討しましたか? ズームインしすぎない限り、フォントでうまく機能することはわかっています。 パスデータのアニメーション化に使用できるかどうか疑問に思っています。
https://github.com/Tw1ddle/WebGL-Distance-Fields/tree/master/sdf

https://www.shadertoy.com/view/ltXSDB

以前の例は、JSBinがforループから早期に抜け出していることに気づかなかったため、完全に不正確n10000 )。 例を更新したので、JSBinのループを壊すことなく、すべて2000個の円をレンダリングします。

SVGの例は、(半径ではなく)円の位置のみをアニメーション化する場合でも最も遅くなります。

Two.jsとSVGも半径をアニメーション化しています。

非radius-animationバージョンを変更する方法がわからなかったため、Pixi.jsバージョンを含めませんでした。 Pixi.js

Pixi.jsを使用して半径アニメーションなしのバージョンを更新して半径アニメーションを含めるにはどうすればよいですか?

パフォーマンスは本当にここで急降下し始めるかもしれません。 グラフィックオブジェクトをクリアする必要があります。これにより、すべてがリセットされます。
https://codepen.io/osublake/pen/8217810e590672c5a5327596e33c4b1a?editors=0010

次に、canvas2dを使用してテクスチャを生成するこのデモを見てください。 私のマシンでは、3,000個のサークルが60fpsで実行されています。
https://codepen.io/osublake/full/MoMeMg/

とにかく、例が示すように、これには良いユースケースがあると思います。場合によっては、WebGLでははるかに高速になる可能性があります。

@OSUblakeおっと、あなたの新しい返信を見る前に、最後の1つに返信しました。

パフォーマンスは本当にここで急降下し始めるかもしれません。 グラフィックオブジェクトをクリアする必要があります。これにより、すべてがリセットされます。
https://codepen.io/osublake/pen/8217810e590672c5a5327596e33c4b1a?editors=0010

それは私が恐れていたものであり、理想的ではありません。 ネイティブSVGの速度に近づき始めます。

次に、canvas2dを使用してテクスチャを生成するこのデモを見てください。 私のマシンでは、3,000個のサークルが60fpsで実行されています。
https://codepen.io/osublake/full/MoMeMg/

なんてこった! わかった! さて、これが現在のところ最良の方法です(そして、3000 <canvas>でも)!

なぜそんなに速いのですか? たぶん、ネイティブSVG実装者はこれ(およびPixi.jsとTwo.js)から学ぶことができますか?

たぶん、Pixi.jsでこのアプローチを使用するには、衝突/ピッキングを変更する必要がありますか? メッシュの代わりに長方形のテクスチャがあります。

@trusktr速い理由は、一度キャンバスに描画してから、それをテクスチャとしてGPUにアップロードすることです。 その例では、4pxステップに丸められた半径ごとに個別のテクスチャが生成されます(私がそれを正しく理解している場合😄)。 アニメーションは十分に高速なので、テクスチャのスワップは表示されません。

Graphicsオブジェクト( cacheAsBitmap )をキャッシュすることにより、Pixiの描画APIで同様のことを行うことができます。 そうすれば、プリミティブを一度描画して、キャッシュからすばやく再描画できます。

その例では、4pxステップに丸められた半径ごとに個別のテクスチャが生成されます(私がそれを正しく理解している場合😄)

実際には0.25刻みに丸めています。 実際にどの程度のサブピクセル精度を確認できますか?

それがおかしい場合は、PixiのCanvasTinterがどのように機能するかを確認してください。 または、スプライトシートアニメーションがどのように機能するか。 パフォーマンスと引き換えにメモリをいくらか犠牲にします。優れたキャッシュ戦略を使用すれば、それは機能します。

Graphicsオブジェクト(cacheAsBitmap)をキャッシュすることにより、Pixiの描画APIで同様のことを行うことができます。 そうすれば、プリミティブを一度描画して、キャッシュからすばやく再描画できます。

グラフィックにはエイリアシングがあるため、cacheAsBitmapの使用は見栄えがよくない場合があります。 アンチエイリアス処理されたグラフィックを取得するには、generateCanvasTextureを使用する必要があります。 したがって、どちらの方法でも最終的にはキャンバスになりますが、PixiのグラフィックAPIを使用すると、ストロークの破線を変更するなどの単純なことはできません。

Graphicsオブジェクト(cacheAsBitmap)をキャッシュすることにより、Pixiの描画APIで同様のことを行うことができます。

アンチエイリアス処理されたグラフィックを取得するには、generateCanvasTextureを使用する必要があります

これらの2つのオプションのいずれかを使用して、例の@OSUblakeのように半径をアニメーション化できますか?

(ちなみに、みんなありがとう、私が前に想像していなかったレンダリング技術に目を開いてくれました)。

@trusktrええ、半径の異なる多くのGraphicsオブジェクトを作成し、生成されたテクスチャのマップを作成する必要があります(したがって、半径ごとにキャッシュされたテクスチャを使用できます)。 cacheAsBitmapを使用すると、テクスチャの代わりにGraphicsオブジェクトをマップできますが、 @ OSUblakeが言ったようなアンチエイリアスはありません。

この種のアニメーションはスプライトシートアニメーションです。 変換を使用してアニメートできる場合は、テクスチャのキャッシュは必要ありません。 円のストロークも拡大縮小することを気にしない場合のように、単純な拡大縮小アニメーションでそれを実行できます。

しかし、私は同意します。canvasの方が描画APIが優れているので、それを使用します。 また、SVGの場合、階層はpixi-svg-loaderようにアトラスに分割できます(私は思いますか?)。 または、アニメーションのようなスプライトシートが必要な場合は、アニメーションの状態をキャンバスに描画することでも可能です。

たぶん、Pixi.jsでこのアプローチを使用するには、衝突/ピッキングを変更する必要がありますか? メッシュの代わりに長方形のテクスチャがあります。

ポリゴンほど高速ではありませんが、canvasにはパスでヒットテストを実行するメソッドisPointInPathがあります。 この地図で動作しているのを見てください。
https://codepen.io/osublake/pen/dzYzab/?editors=0010

three.jsにはsvgloaderがあるようです。おそらく、pixi.jsにマッピングできるものです。
https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/SVGLoader.js

この問題は、最近のアクティビティがないため、自動的に古いものとしてマークされています。 それ以上のアクティビティが発生しない場合は閉じられます。 貢献していただきありがとうございます。

このスレッドは、閉じられた後、最近のアクティビティがないため、自動的にロックされています。 関連するバグについては、新しい問題を開いてください。

このページは役に立ちましたか?
0 / 5 - 0 評価