- Introduction
- Contributing
- Compatibility
- Building
- Tests
- Continuous Integration
- Create a Release
- Older Attempts
- Contact
A Curtain Shader effect in iOS17, use it to revel views underneath.
Screenshot | Gif | Video |
---|---|---|
![]() |
![]() |
Download MP4 Video |
@Observable
public class ControlViewModel {
var offset: CGPoint = CGPoint(x: 0.5, y: 0)
var sections: Int = 10
var maxShadow: Float = 0.1
var pleatHeight: Float = 4.0
var lift: Float = 0
var enable: Bool = true
}
struct ContentView {
@State private var control = ControlViewModel()
@GestureState var dragOffset: CGSize
}
extension ContentView: View {
var body: some View {
content
}
private var content: some View {
VStack {
Text("Some text")
Image("gear")
}
.frame(width: 300, height: 300)
.gesture(
DragGesture()
.onChanged { gesture in
control.offset = CGPoint(x: (gesture.location.x / 300),
y: 1.0 - (gesture.location.y / 300))
}
.onEnded { _ in
withAnimation(.spring()) {
control.offset = CGPoint(x: 0.5, y: 0)
}
}
)
.curtainRaiser(sections: control.sections,
maxShadow: control.maxShadow,
pleatHeight: control.pleatHeight,
lift: control.lift,
offset: control.offset,
enabled: control.enable)
}
}
Parameter | Data Type | Detail |
---|---|---|
sections | Int | The number of sections you want to collapse |
maxShadow | Float | The amount of shadow per section |
pleatHeight | Float | Height of the pleat |
lift | Float | How far the bottom pleat lifts up |
offset | CGPoint | How much to collapse in the range y: 0 to 1, x where the user is holding |
enabled | Bool | If the shader is not enabled, then the view itself is rendered |
To get started as a new contributor on the project, please follow the next steps
If you are a new contributor to the project, we have a script you can run to install all dependencies, there may be parts that you do-not wish to install, so pick and choose what you need from the script
./Scripts/new-developer.sh
This code compiles for .iOS(.v17), .macOS(.v14), .visionOS(.v1)
, if you need a version that worked on an older release, I suggest
investigating Metal Shaders, whilst it's possible to do, via taking a screenshot of the view to apply the effect on. The overhead of
constantly screenshoting (for animated content) may be too much, your mileage may vary
It appears that any views backed by native platform views won't work, ie, textfields, videos
Note from .drawingGroup
Note: Views backed by native platform views may not render into the
/// image. Instead, they log a warning and display a placeholder image to
/// highlight the error.
swift build
PACKAGE_NAME=CurtainRaiser
REPOSITORY_NAME=CurtainRaiser
OUTPUT_PATH=./docs
swift package --allow-writing-to-directory $OUTPUT_PATH \
generate-documentation --target $PACKAGE_NAME \
--disable-indexing \
--transform-for-static-hosting \
--hosting-base-path $REPOSITORY_NAME \
--output-path $OUTPUT_PATH
swift test
Continuous Integration (CI) runs every time you push up to the remote GitHub Repo, it will:
- Compile & Test the code
- Check your PR title
- Build the documentation
- Auto assign the author
- Run Swift lint
We can create GitHub sem-ver releases of this Swift Package by using the build-bump-versions
GitHub Action, only Admins can do this.
If we want to bump the version number, we must:
- Bump
Configuration/Version.xcconfig
version number - Commit to the repo
When we create a new release, CI will:
- Bump
Configuration/Version.xcconfig
build number - Create a tag
- Generate the Change log
- Create a release in GitHub
If you git checkout
9ee2a232943cd4e094382e4cb82120be76ea9c99 you can see that I tried to create this effect
with projection/view/model matrix, by rotating each section and putting that section in the correct place.
Whilst it initially looked ok, the perspective always failed.
Hello! I'm Chris, you get in contact with me via my website: http://www.chrisdavis.com, or send me a message on Twitter: @nthState