Skip to content

Instantly share code, notes, and snippets.

@OskarGroth
Created November 1, 2020 21:19
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OskarGroth/c02cddb796835564015d540e4b641532 to your computer and use it in GitHub Desktop.
Save OskarGroth/c02cddb796835564015d540e4b641532 to your computer and use it in GitHub Desktop.
SwiftUI Vibrancy
import SwiftUI
@main
struct DemoVibrancyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State var level: Float = 0
var body: some View {
VStack(spacing: 12) {
Group {
Image(systemName: "plus.diamond.fill")
.resizable()
.frame(width: 140, height: 140)
.vibrancy(level)
Text("Hello, world!")
.font(.system(size: 38, weight: .medium, design: .rounded))
.padding()
.vibrancy(level)
}
Slider(value: $level)
}
.padding(40)
.background(VisualEffectView(material: .hudWindow))
}
}
public struct Vibrancy: ViewModifier {
let level: Double
public func body(content: Content) -> some View {
content
.blendMode(.overlay)
.overlay(content.opacity(1 - level))
}
}
public extension View {
func vibrancy(_ level: Float) -> some View {
self.modifier(Vibrancy(level: Double(level)))
}
}
public struct VisualEffectView: View {
private var material: NSVisualEffectView.Material
private var blendingMode: NSVisualEffectView.BlendingMode
private var state: NSVisualEffectView.State
public init(
material: NSVisualEffectView.Material = .headerView,
blendingMode: NSVisualEffectView.BlendingMode = .behindWindow,
state: NSVisualEffectView.State = .followsWindowActiveState
) {
self.material = material
self.blendingMode = blendingMode
self.state = state
}
public var body: some View {
Representable(
material: material,
blendingMode: blendingMode,
state: state
).accessibility(hidden: true)
}
}
// MARK: - Representable
extension VisualEffectView {
struct Representable: NSViewRepresentable {
var material: NSVisualEffectView.Material
var blendingMode: NSVisualEffectView.BlendingMode
var state: NSVisualEffectView.State
func makeNSView(context: Context) -> NSVisualEffectView {
context.coordinator.visualEffectView
}
func updateNSView(_ view: NSVisualEffectView, context: Context) {
context.coordinator.update(material: material)
context.coordinator.update(blendingMode: blendingMode)
context.coordinator.update(state: state)
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
}
class Coordinator {
let visualEffectView = NSVisualEffectView()
init() {
visualEffectView.blendingMode = .withinWindow
}
func update(material: NSVisualEffectView.Material) {
visualEffectView.material = material
}
func update(blendingMode: NSVisualEffectView.BlendingMode) {
visualEffectView.blendingMode = blendingMode
}
func update(state: NSVisualEffectView.State) {
visualEffectView.state = state
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment