2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

background vs. clipShape vs. mask

Last updated at Posted at 2024-09-09

はじめに

SwiftUI で形状指定をしたいとき、backgroundclipShape あるいは mask といくつかの候補が浮かんで「あれ、どれを使えばいいんだ?」と思ったことはありませんか? 使い分けが紛らわしいので簡単なチャットバブルを例に比べてみます。

標準図形を描画できるか

ひとまず SwiftUI の標準図形たちを描画できるかどうかで実力を測ってみることにします
今回作りたい簡単なチャットバブルはこちら

スクリーンショット 2024-09-10 3.17.39.png

  • 円形 Circle(楕円形 Ellipse
  • カプセル Capsule
  • 四角形 Rectangle(角丸四角形 RoundedRectangle UnevenRoundedRectangle

といったシンプルな図形をカバーしています

スクリーンショット 2024-09-10 3.16.08.png

結論

これらの標準的な図形の描画については、全部いけます。
というのも、それぞれ Shape プロトコルに準拠した型を受け取ることが可能だからです。
具体的な実装を見ていきましょう。

.background

背景に View 全般を描画できるので、当然 Shape に準拠した標準図形も引数に取れます

.background(
  // View
)

// Circle
Image("hamster_transparent") // *1
  .resizable()
  .aspectRatio(contentMode: .fit)
  .background(
    Circle().fill(.white)
  )

// Capsule 
Text("Hello, world.")
  .background(
    Capsule().fill(.white) // *2
  )

// RoundedRectangle
Text("Lorem ipsum dolor sit amet, ...")
  .background(
    RoundedRectangle(cornerRadius: 16).fill(.white)
  )

*1

  • hamster: 背景あり画像
  • hamster_transparent: 背景なし画像

*2
Capsulestyle: .continuous を適用した RoundedRectangle とほぼ等価なため、以降まとめて RoundedRectangle を使用する。

スクリーンショット 2024-09-10 4.17.53.png

.clipShape

形状に合わせてビューそのものを切り取るもので、Shape に準拠した型のみを受け取ります

.clipShape(
  // Shape
)

// Circle
Image("hamster") 
  .resizable()
  .aspectRatio(contentMode: .fit)
  .clipShape(
    Circle()
  )

// Capsule & RoundedRectangle
Text("Lorem ipsum dolor sit amet, ...")
  .background(.white)
  .clipShape(
    RoundedRectangle(cornerRadius: 16)
  )

.mask

指定したビューの透明部分を使い、元のビューを特定の形に見せるもので、View 全般を受け取れます

.mask(
  // View
)

// Circle
Image("hamster") 
  .resizable()
  .aspectRatio(contentMode: .fit)
  .mask(
    Circle()
  )

// Capsule & RoundedRectangle
Text("Lorem ipsum dolor sit amet, ...")
  .background(.white)
  .mask(
    RoundedRectangle(cornerRadius: 16)
  )

使い分けを考える

background & clipShape vs. mask

mask は複雑な形や透明度を操作するため実は処理がかなり重くなります。対して背景を追加するだけの background と、ビューを切り取る clipShape は処理が軽いため、シンプルな形状なら前者を使うのが適していると言えます。

background vs. clipShape

背景を操作する background とビューを切り取る clipShape は、得意とする用途が全く違うと言えます。background は背後に要素を重ねるだけでビュー自体を切り取ったり形を変えるわけではありません。元のビューのレイアウトや形状には影響を与えず、単に背景に色や画像を追加する場合に適しています。
一方、明確に元のビューを切り取りたいだけであれば、clipShape を使用するのが適しているでしょう。

clipShape vs. mask

先にみたように、(Shape 型に準拠した)単純な形を作りたい場合は、処理が軽量な前者の clipShape が適しています。
一方で、複雑な形状に変えたい場合mask の方が適切です。
とはいえ、複雑な形状って何でしょう?

例えば、こういったチャットバブルを作るには mask が適切です(とはいえ、チャットバブルとして成り立たせるには工夫が必要そうです)

スクリーンショット 2024-09-10 5.54.32.png

スクリーンショット 2024-09-10 5.58.36.png

// あくまでイメージだが、png 画像の透明エリアを使って形状を作っている
Text(text)
  .background(.white)
  .mask(
    Image("hamster_transparent") 
      .resizable()
      .aspectRatio(contentMode: .fill)
    )
  .multilineTextAlignment(.center)

まとめ

background vs. clipShape vs. mask の使い分け

  • background: 背後に色や画像の View を追加するシンプルで軽量な処理。元のビューの形状には影響を与えない。

  • clipShape : 元のビューそのものを指定した Shape でクリップする。処理は軽量で、シンプルな形状を適用したいときに最適。

  • mask : 任意のビューを使用して、透明度をもとに形を変えたように見せる。複雑な形状にも対応できるが、処理はやや重くなる。

これらを踏まえて、パフォーマンスと形状の複雑さの観点で使い分けるとよい。

2
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?