Skip to content

SVG 押し出しと読み込みの対応状況 ​

第 39 課のデモ で操作を試せます。

SVG の対応条件 ​

変換器は、単色の塗りが一つある閉じた輪郭を受け付けます。<path>、<line>、<polyline>、<polygon>、<rect>、<circle>、<ellipse> 上の単色 SVG ストロークは、閉じた編集可能な Path へ展開されます。

したがって、ストロークだけの開いた線とパスも押し出せます。図形に塗りとストロークの両方があるとき、ストロークは塗られたソースの上の別 Path になります。

どちらも SVG グループの変換を保ち、GLB へ書き出せます。丸いキャップと四角いキャップ、そして丸いジョイン、ベベルジョイン、マイタージョインが保持されます。

SVG の stroke="none" プレースホルダは無視されます。変換器は evenodd の穴を含む fill-rule を保持し、SVG グループからペイントとストローク幅を継承します。

ただ塗られた矩形は編集可能な Rect ノードのまま残り、角丸矩形、楕円、閉じたポリラインは編集可能な Path になります。塗り、ストローク、不透明度、塗り規則、ストロークジオメトリに対するインライン style 宣言は、プレゼンテーション属性より優先します。

fill="currentColor" と stroke="currentColor" は、図形、グループ、<use> インスタンス、SVG ルートのうち最も近い color に対して解決されます。色がなければ既定は黒です。

style で与えたストロークも展開できます。外部 CSS スタイルシートは解析しません。

押し出しでは、角丸矩形が SVG の独立した rx と ry を楕円の角の弧として保持します。欠けた半径はもう一方を既定にし、各半径は対応する辺の半分にクランプされます。

通常の 2D Rect インポータは、引き続き角の半径を一つだけ保存します。解決できる正の長さの SVG ダッシュパターンは、奇数長のパターンと stroke-dashoffset を含めて、編集可能な別々の実線輪郭へ展開されます。

長さ 0 のダッシュに丸いキャップがあると、押し出された点になります。non-scaling-stroke は、SVG グループ変換と viewBox の拡大縮小を経ても指定された幅を保ちます。

インポータは中心線を先に投影してから、編集可能な 3D 輪郭へ展開します。この幅は読み込み時に焼き込まれるので、その後のエディタのズームは 3D メッシュを通常の空間オブジェクトとして拡大縮小します。

パターンとグラデーション ​

クリップパスやスライスされたビューポートの下にある非スケーリングストローク、長さ 0 の間隔、ほかのキャップが付いた長さ 0 のダッシュ、グラデーション、ペイントサーバー、未対応の SVG 図形は 2D のままです。patternUnits="userSpaceOnUse" で、整数ピクセルのタイルと基本的な SVG 図形を含む自己完結の <pattern> 塗りは、繰り返す 2D 塗りとして読み込みます。

タイル内ではローカルな <use> と線形・放射グラデーション、PNG・JPEG・WebP・AVIF の埋め込みデータ画像を使えます。パターンはローカルな href で継承でき、数値の x / y 原点と patternTransform の matrix、translate、scale、rotate、skew に対応します。外部参照、外部画像、循環参照、その他のペイントサーバーには対応していません。

矩形上の円形 <radialGradient> 塗りは、userSpaceOnUse、明示的な数値の中心と半径、中心と一致する焦点を使うとき、2D のまま残します。

楕円グラデーション、ずらした焦点、グラデーション変換を含む、その他の自己完結な放射グラデーションは、矩形、円、楕円、パス、ポリゴンに適用でき、ラスタライズした SVG 画像塗りを使います。図形は編集可能なままで、グラデーションの色停止は個別に編集できるペイントではなく、その画像へ焼き込まれます。

SVG 画像塗りは、ズームインするときにテクスチャサイズの上限までベクターソースから描き直されるので、倍率を上げても縁がより鮮明なままです。ストロークが有効な閉じたメッシュを生成できない場合は、元の 2D ノードを保ちます。

ローカル参照とビューポート ​

展開されたストローク輪郭は、座標を正規化する間、小数第 6 位まで残すので、非常に細いディテールが最終的なメッシュ検査の前につぶれません。対応する図形またはグループを指すローカルな <use href="#id"> とレガシーの xlink:href は、前方参照と繰り返し参照を含めて独立したインスタンスを作ります。

インスタンスのピクセルオフセット、変換、継承された塗りは押し出しの前に適用され、各インスタンスは自分の編集可能な ID を受け取ります。循環参照と解決できない参照はスキップされます。

<use> は viewBox を持つ <symbol> も参照できます。インスタンスまたはシンボルが正のピクセル width と height を提供する必要があります。

インスタンスの寸法がシンボルの寸法より優先します。シンボルの preserveAspectRatio は、meet の配置、none、押し出し輪郭の slice クリップをサポートします。

有効な寸法がないか不正な場合、そのシンボルインスタンスはスキップされます。外部参照はまだ読み込みません。

明示的な正のピクセル寸法と viewBox を持つ入れ子の <svg> 要素も、編集可能なビューポートグループを作ります。その x/y、変換、preserveAspectRatio は押し出された子に影響します。

ローカルな <use> は、こうした SVG 要素の一つを参照し、ビューポート寸法を別に上書きできます。入れ子の SVG ビューポートは、生成された押し出し輪郭を既定でクリップします。

slice も含みます。はみ出したジオメトリを残すには overflow="visible" を設定してください。

完全に内側にある図形はグループ関係を保つので、ビューポートグループを動かすとその 3D メッシュも一緒に動きます。端を横切る図形は、クリップされた Path になります。

クリッピングと可視性 ​

ローカルな clip-path="url(#id)" とインライン CSS の clip-path も、対象となる 3D 輪郭をクリップするようになりました。<clipPath> には Path、ポリゴン、ポリライン、矩形、円、楕円、入れ子のグループ、およびそれらの図形を指すローカルな <use> 参照を含められます。

それらの図形は和集合を作り、clip-rule="evenodd" は穴を開けられます。グループと繰り返される <use> インスタンス上のクリップはそれぞれの変換に従い、複数の祖先クリップは互いに、そして SVG ビューポートと交差します。

clipPathUnits="objectBoundingBox" は、単一図形のバウンド、またはグループ内の対応する子図形のバウンドを、その変換も含めて使います。クリップされた輪郭は編集可能な Path になります。

クリップの内側に完全に入る輪郭は、元のノードとグループ関係を保ちます。解決できない、または未対応のクリップ定義は 2D のままです。

マスク、フィルタ、クリップパス内のテキスト、外部クリップ参照は 3D へ変換しません。display="none"、または継承された visibility="hidden" の要素は 3D メッシュを作りません。

子孫は visibility="visible" を明示的に設定できます。ルートの <svg> を渡すと、明示的なピクセル width/height と viewBox が適用されます。

preserveAspectRatio も含みます。塗りの押し出しは、入れ子グループの SVG skewX、skewY、せん断を含む matrix(...) 変換も保持します。

合成変換にせん断が含まれると、これらの輪郭はサンプリングされた線分からなる編集可能な Path になります。通常の viewBox スケールは、矩形と曲線 Path を元の形のまま編集できるように保ちます。

明示的なピクセルのビューポート寸法がない SVG は、viewBox 座標を保ちます。未対応の 2D 図形は引き続き通常の SVG インポータを使い、そのインポータはソースのせん断を保持しません。

preserveAspectRatio="slice" のとき、塗りの押し出し輪郭はビューポートに合わせてクリップされます。穴と、複数の島に分かれた図形も含みます。ビューポート内に完全に入る図形は、Rect または曲線 Path の形を保ちます。未対応の 2D 図形は引き続き通常のインポータに従い、このヘルパーはそれらをクリップしません。

デモと性能 ​

第 39 課の Repeated use sample を選ぶと、同じ定義を異なる塗りで作った二つのインスタンスと、そのそばの通常の矩形を調べられます。Symbol viewport sample を選ぶと、穴のあるシンボル一つのビューポートインスタンスを二つ比較します。

一つ目はシンボルの寸法を使い、二つ目は自分の寸法を指定します。Nested SVG viewport sample を選ぶと、インラインの SVG ビューポートと、<use> で参照した二つ目のインスタンスを比較します。

両者の押し出し輪郭は、それぞれのビューポートに合わせてクリップされます。Paint style + currentColor sample を選ぶと、継承された色とインスタンス固有の色、インラインの塗り上書き、スタイル指定されたストロークを比較します。

Stroke caps + joins sample を選ぶと、丸いキャップと四角いキャップ、別の 3D 輪郭を持つ塗られた図形、グループ変換の下の非スケーリングストローク、押し出された破線ストロークと丸い点を比較します。Clip paths + repeated use sample を選ぶと、穴があり互いに独立してクリップされた二つのインスタンスと、オブジェクトバウンドの和集合でクリップされた図形を調べます。

Group bounds + clip use sample を選ぶと、変換されたグループ上のオブジェクトバウンドクリップを調べます。二つの窓は、一つのローカル定義を再利用します。

SVG の事前検査は、各輪郭がメッシュになれるかを確認します。その CPU ジオメトリは、メッシュ最大 256 個、ジオメトリ配列の合計 8 MiB までの最近キャッシュに残るので、非同期のキャンバス更新が 3D コンパニオンを作るときに再利用できます。

より古い項目は追い出されます。GPU ジオメトリはキャンバスごとに別のキャッシュを持ちます。

pnpm bench:svg-import:browser を実行すると、リポジトリの Ghostscript Tiger SVG と他の代表的な作品について、読み込みと編集の時間を調べられます。その SVG をダウンロードし、第 39 課の Upload SVG で編集可能なレイヤーを見て、ズーム段階を比較することもできます。

読み込んだ SVG レイヤーが重なるとき、押し出された前面は入れ子グループ内のレイヤーを含めて SVG のペイント順を保ちます。連動した 3D ビューでは、後から描かれたレイヤーが先に描かれたレイヤーの上に見えます。

重なりと GLB ​

GLB 書き出しは押し出しノードを同じ手前から奥への走査順で並べ、私たちの glTF インポータがその順序を保持します。同一平面上の不透明で平らな押し出しについて、書き出しは重なるレイヤーを深度方向に、最も薄い押し出しの厚さの最大 5% だけ離すこともあります。

これにより、キャンバス上の編集可能な図形は動かさずに、glTF ビューアが異なる深度バッファ値を得ます。互いに交差しないスタックは別々に処理されるので、遠くの 3D メッシュがこの間隔を無効にしません。

投影バウンドが、傾いたまたは透明な押し出し、別の高さ、あるいは独立した 3D メッシュと重なるスタックは、オーサリングされた変換を保ちます。極端に大きい、または遠いモデルは、ビューアの深度バッファ精度によって小さな深度差を失うことがあります。

Released under the MIT License.