Skip to content

Instantly share code, notes, and snippets.

@pnlybubbles
Created November 20, 2024 04:18
Show Gist options
  • Save pnlybubbles/61289c2c97da77e3c7627ad7c9a372ab to your computer and use it in GitHub Desktop.
Save pnlybubbles/61289c2c97da77e3c7627ad7c9a372ab to your computer and use it in GitHub Desktop.
SwiftUI `.shadow` with spread parameters like css.
import SwiftUI
struct SpreadShadow: ViewModifier {
let color: Color
let x: CGFloat
let y: CGFloat
let blur: CGFloat
let spread: CGFloat
init(color: Color, x: CGFloat = 0, y: CGFloat = 0, blur: CGFloat = 0, spread: CGFloat = 0) {
self.color = color
self.x = x
self.y = y
self.blur = blur
self.spread = spread
}
func body(content: Content) -> some View {
let composited = content.compositingGroup()
return composited.background {
GeometryReader { proxy in
let spreadSize = CGSize(width: proxy.size.width + spread * 2, height: proxy.size.height + spread * 2)
return Rectangle().fill(color)
.frame(width: spreadSize.width, height: spreadSize.height)
.mask(composited.drawingGroup().scaleEffect(spreadSize / proxy.size))
.offset(x: x - spread, y: y - spread)
.blur(radius: blur / 2)
.overlay(alignment: .topLeading) {
composited
.frame(width: proxy.size.width, height: proxy.size.height)
.blendMode(.destinationOut)
}
.compositingGroup()
}
}
}
}
extension View {
func spreadShadow(color: Color, x: CGFloat = 0, y: CGFloat = 0, blur: CGFloat = 0, spread: CGFloat = 0) -> some View {
return modifier(SpreadShadow(color: color, x: x, y: y, blur: blur, spread: spread))
}
}
#Preview {
VStack(spacing: 40) {
Button { } label: {
Text("Button")
.foregroundStyle(Color.black)
.bold()
.padding(20)
.background(.white)
.clipShape(Capsule())
.spreadShadow(color: .black.opacity(0.5), y: 4, blur: 32, spread: -8)
.rotationEffect(.init(degrees: 20))
}
Button { } label: {
Text("Button")
.foregroundStyle(Color.black)
.bold()
.padding(20)
.background(.white)
.clipShape(Capsule())
.shadow(color: .black.opacity(0.5), radius: 16, y: 4)
.rotationEffect(.init(degrees: 20))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment