PerfectVector
著者: Irene Kim1 分で読める

SVGマーカー:位置のずれない独自の矢印先端を作る

独自のSVG矢印先端を作り、先端の位置と開始側の向きを調整します。ブラウザーで描画した独自の例で、2つのストローク幅でのサイズを比較します。

目次

SVGパスへ独自の矢印先端を付けるには、画像を<marker>内に定義し、marker-endでIDを参照します。画像のどの点をパスの端点に合わせるか、refXとrefYで指定します。その後、パスに合わせて回転させるか、ストローク幅に合わせて大きくするかを選びます。

これらは別々の問題を解決します。矢印の方向が正しくても、端点からずれる場合があります。細い線では正しく合っていても、線を太くすると大きすぎる場合もあります。この手順では、独自のポインター形状を使い、配置、方向、サイズを分けて扱います。

小さな完全なSVGから始める

以下をmarkers.svgとして保存し、ブラウザーで開きます。ポインターは手書きの例で、12 × 12の座標空間内の(11, 6)に先端があります。PerfectVectorの変換結果ではありません。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 180">
  <defs>
    <marker id="pv-pointer" viewBox="0 0 12 12"
      refX="11" refY="6" markerWidth="6" markerHeight="6"
      markerUnits="strokeWidth" orient="auto-start-reverse">
      <path d="M1 1 L11 6 L1 11 L4 6 Z" fill="#087f82"/>
    </marker>
  </defs>
  <g fill="none" stroke="#20364d" stroke-width="4"
    marker-start="url(#pv-pointer)" marker-end="url(#pv-pointer)">
    <path d="M50 45 H350"/>
    <path d="M50 135 C130 75,260 195,350 135"/>
  </g>
</svg>

最初のパスは直線、2つ目は曲線です。両方の両端で同じマーカーを参照します。<defs>は定義を保存し、パスからの参照が表示します。MDNのmarkerリファレンスは、開始、中間、終点の取り付け属性を説明しています。

包含する文書内で一意のIDを使います。複数のSVGをインラインで組み合わせる場合は、マーカーIDに接頭辞を付け、対応するすべてのurl(#...)参照を更新します。SVGのsymbolスプライトガイドは、再利用アイコンでの同じ参照管理の問題を説明しています。

意図した点を端点に合わせる

refX="11" refY="6"は、マーカー画像のどの点をパスの端点に一致させるかを指定します。パス自体は動かしません。この例では、尖った先端です。

refX="0" refY="0"と比較します。ブラウザーはマーカーの座標原点を端点へ配置し、水平線では先端がさらに右下へずれます。マーカーを大きくすると誤りが目立つだけで、基準点は直りません。

MDNはrefXとrefYを、マーカーの参照点の座標として説明しています。表示幅から推測せず、viewBoxを含む画像自身の座標で読み取ります。

4単位と8単位のストロークで、ポインターの位置合わせ、開始方向、マーカーサイズを比較したブラウザー描画
同じ独自ポインターで4つの選択を試しています。オレンジの十字は端点で、下のパネルではストローク依存のサイズとSVGユーザー単位での固定サイズを比較します。

完全なSVGを別途開き、ブラウザーで比較を描画しました。参照点を変えると先端がオレンジの十字に合いました。方向を変えると開始側の矢印が反転しました。単位モードを変えると、ポインターが線とともに大きくなるかを制御できました。これらはこの例の観察結果です。実際の書き出しファイルを受け取り側のアプリで確認します。

先端を端点に正確に合わせても、ストロークはその点まで伸びています。比較にあるように、太い線では細い先端の横にストロークが見える場合があります。その継ぎ目が重要なら、モチーフ、基準点、パス端点を一緒に調整し、接合を確認します。マーカーの配置は、元のストロークを切り取りません。

曲線に方向を決めさせる

パスの終端の矢印には、orient="auto"がその点でのパス方向に従います。曲線の終わりの方向は局所的な接線から決まるため、矢印はパスの両端を結ぶ直線の方向を向くとは限りません。

両端の矢印にはorient="auto-start-reverse"を使います。終端ではautoと同じで、開始マーカーはさらに180度回転します。MDNのorientドキュメントは、両端から外向きの1つの矢印先端を再利用する方法として説明しています。

右上の比較で違いが分かります。autoでは開始ポインターが曲線に沿って向きます。auto-start-reverseでは開始点の外側へ向きます。手で反転した2つ目の形を用意する必要はありません。

予想外の結果なら、パス方向を確認します。パスを反転すると、どちらの端が開始点かが変わります。流れを示す矢印は、両端の画面位置が以前と同じでも、その方向に応じて付ける必要があります。

線の太さでマーカーのサイズを変えるか決める

markerUnitsは、マーカーの寸法と内容の座標系を設定します。既定値はstrokeWidthで、もう一方はuserSpaceOnUseです。違いはMDNのmarkerUnitsリファレンスを参照してください。

選択ストロークを4から8にした場合役立つ場面
strokeWidthマーカー寸法が2倍になります矢印先端を線の太さに比例させる場合
userSpaceOnUse参照要素のユーザー座標では寸法が同じです線の太さが異なってもモチーフのサイズを保つ場合

ポインターはviewBoxの水平12単位のうち10単位を占めます。markerWidth="6"とmarkerUnits="strokeWidth"では、回転前の幅は10 / 12 × 6 × stroke-widthです。4単位のストロークでは20ユーザー単位、8単位では40です。左下の比較はその設定を使います。

両方の線の太さでポインター幅を20単位に保つには、定義を次に変えます。

markerUnits="userSpaceOnUse" markerWidth="24" markerHeight="24"

右下の比較はこれらの値です。markerWidth="6"を維持して単位モードだけ変えると、6単位がストローク幅で乗算されなくなるため、ポインターはずっと小さくなります。

userSpaceOnUseは、画面ピクセル数の固定を意味しません。周囲のSVGや座標系を拡大縮小すると、表示サイズは変わる場合があります。特に大きなモチーフを小さな図の注記に縮小する場合は、最終レイアウトのサイズで確認します。

マーカーにする前に独自のモチーフを準備する

三角形や単純なポインターは、直接パスを描きます。既存のベクター画像では元パスを保持し、どの座標を線へ付けるか決めます。意図した穴を保持し、最終サイズで消える細部を簡略化して、マーカービューポート内に十分な余裕を与えます。

独自の矢印先端や装飾モチーフがPNGやJPGでしか残っていない場合は、PerfectVectorの画像をベクターに変換する手順で、この組み込みの前にSVG候補を復元できます。輪郭と小さな穴を元画像と比較し、不要な背景形状を削除してから、承認した画像の境界と基準点を選びます。変換はマーカー定義を作ったり、パス方向を割り当てたり、図のコネクターの動作を加えたりはしません。

テスト中は色を明示します。この例は青緑のマーカーと紺の線を使い、境界が見えるようにしています。矢印全体を1色にしたい場合は、両方の描画設定を意図して設定し、納品結果を確認します。SVGの色編集ガイドは、色変更を妨げる固定の塗りとスタイルを扱っています。

実際に使う場所でファイルを確認する

編集可能なマスターを保持し、納品用コピーを実際のWebサイト、エディター、書き出し工程で試します。正しいブラウザープレビューは、そのファイルのブラウザーでの見た目を確認するもので、すべてのアプリの読み込み動作を保証しません。

  • 組み込みや最適化後に、各url(#...)が意図したマーカーIDを参照するか確認します。
  • 開始マーカーも使う場合は含めて、直線と曲線を確認します。
  • デザイン内の最も細い線と太い線を比較します。
  • 最終表示サイズで、先端、接合部、切れた画像を確認します。
  • 納品SVGを独立して開き直し、元のプレビューと比較します。

マーカーは、パス上の位置に付ける見える装飾です。図のオブジェクト間に意味的な接続を作るものではありません。図のエディターの接続点やステンシルの動作には、ネイティブの形状システムを使います。draw.ioのカスタム形状ガイドは、その別の作業を扱っています。

マーカーは、物理的につながったカット輪郭にも自動ではなりません。対象環境に閉じたカット形状が必要なら、ベクターエディターで別のパスベースの納品用コピーを準備して確認します。画面上で線と矢印先端が重なっても、結合した輪郭の証拠ではありません。他のSVG準備ガイドは、画像整理と後工程の確認を扱っています。

よくある質問

SVGの矢印先端が線からずれるのはなぜですか? マーカー画像の座標に対してrefXとrefYを確認します。それらはパス端点へ置く点を特定します。この例の先端は11,6で、0,0を使うと原点が端点に置かれます。

1つの矢印先端を両端に再利用するにはどうすればよいですか? marker-startとmarker-endで同じマーカーを参照し、orient="auto-start-reverse"を使います。開始側は反転し、終端側はパス方向に従います。

線を太くすると矢印先端が大きくなるのはなぜですか? markerUnitsの既定値がstrokeWidthだからです。要素のユーザー座標でサイズを保ちたいならuserSpaceOnUseを使い、その単位系に合わせてmarkerWidthとmarkerHeightを調整します。

マーカーは矢印を1つの閉じたパスにしますか? いいえ。マーカー定義は、参照するパスとは別のままです。後工程のカットや編集に必要なら、実際に結合した形状を準備して確認します。

参考資料

  1. MDN — marker — マーカー定義、対応形状、取り付け属性。
  2. MDN — refX — マーカー座標系での水平参照点の配置。
  3. MDN — refY — マーカー座標系での垂直参照点の配置。
  4. MDN — orient — 自動回転と開始インスタンスの反転。
  5. MDN — markerUnits — ストロークに対するサイズとユーザー座標でのサイズ。

1つのモチーフから始め、直線と曲線の両方で基準点、方向、サイズを確認します。モチーフがラスターしかない場合は、SVG候補を準備し、輪郭と開口部を確認してから、承認したパスをマーカーとして組み込みます。

ブログのその他の記事

編集しやすい
よりきれいなSVGから始めましょう