From 4b1fd90897491ec4d5bf9ab2d75205af95809c81 Mon Sep 17 00:00:00 2001 From: thyselius Date: Wed, 10 May 2023 00:39:30 +0200 Subject: [PATCH] Added touch & motion support, added inverted 3d effect for light reflection --- Sources/layer-explosion/Environment.swift | 35 ++++++++++++----- Sources/layer-explosion/MotionGesture.swift | 14 ++++--- Sources/layer-explosion/Parallax.swift | 39 +++++++++---------- .../TouchAndMotionGesture.swift | 12 ++++++ Sources/layer-explosion/TouchGesture.swift | 7 ++-- 5 files changed, 69 insertions(+), 38 deletions(-) create mode 100644 Sources/layer-explosion/TouchAndMotionGesture.swift diff --git a/Sources/layer-explosion/Environment.swift b/Sources/layer-explosion/Environment.swift index bce4271..a11ba4b 100644 --- a/Sources/layer-explosion/Environment.swift +++ b/Sources/layer-explosion/Environment.swift @@ -1,6 +1,6 @@ // // Environment.swift -// +// // // Created by Luis Gonzalez on 18/2/23. // @@ -11,7 +11,11 @@ struct ParallaxLevel: EnvironmentKey { static var defaultValue: Int = 0 } -struct ParallaxOffset: EnvironmentKey { +struct ParallaxOffsetMotion: EnvironmentKey { + static var defaultValue: CGSize = .zero +} + +struct ParallaxOffsetTouch: EnvironmentKey { static var defaultValue: CGSize = .zero } @@ -19,7 +23,11 @@ struct ParallaxBorder: EnvironmentKey { static var defaultValue: Color? = nil } -struct ParallaxStrength: EnvironmentKey { +struct ParallaxTouchStrength: EnvironmentKey { + static var defaultValue: Double = 1 +} + +struct ParallaxMotionStrength: EnvironmentKey { static var defaultValue: Double = 1 } @@ -29,9 +37,14 @@ extension EnvironmentValues { set { self[ParallaxLevel.self] = newValue } } - var parallaxOffset: CGSize { - get { self[ParallaxOffset.self] } - set { self[ParallaxOffset.self] = newValue } + var parallaxOffsetMotion: CGSize { + get { self[ParallaxOffsetMotion.self] } + set { self[ParallaxOffsetMotion.self] = newValue } + } + + var parallaxOffsetTouch: CGSize { + get { self[ParallaxOffsetTouch.self] } + set { self[ParallaxOffsetTouch.self] = newValue } } var parallaxBorder: Color? { @@ -39,8 +52,12 @@ extension EnvironmentValues { set { self[ParallaxBorder.self] = newValue } } - var parallaxStrength: Double { - get { self[ParallaxStrength.self] } - set { self[ParallaxStrength.self] = newValue } + var parallaxTouchStrength: Double { + get { self[ParallaxTouchStrength.self] } + set { self[ParallaxTouchStrength.self] = newValue } + } + var parallaxMotionStrength: Double { + get { self[ParallaxMotionStrength.self] } + set { self[ParallaxMotionStrength.self] = newValue } } } diff --git a/Sources/layer-explosion/MotionGesture.swift b/Sources/layer-explosion/MotionGesture.swift index ed41917..7991dac 100644 --- a/Sources/layer-explosion/MotionGesture.swift +++ b/Sources/layer-explosion/MotionGesture.swift @@ -1,6 +1,6 @@ // // MotionGesture.swift -// +// // // Created by Luis Gonzalez on 18/2/23. // @@ -14,7 +14,7 @@ fileprivate class MotionObserver { let motionManager: CMMotionManager = { let motionManager = CMMotionManager() - motionManager.deviceMotionUpdateInterval = 1 / 15 + motionManager.deviceMotionUpdateInterval = 1 / 30 return motionManager }() @@ -49,6 +49,8 @@ fileprivate class MotionObserver { guard let rotation = data?.rotationRate else { return } manager?.rotationOffset.width += rotation.y manager?.rotationOffset.height += rotation.x + manager?.rotationOffset.width *= 0.99 + manager?.rotationOffset.height *= 0.99 } } @@ -83,11 +85,11 @@ struct ParallaxMotionGesture: ViewModifier { func body(content: Content) -> some View { content - .environment(\.parallaxOffset, motion.rotationOffset) - .environment(\.parallaxStrength, strength) - .onTapGesture { // TODO: TEMPORARY. JUST FOR TESTING + .environment(\.parallaxOffsetMotion, motion.rotationOffset) + .environment(\.parallaxMotionStrength, strength) + /*.onTapGesture { // TODO: TEMPORARY. JUST FOR TESTING motion.rotationOffset = .zero - } + }*/ } } diff --git a/Sources/layer-explosion/Parallax.swift b/Sources/layer-explosion/Parallax.swift index 699b064..352b6ad 100644 --- a/Sources/layer-explosion/Parallax.swift +++ b/Sources/layer-explosion/Parallax.swift @@ -1,24 +1,23 @@ -// -// Parallax.swift -// -// -// Created by Luis Gonzalez on 18/2/23. -// +// https://github.com/louis1001/layer-explosion?ref=iosexample.com import SwiftUI struct ParallaxModifier: ViewModifier { var zIndex: Int + var direction:Double @Environment(\.parallaxLevel) var parallaxLevel - @Environment(\.parallaxOffset) var parallaxOffset + @Environment(\.parallaxOffsetTouch) var parallaxOffsetTouch + @Environment(\.parallaxOffsetMotion) var parallaxOffsetMotion @Environment(\.parallaxBorder) var parallaxBorder - @Environment(\.parallaxStrength) var parallaxStrength + @Environment(\.parallaxTouchStrength) var parallaxTouchStrength + @Environment(\.parallaxMotionStrength) var parallaxMotionStrength @ViewBuilder func body(content: Content) -> some View { + let actualLevel = parallaxLevel + zIndex - let offsetDamp = 0.2 * parallaxStrength + let offsetDamp = 0.2 * ((parallaxTouchStrength + parallaxMotionStrength) / 2) let content = Group { if let parallaxBorder { @@ -30,29 +29,29 @@ struct ParallaxModifier: ViewModifier { } let rotationDampened = CGSize( - width: parallaxOffset.width * CGFloat(parallaxStrength), - height: parallaxOffset.height * CGFloat(parallaxStrength) + width: (parallaxOffsetMotion.width * CGFloat(parallaxMotionStrength)) + (parallaxOffsetTouch.width * CGFloat(parallaxTouchStrength)), + height: (parallaxOffsetMotion.height * CGFloat(parallaxMotionStrength)) + (parallaxOffsetTouch.height * CGFloat(parallaxTouchStrength)) ) let result = content .environment(\.parallaxLevel, actualLevel + 1) .offset( - x: offsetDamp * parallaxOffset.width * CGFloat(actualLevel), - y: offsetDamp * parallaxOffset.height * CGFloat(actualLevel) // FIXME: Z-index offsetting + x: offsetDamp * (parallaxOffsetMotion.width + parallaxOffsetTouch.width) * CGFloat(actualLevel) * direction, + y: offsetDamp * (parallaxOffsetMotion.height + parallaxOffsetTouch.height) * CGFloat(actualLevel) * direction // FIXME: Z-index offsetting ) if actualLevel == 0 { let perspective = 0.5 result - .rotation3DEffect( + /*.rotation3DEffect( Angle.degrees(rotationDampened.width * 0.2), - axis: (x: 0, y: 1, z: 0), + axis: (0,1,0), perspective: perspective - ) + )*/ .rotation3DEffect( - Angle.degrees(-rotationDampened.height * 0.2), - axis: (x: 1, y: 0, z: 0), + Angle.degrees((-rotationDampened.height+rotationDampened.width) * 0.2), + axis: (1,1,0), perspective: perspective ) } else { @@ -62,8 +61,8 @@ struct ParallaxModifier: ViewModifier { } extension View { - func parallaxLayer(zIndex: Int = 0) -> some View { + func parallaxLayer(zIndex: Int = 0, invertMotion:Bool=false) -> some View { self - .modifier(ParallaxModifier(zIndex: zIndex)) + .modifier(ParallaxModifier(zIndex: zIndex, direction:invertMotion == true ? -1.0 : 1.0)) } } diff --git a/Sources/layer-explosion/TouchAndMotionGesture.swift b/Sources/layer-explosion/TouchAndMotionGesture.swift new file mode 100644 index 0000000..6fd6a56 --- /dev/null +++ b/Sources/layer-explosion/TouchAndMotionGesture.swift @@ -0,0 +1,12 @@ +import SwiftUI + +extension View { + + func parallaxTouchAndMotionGesture(motionStrength: Double = 0.5, touchStrength: Double = 0.3) -> some View { + self + .contentShape(Rectangle()) + .parallaxLayer() + .modifier(ParallaxMotionGesture(strength: motionStrength)) + .modifier(ParallaxTouchGesture(strength: touchStrength)) + } +} diff --git a/Sources/layer-explosion/TouchGesture.swift b/Sources/layer-explosion/TouchGesture.swift index c849a4c..051aa1f 100644 --- a/Sources/layer-explosion/TouchGesture.swift +++ b/Sources/layer-explosion/TouchGesture.swift @@ -1,6 +1,6 @@ // // TouchGesture.swift -// +// // // Created by Luis Gonzalez on 18/2/23. // @@ -9,12 +9,13 @@ import SwiftUI struct ParallaxTouchGesture: ViewModifier { var strength: Double + @State private var gestureOffset = CGSize.zero func body(content: Content) -> some View { content - .environment(\.parallaxOffset, gestureOffset) - .environment(\.parallaxStrength, strength) + .environment(\.parallaxOffsetTouch, gestureOffset) + .environment(\.parallaxTouchStrength, strength) .gesture( DragGesture() .onChanged { value in