以前、UIView
で切り抜く方法は紹介したのですが、せっかくなのでSwitUIのView
でも切り抜く方法を調べてみました。
環境
- Xcode 14
Viewをマスク
図形で切り抜き
SwiftUIでクリッピングマスクを行うのは非常に簡単です。
図形で切り取りを行いたい場合は、.clipShape
を使用します
Image("img_mask")
.resizable()
.frame(width: 300, height: 300)
.clipShape(Circle())
Viewで切り抜き
Shape
型だけではなく、特定のView
で切り抜くことも出来ます。
Image("img_mask")
.resizable()
.frame(width: 300, height: 300)
.mask {
Circle()
}
Viewの中を切り抜く
SwiftUIにはリバースマスクのAPIがまだ無い為、View
の中を切り抜くにはまだ一手間必要です。
マスクの原理
簡単な説明になりますが、今回のCircle
で切り抜く例で言いますと、.mask
に記述したView
と重なっている箇所だけが描画されるという動きになっています。
重なっている箇所 | mask後 |
---|---|
![]() |
![]() |
なので、リバースマスクを表現する為には、切り抜きたい箇所が切り抜かれたView
が必要です。
切り抜かれたViewを作成
.blendMode(.destinationOut)
を使用して合成した切り抜かれたView
を作成します。
.blendMode
は、View
とその重なり合うView
とを合成するためのモードを設定します。
.destinationOut
を設定すると、重なり合っている部分だけを切り抜き、切り抜かれた状態のものが残ります。また、compositingGroup()
を使用して合成効果を有効にする為にラップしています。
Zstackを使用した例
ZStack {
Rectangle()
Circle()
.blendMode(.destinationOut)
}
.compositingGroup()
.background(.mint)
overlayを使用した例
Rectangle()
.fill(.black)
.overlay() {
Circle()
.blendMode(.destinationOut)
}
.compositingGroup()
.background(.mint)
プレビュー
円の形が切り抜かれたView
が完成しました。しっかり背景の色が切り抜かれた箇所から確認が出来ます。
切り抜かれたViewでマスクする
.mask
の中に作成した切り抜かれたView
を渡してみましょう。
Image("img_mask")
.resizable()
.frame(width: 300, height: 300)
.mask {
// 元々切り抜かれたView
Rectangle()
.overlay() {
Circle()
.blendMode(.destinationOut)
}
.compositingGroup()
}
プレビュー
View
の中が円形に切り抜かれて出力出来ました!
Extensionを作成
汎用的に使用する為のExtensionを作成しました。
extension View {
func reverseMask<Mask: View>(alignment: Alignment = .center,
@ViewBuilder _ mask: () -> Mask) -> some View {
self.mask {
Rectangle()
.overlay(alignment: alignment) {
mask()
.blendMode(.destinationOut)
}
// .compositingGroup() 無くても機能する
}
}
}
使用例
Image("img_mask")
.resizable()
.frame(width: 300, height: 300)
.reverseMask {
Image(systemName: "applelogo")
.font(.system(size: 100))
}
プレビュー
おしゃれな感じに仕上がりました!
おわりに
SwiftUIでもView
を切り抜く表現をすることが出来ました!今後のSwiftUIのバージョンアップで手軽に実装出来るようになるとさらに良いですね!
この切り抜きを活用した何かを作りたくなってきたので、また試したら記事にしてみようと思います。
素敵な切り抜きライフをお過ごしください🍏