241

現在、ブラウザベースの SVG アプリケーションを構築しています。このアプリ内では、長方形を含むさまざまな形状をユーザーがスタイルおよび配置できます。

stroke-widthたとえばの SVGrect要素にa を適用すると1px、ストロークはrectのオフセットとインセットに、さまざまなブラウザーによってさまざまな方法で適用されます。これは、特に四角形の外側の幅と視覚的な位置を計算して、他の要素の隣に配置しようとするときに厄介であることが判明しています。

例えば:

  • Firefox は 1 ピクセルのインセット (下と左) と 1 ピクセルのオフセット (上と右) を追加します。
  • Chrome は 1 ピクセルのインセット (上と左) と 1 ピクセルのオフセット (下と右) を追加します。

これまでの私の唯一の解決策は、実際の境界線を自分で(おそらくpathツールを使用して)描画し、境界線をストローク要素の後ろに配置することです。しかし、この解決策は不愉快な回避策であり、可能であればこの道をたどりたくない.

私の質問は、SVGstroke-widthが要素にどのように描画されるかを制御できますか?

4

11 に答える 11

437

いいえ、ストロークが要素の内側または外側のどちらで描画されるかを指定することはできません。私は2003 年にこの機能について SVG ワーキング グループに提案しましたが、サポート (または議論) はありませんでした。

phrogz.net/SVG/stroke-location.svg からの SVG 提案のストローク位置の例

提案書で指摘したように、

  • ストローク幅を 2 ​​倍にし、クリッピング パスを使用してオブジェクトをそれ自体にクリップすることで、「内側」と同じ視覚的結果を得ることができます。
  • ストローク幅を 2 ​​倍にしてから、オブジェクトのストロークなしのコピーをそれ自体の上に重ねることで、「外側」と同じ視覚的結果を得ることができます。

編集:この答えは将来間違っているかもしれません。これらの結果は、 SVG Vector EffectsveStrokePathveIntersect(「内側」の場合) または(「外側」の場合) と組み合わせることで実現できるはずveExcludeです。ただし、Vector Effects はまだ作業中のドラフト モジュールであり、まだ実装を見つけることができません。

編集 2 : SVG 2 ドラフト仕様にはstroke-alignmentプロパティが含まれています (center|inside|outside の可能な値)。このプロパティは、最終的に UA になる可能性があります。

編集 3 : 面白いことに、残念なことに、SVG ワーキング グループはstroke-alignmentSVG 2 から削除されました

于 2011-09-01T16:26:18.577 に答える
70

更新:属性stroke-alignment2015 年 4 月 1 日に SVG Strokes と呼ばれる完全に新しい仕様に移動されました

2015 年 2 月 26 日の SVG 2.0 Editor's Draft の時点で (おそらく2 月 13 日以降)、stroke-alignmentプロパティが存在するinnercenter (デフォルト)、およびの値を使用しますouter

stroke-location@Phrogz によって提案されたプロパティとその後のstroke-position提案と同じように動作するようです。このプロパティは、少なくとも 2011 年から計画されていますが、次のような注釈は別として

SVG 2 には、ストローク位置を指定する方法を含める必要があります

、延期されたため、仕様に詳細が記載されたことはありません-今まではそうでした。

このプロパティ、または私の知る限り、新しい SVG 2 機能をサポートするブラウザーはまだありませんが、仕様が成熟すればすぐにサポートされることを願っています。これは私が個人的に求めていたプロパティであり、ついに仕様に含まれたことを本当に嬉しく思います.

プロパティがオープンパスとループでどのように動作するかについて、いくつかの問題があるようです。これらの問題は、おそらく、ブラウザ間での実装を長引かせるでしょう。ただし、ブラウザーがこのプロパティをサポートし始めると、この回答を新しい情報で更新します。

于 2015-02-28T22:10:36.013 に答える
66

いくつかの制限がある簡単な方法を見つけましたが、うまくいきました:

  • defs で形状を定義する
  • シェイプを参照するクリップ パスを定義する
  • それを使用して、外側が切り取られているので、ストロークを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>

于 2015-08-23T01:48:58.340 に答える
7

以下は、ブラウザーに基づいて、指定されたストロークを使用して、上、右、下、左に追加する必要があるピクセル数を計算する関数です。

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
            };

        }

    };
于 2011-09-02T11:37:51.463 に答える
6

上記の人々が指摘したように、ストロークのパス座標へのオフセットを再計算するか、その幅を 2 ​​倍にしてから、片側または反対側をマスクする必要があります。SVG は Illustrator のストロークの配置をネイティブにサポートしていないだけでなく、PostScript もどちらもサポートしていないためです。 .

Adobe の PostScript マニュアル第 2 版のストロークの仕様には次のよう に記載ます。辺がセグメントに平行なセグメント." (彼らのものを強調)

仕様の残りの部分には、線の位置をオフセットするための属性はありません。Illustrator で内側または外側に位置合わせできる場合、実際のパスのオフセットが再計算されます (オーバープリントしてからマスキングするよりも計算コストが低いため)。.ai ドキュメント内のパス座標は参照であり、最終的な形式にラスター化またはエクスポートされるものではありません。

Inkscape のネイティブ フォーマットは仕様 SVG であるため、仕様にない機能を提供することはできません。

于 2014-11-04T20:59:24.980 に答える
4

とを使用した内側の境界線 の回避策を次に示します。rectsymboluse

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>

注: ?inuseを実際の値に置き換えてください。

背景: これが機能する理由は、シンボルがシャドウ DOM で要素を置き換えsymbolて作成することにより、新しいビューポートを確立するためです。svgこのsvgシャドウ DOM は、現在のSVG要素にリンクされます。svgs はネストでき、everyは新しいビューポートを作成しますsvg。これにより、オーバーラップする境界線を含め、オーバーラップするすべてがクリップされます。何が起こっているかのより詳細な概要については、Sara Soueidan によるこの素晴らしい記事をお読みください。

于 2015-07-30T14:08:25.993 に答える
0

(汚い)可能な解決策は、パターンを使用することです。

これは、内側にストロークされた三角形の例です:

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>
于 2015-06-03T15:46:36.583 に答える