I am learning SwiftUI and am trying to achieve an effect where when content is scrolled, a background image becomes blurred.
I am using Playgrounds on the Mac/iPad at the moment (which is why ArtworkImage is public), in these are the two files which contain the code.
I've tried to follow the explanation here but with not much luck - ScrollView effects using GeometryReader
Main (MovieView)
import SwiftUI
import PlaygroundSupport
struct MovieView: View {
var body: some View {
ArtworkImage()
.overlay(
ScrollView { <- the amount scrolled will determine the blur effect
VStack(alignment: .leading, spacing: 40) {
Spacer()
.frame(height: 280)
MovieInfo()
CastRow()
MovieRow()
Spacer()
}
}
)
}
}
PlaygroundPage.current.setLiveView(MovieView())
ArtworkImage.swift (within in MovieView Sources)
import SwiftUI
public struct ArtworkImage: View {
public init(){}
public var body: some View {
let poster: Image = Image(uiImage: #imageLiteral(resourceName: "wandavision.jpg"))
GeometryReader { geo in
poster
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geo.size.width)
.blur(radius: 80, opaque: true)
.ignoresSafeArea()
}
.overlay(
VStack {
GeometryReader { geo in
poster
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geo.size.width, height: 456, alignment: .top)
.mask(
Rectangle()
.fill(LinearGradient(gradient: Gradient(colors: [Color.clear, Color.black]), startPoint: .bottom, endPoint: .top))
)
.blur(radius: [based on the amount the user has scrolled the ScrollView in the MovieView view])
}
Spacer()
}
)
}
}
What I'm trying to do (and not sure if this is the best way to do it), is store the amount of units that the user has scrolled (in pixels?), and pass it to ArtworkImage
View, where I can use it in a calculation in the .blur()
modifier. Do I need to use something like @EnvironmentObject
? Or is there just a much better way of doing this? :D
I hope this makes sense. Any help appreciated.