🙌
SwiftUIでマスクの部分をUIImageに変換する
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
@State private var captureRect = CGRect.zero
@State var uiImage: UIImage? = nil
var body: some View {
ZStack {
Image("back")
.opacity(uiImage == nil ? 1 : 0)
VStack {
Group {
if let uiImage = uiImage {
Image(uiImage: uiImage)
} else {
Rectangle()
.foregroundColor(.red)
.frame(width: 200, height: 200)
.mask {
mask
}
}
}
Text("スクショ")
.foregroundColor(.white)
.background(Color.black)
.onTapGesture {
let scenes = UIApplication.shared.connectedScenes
let windowScenes = scenes.first as? UIWindowScene
let rootViewController = windowScenes?.keyWindow?.rootViewController
self.uiImage = rootViewController?.view!.getImage(rect: captureRect)
}
}
}
}
private var mask: some View {
Rectangle()
.overlay {
Rectangle()
.background(CaptureRect(rect: $captureRect))
.frame(
rect: CGRect(x: 50, y: 50, width: 50, height: 50)
)
.blendMode(.destinationOut)
}
}
}
struct CaptureRect: View {
@Binding var rect: CGRect
var body: some View {
GeometryReader { geometry in
self.createView(proxy: geometry)
}
}
func createView(proxy: GeometryProxy) -> some View {
DispatchQueue.main.async {
self.rect = proxy.frame(in: .global)
}
return Rectangle().fill(Color.clear)
}
}
public extension View {
/// Position a view using a rectangular frame.
func frame(rect: CGRect) -> some View {
return modifier(FrameRectModifier(rect: rect))
}
}
struct FrameRectModifier: ViewModifier {
let rect: CGRect
func body(content: Content) -> some View {
content
.frame(width: rect.width, height: rect.height, alignment: .topLeading)
.position(x: rect.origin.x + rect.width / 2, y: rect.origin.y + rect.height / 2)
}
}
extension UIView {
func getImage(rect: CGRect) -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: rect)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
Discussion