組み込みシェイプ ― Circle・Rectangle・Capsule を使いこなす

SwiftUI には、よく使う図形があらかじめ用意されている。これらは Shape プロトコルに準拠した構造体で、ビューとしてそのまま配置できる。カスタムシェイプを作る前に、まず組み込みシェイプの特徴と使い方を押さえておこう。

Circle

Circle は正円を描画するシェイプだ。配置された領域の短辺に合わせて直径が決まるため、正方形のフレーム内では期待どおりの円になる。長方形のフレームでも円が崩れることはなく、短辺基準で中央に配置される。

Circle()
    .fill(.blue)
    .frame(width: 100, height: 100)

fill モディファイアで塗りつぶし色を指定している。frame を省略すると親ビュー全体に広がるので、サイズ指定はほぼ必須と考えてよい。

stroke に切り替えれば、輪郭だけの円になる。

Circle()
    .stroke(.red, lineWidth: 3)
    .frame(width: 80, height: 80)

fill と stroke は排他的で、同時に適用したい場合は ZStack で重ねるか、background を使う手法が一般的だ。

Rectangle

Rectangle は矩形を描画する。frame で指定した幅と高さがそのまま矩形のサイズになるため、Circle のような短辺基準の制約はない。

Rectangle()
    .fill(.green)
    .frame(width: 200, height: 100)

角を丸めたい場合は RoundedRectangle を使う。cornerRadius パラメータで角の半径を指定できる。

RoundedRectangle(cornerRadius: 16)
    .fill(.orange)
    .frame(width: 200, height: 100)

RoundedRectangle にはもう一つ、cornerSize を受け取るイニシャライザがある。幅と高さで異なる角丸を指定でき、楕円形の角を作れるが、実務で使う機会はそれほど多くない。

cornerRadius

水平・垂直の角丸を同じ値で指定する。ほとんどのケースではこちらで十分。

cornerSize

CGSize で水平・垂直の角丸を別々に指定できる。楕円的な角を作りたいときに使う。

Ellipse

Ellipse は楕円を描画するシェイプで、frame の幅と高さに応じて楕円の形状が決まる。正方形の frame を与えれば Circle と同じ見た目になるが、型としては別物である。

Ellipse()
    .fill(.purple)
    .frame(width: 200, height: 100)

レスポンシブな UI では、親ビューの幅に合わせて自然に変形する Ellipse のほうが Circle より柔軟に使える場面もある。

Capsule

Capsule は、短辺の半分を cornerRadius とした角丸矩形だ。ボタンやタグの背景としてよく使われており、横長にすればピル型、縦長にすればカプセル型の形状になる。

Capsule()
    .fill(.pink)
    .frame(width: 160, height: 50)

RoundedRectangle(cornerRadius: height / 2) と同じ結果だが、Capsule のほうがコードの意図が明確で読みやすい。

Capsule にも RoundedRectangle と同様に style パラメータがあり、.continuous を指定するとよりなめらかな角丸(スーパー楕円)になる。iOS のアプリアイコンで採用されている形状がまさにこれだ。

Capsule(style: .continuous)
    .fill(.mint)
    .frame(width: 160, height: 50)

共通のモディファイア

組み込みシェイプはすべて Shape プロトコルに準拠しているため、共通のモディファイアが使える。代表的なものを整理しておく。

fill と foregroundStyle

fill はシェイプ専用の塗りつぶし指定。foregroundStyle はビュー全般に使えるが、Shape に対しても同様に機能する。グラデーションや Material を渡せる点も共通している。

stroke と strokeBorder

stroke は図形の中心線に沿って線を引く。strokeBorder は InsettableShape に準拠したシェイプでのみ使え、線幅の分だけ内側にオフセットして描画する。太い線を引くときに図形がはみ出さないのが利点だ。

trim

trim(from:to:) で図形の一部だけを描画できる。パスの開始点から終了点を 0.0〜1.0 の範囲で指定する。ローディングインジケーターやプログレスバーの実装でよく使われるテクニックである。

実践的な組み合わせ

組み込みシェイプは単体で使うだけでなく、overlay や background と組み合わせることで表現の幅が広がる。たとえば、テキストに Capsule の背景をつけてタグ風の UI を作れる。

Text("SwiftUI")
    .font(.caption)
    .padding(.horizontal, 12)
    .padding(.vertical, 6)
    .background(Capsule().fill(.blue.opacity(0.2)))

また、Circle を overlay として重ねれば、アバター画像に枠線をつけるようなデザインも簡単に実現できる。シンプルな組み込みシェイプでも、モディファイアの組み合わせ次第で多彩な UI 表現が可能になる。次の記事では、これら既成の図形では表現しきれないケースに対応するため、Path を使った自由な線描画に進んでいく。