🎉

SVGにおける単位指定

2023/06/02に公開

SVGで単位を指定したときに想像した結果と違った結果が得られたので備忘のため記録.

概要

SVGの中で絶対単位を指定するとその場でいったん単位なし(px)に変換され, その後viewport/viewboxの設定に応じてスケーリングされる.

環境

  • windows11 pro
  • chrome バージョン: 113.0.5672.127(Official Build) (64 ビット)

詳細

viewport 300pt x 300pt に viewbox 300 x 300 を設定し, 半径100の円を描画した. このとき, 線の太さを絶対単位で指定した(40pt).

viewportとviewboxをそろえてあるので, ユーザー座標系の1は1ptと等しい. このとき, 線の太さを40ptに指定すれば, ユーザー座標系で40の太さで描画される(下図の濃いグレー)と予想される. しかし, 実際にやってみると, 線は53.333…の太さで描画された(下図の薄いグレー).

このように描画される理由は, 絶対単位(ここではpt)が指定されたときに, いったんpxに変換され(ここでは1pt=1.333…px), すなわち, stroke-widthが40ptから53.333…(=40x1.333…)に変換され, その後描画されたからであると考えられる.

結果として, 40ptの太さを指定したにも関わらず, 得られた画像は53.333…ptの太さになっている点に注意が必要.

サンプルコード

<svg  xmlns="http://www.w3.org/2000/svg"
      width="300pt" height="300pt"
      viewBox="-150 -150 300 300">

  <!-- origin -->
  <circle cx="0" cy="0" r="1"
          style=" stroke:black;
                  fill:black;"/>

  <!-- using absolute unit (40pt) -->
  <circle cx="0" cy="0" r="100"
          style=" stroke:#aaaaaa;
                  stroke-width:40pt;
                  fill:none;"/>

  <!-- using relative value (40) -->
  <circle cx="0" cy="0" r="100"
          style=" stroke:#555555;
                  stroke-width:40;
                  fill:none;"/>
</svg>

Discussion