-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8a5e71c
Showing
6 changed files
with
148 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// swift-tools-version:5.3 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "ParallaxSwiftUI", | ||
platforms: [ | ||
.iOS(.v13) | ||
], | ||
products: [ | ||
// Products define the executables and libraries a package produces, and make them visible to other packages. | ||
.library( | ||
name: "ParallaxSwiftUI", | ||
targets: ["ParallaxSwiftUI"]), | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package. A target can define a module or a test suite. | ||
// Targets can depend on other targets in this package, and on products in packages this package depends on. | ||
.target( | ||
name: "ParallaxSwiftUI", | ||
dependencies: []), | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# ParallaxSwiftUI | ||
|
||
A description of this package. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import SwiftUI | ||
|
||
extension View { | ||
func parallax(amount: CGFloat = 10) -> some View { | ||
ParallaxView(view: AnyView(self), amount: amount) | ||
} | ||
} | ||
|
||
/// A wrapper view to add a parallax effect to a SwiftUI view. | ||
struct ParallaxView: View { | ||
|
||
/// The view to apply the parallax too. | ||
let view: AnyView | ||
|
||
/// The amount of the parallax effect to be applied. | ||
let amount: CGFloat | ||
|
||
var body: some View { | ||
/// Using geometry reader we can get the proposed width and height of the view normally. Then we can pass that to the view controller. | ||
GeometryReader { geometry in | ||
ParallaxRepresentable(view: view, width: geometry.size.width, height: geometry.size.height, amount: amount) | ||
} | ||
} | ||
} | ||
|
||
/// Converts SwiftUI view to UIKit controller. | ||
struct ParallaxRepresentable: UIViewControllerRepresentable { | ||
|
||
let view: AnyView | ||
let width: CGFloat | ||
let height: CGFloat | ||
let amount: CGFloat | ||
|
||
func makeUIViewController(context: Context) -> ParallaxController { | ||
|
||
let controller = ParallaxController() | ||
|
||
let hostingController = UIHostingController(rootView: view) | ||
|
||
controller.viewWidth = width | ||
controller.viewHeight = height | ||
controller.amount = amount | ||
controller.viewToChange = hostingController | ||
|
||
return controller | ||
} | ||
|
||
func updateUIViewController(_ uiViewController: ParallaxController, context: Context) { | ||
uiViewController.viewWidth = width | ||
uiViewController.viewHeight = height | ||
uiViewController.updateView() | ||
} | ||
} | ||
|
||
/// View controller that adds parallax effect to view of another view controller. | ||
class ParallaxController: UIViewController { | ||
|
||
var viewToChange: UIViewController? | ||
var viewWidth: CGFloat = 0 | ||
var viewHeight: CGFloat = 0 | ||
var amount: CGFloat = 10 | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
|
||
// Add SwiftUI view to view controller | ||
addChild(viewToChange!) | ||
view.addSubview(viewToChange!.view) | ||
viewToChange!.didMove(toParent: self) | ||
|
||
// Set frame | ||
viewToChange!.view.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight) | ||
view.frame = viewToChange!.view.frame | ||
|
||
// Clear background colour | ||
viewToChange!.view.backgroundColor = .clear | ||
} | ||
|
||
func updateView() { | ||
viewToChange!.view.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight) | ||
view.frame = viewToChange!.view.frame | ||
} | ||
|
||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis) | ||
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis) | ||
let group = UIMotionEffectGroup() | ||
|
||
override func viewWillLayoutSubviews() { | ||
|
||
horizontal.minimumRelativeValue = -amount | ||
horizontal.maximumRelativeValue = amount | ||
|
||
vertical.minimumRelativeValue = -amount | ||
vertical.maximumRelativeValue = amount | ||
|
||
group.motionEffects = [horizontal, vertical] | ||
viewToChange!.view.addMotionEffect(group) | ||
} | ||
|
||
} | ||
|