Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions Sources/layer-explosion/Environment.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Environment.swift
//
//
//
// Created by Luis Gonzalez on 18/2/23.
//
Expand All @@ -11,15 +11,23 @@ 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
}

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
}

Expand All @@ -29,18 +37,27 @@ 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? {
get { self[ParallaxBorder.self] }
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 }
}
}
14 changes: 8 additions & 6 deletions Sources/layer-explosion/MotionGesture.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// MotionGesture.swift
//
//
//
// Created by Luis Gonzalez on 18/2/23.
//
Expand All @@ -14,7 +14,7 @@ fileprivate class MotionObserver {

let motionManager: CMMotionManager = {
let motionManager = CMMotionManager()
motionManager.deviceMotionUpdateInterval = 1 / 15
motionManager.deviceMotionUpdateInterval = 1 / 30

return motionManager
}()
Expand Down Expand Up @@ -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
}

}
Expand Down Expand Up @@ -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
}
}*/
}
}

Expand Down
39 changes: 19 additions & 20 deletions Sources/layer-explosion/Parallax.swift
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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 {
Expand All @@ -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))
}
}
12 changes: 12 additions & 0 deletions Sources/layer-explosion/TouchAndMotionGesture.swift
Original file line number Diff line number Diff line change
@@ -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))
}
}
7 changes: 4 additions & 3 deletions Sources/layer-explosion/TouchGesture.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// TouchGesture.swift
//
//
//
// Created by Luis Gonzalez on 18/2/23.
//
Expand All @@ -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
Expand Down