現在、ブラウザベースのSVGアプリケーションを構築しています。このアプリ内では、長方形など、さまざまな形状をユーザーがスタイル設定および配置できます。
たとえばstroke-width
の1px
をSVG rect
要素に適用すると、ストロークはrect
のオフセットとインセットに異なるブラウザーで異なる方法で適用されます。これは厄介であることが判明しています特に四角形の外側の幅と視覚的な位置を計算し、他の要素の隣に配置しようとすると。
例えば:
これまでの私の唯一の解決策は、実際に境界線を(おそらくpath
ツールを使用して)描画し、境界線をストローク要素の後ろに配置することです。しかし、この解決策は不快な回避策であり、できればこの道を進んで行きたくないと思います。
私の質問は、SVGのstroke-width
を要素に描画する方法を制御できますか?
いいえ、ストロークを要素の内側と外側のどちらに描画するかを指定することはできません。 2003年にこの機能についてSVGワーキンググループに aプロポーザル を作成しましたが、サポート(または議論)を受けませんでした。
提案で述べたように、
Edit:この答えは将来間違っているかもしれません。 SVG Vector Effects を使用して、veStrokePath
をveIntersect
( 'inside'の場合)またはveExclude
( 'outsideの場合)と組み合わせることにより、これらの結果を達成できるはずです。ただし、ベクターエフェクトはまだ機能するドラフトモジュールであり、実装はまだ見つかりません。
Edit 2:SVG 2ドラフト仕様には、 stroke-alignment
プロパティ(withwith | inside |可能な値の外側)。このプロパティは、最終的にはUAになります。
Edit 3:面白くて残念なことに、SVGワーキンググループはstroke-alignment
をSVG 2から削除しました。散文 here 。
UPDATE:stroke-alignment
属性 4月1日にSVG Strokesと呼ばれる完全に新しい仕様に移動しました 。
2015年2月26日のSVG 2.0エディターズドラフトの時点で(おそらく 2月13日 以降) 値stroke-alignment
プロパティが存在するinner
、center
(デフォルト)およびouter
を使用します。
@Phrogzおよびそれ以降の stroke-location
提案 によって提案されたstroke-position
プロパティと同じように機能するようです。このプロパティは少なくとも2011年から計画されていますが、
SVG 2には、ストローク位置を指定する方法が含まれます。
、deferredのように仕様に詳細が記載されたことはありません-今まではそうです。
このプロパティをサポートしているブラウザはありません。また、私が知る限り、SVG 2の新しい機能はまだサポートされていませんが、仕様が完成するとすぐにサポートされることを願っています。これは私が個人的に持っておくよう求めてきた財産であり、最終的に仕様に含まれていることを本当に嬉しく思っています。
ループと同様にオープンパスでもプロパティがどのように動作するかについていくつかの問題があるようです。これらの問題は、ほとんどの場合、ブラウザー間で実装を長引かせます。ただし、ブラウザがこのプロパティのサポートを開始すると、新しい情報でこの回答を更新します。
私は簡単な方法を見つけましたが、これにはいくつかの制限がありますが、私にとってはうまくいきました:
ここに実際の例:
<svg width="240" height="240" viewBox="0 0 1024 1024">
<defs>
<path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z"/>
<clipPath id="clip">
<use xlink:href="#ld"/>
</clipPath>
</defs>
<g>
<use xlink:href="#ld" stroke="#0081C6" stroke-width="160" fill="#00D2B8" clip-path="url(#clip)"/>
</g>
</svg>
CSSを使用して、ストロークと塗りの順序をスタイル設定できます。つまり、最初にストロークを実行し、次に2番目に塗りつぶして、目的の効果を実現します。
Paint-order
のMDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Paint-order
CSSコード:
Paint-order: stroke;
これは、ブラウザに基づいて、指定されたストロークを使用して、上、右、下、左に追加する必要があるピクセル数を計算する関数です。
var getStrokeOffsets = function(stroke){
var strokeFloor = Math.floor(stroke / 2), // max offset
strokeCeil = Math.ceil(stroke / 2); // min offset
if($.browser.mozilla){ // Mozilla offsets
return {
bottom: strokeFloor,
left: strokeFloor,
top: strokeCeil,
right: strokeCeil
};
}else if($.browser.webkit){ // WebKit offsets
return {
bottom: strokeCeil,
left: strokeFloor,
top: strokeFloor,
right: strokeCeil
};
}else{ // default offsets
return {
bottom: strokeCeil,
left: strokeCeil,
top: strokeCeil,
right: strokeCeil
};
}
};
上記の人々が指摘したように、ストロークのパス座標へのオフセットを再計算するか、幅を2倍にしてから、一方または他方をマスクする必要があります。 。
AdobeのPostScript Manual第2版のストロークの仕様には、「4.5.1 Stroking:stroke演算子は、現在のパスに沿って太さの線を描画します。各直線またはパス内の曲線セグメント、-ストロークは、辺がparallelのセグメントにcenteredである線を描画しますセグメントに。」 (それらを強調する)
仕様の残りの部分には、行の位置をオフセットするための属性がありません。 Illustratorで内側または外側に位置合わせできる場合、実際のパスのオフセットが再計算されます(オーバープリントしてからマスキングするよりも計算コストが低いため)。 .aiドキュメントのパス座標は参照であり、最終的な形式にラスタ化またはエクスポートされるものではありません。
Inkscapeのネイティブ形式は仕様SVGであるため、仕様に欠けている機能を提供することはできません。
以下は、内部境界rect
とsymbol
およびuse
を使用した回避策です。
例: https://jsbin.com/yopemiwame/edit?html,output
SVG:
<svg>
<symbol id="inner-border-rect">
<rect class="inner-border" width="100%" height="100%" style="fill:rgb(0,255,255);stroke-width:10;stroke:rgb(0,0,0)">
</symbol>
...
<use xlink:href="#inner-border-rect" x="?" y="?" width="?" height="?">
</svg>
注:use
の?
を実際の値に置き換えてください。
Background:これが機能する理由は、シンボルがsymbol
をsvg
に置き換えて要素を作成することで新しいビューポートを確立するためですシャドウDOM。シャドウDOMのこのsvg
は、現在のSVG
要素にリンクされます。 svg
sはネストでき、すべてのsvg
は新しいビューポートを作成し、重複する境界線を含む重複するすべてのものをクリップすることに注意してください。何が起こっているかについてのより詳細な概要については、Sara Soueidanによる この素晴らしい記事 を読んでください。
それがどれほど役立つかはわかりませんが、私の場合は、境界線だけで別の円を作成し、他の図形の「内側」に配置しました。
(汚い)可能な解決策は、パターンを使用することです。
これは、内側のストロークの三角形の例です。
https://jsfiddle.net/qr3p7php/5/
<style>
#triangle1{
fill: #0F0;
fill-opacity: 0.3;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 20;
}
#triangle2{
stroke: #f00;
stroke-opacity: 1;
stroke-width: 1;
}
</style>
<svg height="210" width="400" >
<pattern id="fagl" patternUnits="objectBoundingBox" width="2" height="1" x="-50%">
<path id="triangle1" d="M150 0 L75 200 L225 200 Z">
</pattern>
<path id="triangle2" d="M150 0 L75 200 L225 200 Z" fill="url(#fagl)"/>
</svg>