web-dev-qa-db-ja.com

ストローク幅を現在の変換行列の影響を受けないようにする方法

SVG(およびCanvas、Quartz、Postscriptなど)では、変換行列はパス座標と線幅の両方に影響します。線幅が影響を受けないように調整する方法はありますか?つまり、次の例では、XとYの縮尺が異なります。これにより、正方形が長方形になり、問題はありませんが、線の両側の幅も広くなります。

  <g transform="rotate(30) scale(5,1) ">
      <rect x="10" y="10" width="20" height="20" 
            stroke="blue" fill="none" stroke-width="2"/>
  </g>

rectangle width scaled pen

それは多くの場合に役立つでしょうが、それをオプトアウトする方法はありますか?別のペンTMを用意したい、またはCTMが円に変換する楕円にペンを設定できるようにしたいのですが、そのようなものは表示されません。

それがなければ、CVGについてSVGに伝える必要はなく、代わりに自分で座標を変換する必要があります。つまり、rectのようなプリミティブを同等のpathに変換します。

38
xan

編集:

この動作を正確に行うために、rectに追加できる属性があります。

vector-effect="non-scaling-stroke"

これは間違っていました:

これは、変形を、それが属しているグループではなく、形状に直接適用する場合に機能します。もちろん、複数のアイテムをグループ化し、それらをすべて一緒にスケーリングする場合、そのアプローチは機能しません。

<rect x="10" y="10" width="20" height="20" 
            stroke="blue" fill="none" stroke-width="2"
            transform="rotate(30) scale(5,1)"/>

これはSVGビューアによっても異なる場合があります。 Inkscapeはファイルを希望どおりにレンダリングします(線幅はスケールの影響を受けません)Chromeは、表示されているとおりにレンダリングします。

45

追記では、パスの記述とストロークの実行は別個のイベントであるため、別個の「ペン」TMを使用することは完全に可能です。

%!PS
%A Funky Shape

matrix currentmatrix %save normal matrix for stroke pen
306 396 translate
72 72 scale
1 1 5 { pop
    360 5 div rotate
    1 0 translate
    0 0 moveto
    1 1 5 { pop
        360 5 div rotate
        1 0 translate
        1 0 lineto
        -1 0 translate
    } for
    -1 0 translate
    closepath
} for
setmatrix
[ 1 -3 4 2 0 0 ] concat %put some skew in the pen
10 rotate     %makes it look more "organic"
stroke
showpage
6
luser droog