Open1

SwiftUI: エンボス風?ベベル風?の表現

kabeyakabeya

iOS16, macOS13以降で、ShapeStyleの一種としてShadowStyleというのが導入されて、ドロップシャドウの他、インナーシャドウというのができるようになっています。

インナーシャドウができると、へこみの表現がしやすいのです。
ただ光源が左上の場合、左上側を暗く、右下側を明るくしたいのです。2個要るんですね。

切りとって貼り付けるような処理をせんといかんのかなと思いましたが、色々やっていたところ、重ね掛けできるんですね。

struct TrayView: View {
    var width: CGFloat
    var height: CGFloat
    var depth: CGFloat
    var cornerRadius: CGFloat
    var color: Color
    
    var body: some View {
        RoundedRectangle(cornerRadius: cornerRadius)
            .fill(color
                .shadow(.inner(color: Color(white: 0.2, opacity: 0.4), radius: abs(depth), x: depth, y: depth))
                .shadow(.inner(color: Color(white: 0.8, opacity: 0.4), radius: abs(depth), x : -depth, y: -depth)))
            .frame(width: width, height: height)
    }
}
 
#Preview {
    VStack {
        TrayView(width: 400, height: 300, depth:  10, cornerRadius: 150, color: .blue)
        TrayView(width: 400, height: 300, depth: -10, cornerRadius: 150, color: .blue)
    }
}

プレビューでは以下のようになります。

最初、へこみのつもりで作っていたんですが(なので名前がTrayViewなんですけども)、逆にしたらふくらみもできるよね、ってことで、depthにマイナスを入れられるようにして良い感じになりました。