diff --git a/.gitignore b/.gitignore index cd00854..8823155 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,4 @@ fastlane/test_output # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ +Mcrich23-Toolkit/ diff --git a/Example/ContentView.swift b/Example/ContentView.swift index 63d83bf..020442c 100644 --- a/Example/ContentView.swift +++ b/Example/ContentView.swift @@ -12,40 +12,40 @@ struct ContentView: View { var body: some View { VStack(spacing: 20) { HStack(spacing: 20) { - BallPulse() - BallGridPulse() - BallClipRotate() - SquareSpin() + BallPulse(duration: 0.0) + BallGridPulse(duration: 0.0) + BallClipRotate(duration: 0.0) + SquareSpin(duration: 0.0) } HStack(spacing: 20) { - BallClipRotatePulse() - BallClipRotateMultiple() - BallRotate() - CubeTransition() + BallClipRotatePulse(duration: 0.0) + BallClipRotateMultiple(duration: 0.0) + BallRotate(duration: 0.0) + CubeTransition(duration: 0.0) } HStack(spacing: 20) { - BallZigZag() - BallZigZagDeflect() - BallTrianglePath() - BallScale() + BallZigZag(duration: 0.0) + BallZigZagDeflect(duration: 0.0) + BallTrianglePath(duration: 0.0) + BallScale(duration: 0.0) } HStack(spacing: 20) { - LineScale() - LineScaleParty() - BallPulseSync() - BallBeat() + LineScale(duration: 0.0) + LineScaleParty(duration: 0.0) + BallPulseSync(duration: 0.0) + BallBeat(duration: 0.0) } HStack(spacing: 20) { - LineScalePulseOut() - LineScalePulseOutRapid() - BallScaleRipple() - BallScaleRippleMultiple() + LineScalePulseOut(duration: 0.0) + LineScalePulseOutRapid(duration: 0.0) + BallScaleRipple(duration: 0.0) + BallScaleRippleMultiple(duration: 0.0) } HStack(spacing: 20) { - BallScaleRippleMultiple() - TriangleSkewSpin() - BallGridBeat() - SemiCircleSpin() + BallScaleRippleMultiple(duration: 0.0) + TriangleSkewSpin(duration: 0.0) + BallGridBeat(duration: 0.0) + SemiCircleSpin(duration: 0.0) } } .padding(20) diff --git a/Package.swift b/Package.swift index 44e39c0..828e0a0 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( targets: [ .target( name: "LoaderUI", - path: "Sources", - exclude: ["Exclude"]), + path: "Sources" + ), ] ) diff --git a/README.md b/README.md index 0a303b0..ebab70a 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ LoaderUI [NVActivityIndicatorView](https://github.com/ninjaprox/NVActivityIndicatorView) implemented in SwiftUI. +For default speed, set duration to 0.0 + ## Demo ![Demo](https://github.com/ninjaprox/LoaderUI/blob/master/Demo.gif?raw=true) diff --git a/Sources/BallBeat.swift b/Sources/BallBeat.swift index 28f2a30..67284be 100644 --- a/Sources/BallBeat.swift +++ b/Sources/BallBeat.swift @@ -10,9 +10,10 @@ import SwiftUI public struct BallBeat: View { private let beginTimes = [0.35, 0, 0.35] - private let duration = 0.7 + private let duration: Double + private let defaultDuration = 0.7 private let timingFunction = TimingFunction.linear - private let keyTimes = [0, 0.5, 1] + private var keyTimes = [0, 0.5, 1] private let scaleValues: [CGFloat] = [1, 0.75, 1] private let opacityValues = [1, 0.2, 1] @@ -20,7 +21,16 @@ public struct BallBeat: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.5*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -45,6 +55,6 @@ public struct BallBeat: View { struct BallBeat_Previews: PreviewProvider { static var previews: some View { - BallBeat() + BallBeat(duration: 0.7) } } diff --git a/Sources/BallClipRotate.swift b/Sources/BallClipRotate.swift index 74efa4a..e7735fc 100644 --- a/Sources/BallClipRotate.swift +++ b/Sources/BallClipRotate.swift @@ -26,9 +26,10 @@ fileprivate struct BallClip: Shape { } public struct BallClipRotate: View { - private let duration = 0.75 + private let duration: Double + private let defaultDuration = 0.75 private let timingFunction = TimingFunction.linear - private let keyTimes = [0, 0.5, 1] + private var keyTimes = [0, 0.5, 1] private let scaleValues: [CGFloat] = [1, 0.6, 1] private let rotationValues = [0.0, .pi, 2 * .pi] @@ -36,7 +37,16 @@ public struct BallClipRotate: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.5*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -55,7 +65,7 @@ public struct BallClipRotate: View { struct BallClipRotate_Previews: PreviewProvider { static var previews: some View { - BallClipRotate() + BallClipRotate(duration: 0.75) } } } diff --git a/Sources/BallClipRotateMultiple.swift b/Sources/BallClipRotateMultiple.swift index 9a8f4ce..ddd8d00 100644 --- a/Sources/BallClipRotateMultiple.swift +++ b/Sources/BallClipRotateMultiple.swift @@ -34,11 +34,45 @@ struct HorizontalRing: Shape { } public struct BallClipRotateMultiple: View { + private var duration: Double + private var defaultDuration = 1.0 + private var keyTimes: Array = [] + private var rotationValues: Array = [] + private var scaleValues: Array = [1, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1] public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + rotationValues.append(-2 * -.pi) + if duration <= defaultDuration { + self.duration = defaultDuration + rotationValues.append(-.pi) + keyTimes.append(contentsOf: [1, 0.5]) + + } else { + self.duration = duration + } + if duration > defaultDuration { + let topNum = Int(duration.rounded() + 1) + for num in 1...topNum { +// print("ballClipRotateMultiple.num = \(num)") + let finalValue = 1/Double(num) + keyTimes.append(finalValue) + } + for num in 1...topNum-1 { + let finalValue = 1/Double(num) + rotationValues.append(.pi * -finalValue) + } + } +// print("ballClipRotateMultiple.scaleValues = \(scaleValues)") + rotationValues.append(0) + rotationValues.reverse() +// print("ballClipRotateMultiple.rotationValues = \(rotationValues)") + keyTimes.append(0) + keyTimes.reverse() +// print("ballClipRotateMultiple.keyTimes = \(keyTimes)") + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -50,11 +84,11 @@ public struct BallClipRotateMultiple: View { } func renderMyBigRing() -> some View { - let duration = 1.0 + let duration = duration let timingFunction = TimingFunction.easeInOut - let keyTimes = [0, 0.5, 1] - let scaleValues: [CGFloat] = [1, 0.6, 1] - let rotationValues = [0.0, .pi, 2 * .pi] + let keyTimes = keyTimes + let scaleValues: [CGFloat] = scaleValues + let rotationValues = rotationValues let timingFunctions = Array(repeating: timingFunction, count: keyTimes.count - 1) return KeyframeAnimationController(beginTime: 0, @@ -68,11 +102,11 @@ public struct BallClipRotateMultiple: View { } func renderMySmallRing() -> some View { - let duration = 1.0 + let duration = duration let timingFunction = TimingFunction.easeInOut - let keyTimes = [0, 0.5, 1] - let scaleValues: [CGFloat] = [1, 0.6, 1] - let rotationValues = [0.0, -.pi, -2 * .pi] + let keyTimes = keyTimes + let scaleValues: [CGFloat] = scaleValues + let rotationValues = rotationValues let timingFunctions = Array(repeating: timingFunction, count: keyTimes.count - 1) return KeyframeAnimationController(beginTime: 0, @@ -89,6 +123,6 @@ public struct BallClipRotateMultiple: View { struct BallClipRotateMultiple_Previews: PreviewProvider { static var previews: some View { - BallClipRotateMultiple() + BallClipRotateMultiple(duration: 1.0) } } diff --git a/Sources/BallClipRotatePulse.swift b/Sources/BallClipRotatePulse.swift index d5399f7..06de5d6 100644 --- a/Sources/BallClipRotatePulse.swift +++ b/Sources/BallClipRotatePulse.swift @@ -34,11 +34,53 @@ struct VerticalRing: Shape { } public struct BallClipRotatePulse: View { + private var duration: Double + private var defaultDuration = 1.0 + private var ringKeyTimes: Array = [] + private var ringScaleValues: Array = [1, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1] + private var ringRotationValues: Array = [] + private var ballKeyTimes: Array = [] + private var ballScaleValues: Array = [1, 0.95, 0.90, 0.85, 0.80, 0.75, 0.70, 0.65, 0.60, 0.55, 0.50, 0.45, 0.40, 0.35, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1] public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + ringRotationValues.append(-2 * -.pi) + if duration <= defaultDuration { + self.duration = defaultDuration + ringRotationValues.append(-.pi) + ringKeyTimes.append(contentsOf: [1, 0.5]) + ballKeyTimes.append(contentsOf: [1, 0.5]) + } else { + self.duration = duration + } + if duration > defaultDuration { +// ringKeyTimes = [0, 0.5*duration, duration] +// ballKeyTimes = [0, 0.3*duration, duration] + let topNum = Int(duration.rounded() + 1) + for num in 1...topNum { + print("BallClipRotatePulse.num = \(num)") + ballKeyTimes.append(0.3 * Double(num)) + ringKeyTimes.append(0.5 * Double(num)) + } + for num in 1...topNum-1 { + let finalValue = 1/Double(num) + ringRotationValues.append(.pi * -finalValue) + } + } + ringRotationValues.append(0) + ringRotationValues.reverse() +// print("BallClipRotatePulse.ringRotationValues = \(ringRotationValues)") + ringKeyTimes.reverse() + ringKeyTimes.append(0) + ringKeyTimes.reverse() +// print("BallClipRotatePulse.ringKeyTimes = \(ringKeyTimes)") + ballKeyTimes.reverse() + ballKeyTimes.append(0) + ballKeyTimes.reverse() +// print("BallClipRotatePulse.ballKeyTimes = \(ballKeyTimes)") + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -50,11 +92,11 @@ public struct BallClipRotatePulse: View { } func renderMyRing() -> some View { - let duration = 1.0 + let duration = duration let timingFunction = TimingFunction.timingCurve(c0x: 0.09, c0y: 0.57, c1x: 0.49, c1y: 0.9) - let keyTimes = [0, 0.5, 1] - let scaleValues: [CGFloat] = [1, 0.6, 1] - let rotationValues = [0.0, .pi, 2 * .pi] + let keyTimes = ringKeyTimes + let scaleValues: [CGFloat] = ringScaleValues + let rotationValues = ringRotationValues let timingFunctions = Array(repeating: timingFunction, count: keyTimes.count - 1) return KeyframeAnimationController(beginTime: 0, @@ -68,10 +110,10 @@ public struct BallClipRotatePulse: View { } func renderBall() -> some View { - let duration = 1.0 + let duration = duration let timingFunction = TimingFunction.timingCurve(c0x: 0.09, c0y: 0.57, c1x: 0.49, c1y: 0.9) - let keyTimes = [0, 0.3, 1] - let values: [CGFloat] = [1, 0.3, 1] + let keyTimes = ballKeyTimes + let values: [CGFloat] = ballScaleValues let timingFunctions = Array(repeating: timingFunction, count: keyTimes.count - 1) return KeyframeAnimationController(beginTime: 0, @@ -87,6 +129,6 @@ public struct BallClipRotatePulse: View { struct BallClipRotatePulse_Previews: PreviewProvider { static var previews: some View { - BallClipRotatePulse() + BallClipRotatePulse(duration: 1.0) } } diff --git a/Sources/BallPulse.swift b/Sources/BallPulse.swift index 427a95b..b08fccc 100644 --- a/Sources/BallPulse.swift +++ b/Sources/BallPulse.swift @@ -10,16 +10,26 @@ import SwiftUI public struct BallPulse: View { private let beginTimes = [0.12, 0.24, 0.36] - private let duration = 0.75 + private let duration: Double + private let defaultDuration = 0.75 private let timingFunction = TimingFunction.timingCurve(c0x: 0.2, c0y: 0.68, c1x: 0.18, c1y: 1.08) - private let keyTimes = [0, 0.3, 1] + private var keyTimes: Array = [0, 0.3, 1] private let values: [CGFloat] = [1, 0.3, 1] public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, (0.3*duration), duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -42,6 +52,6 @@ public struct BallPulse: View { struct BallPulse_Previews: PreviewProvider { static var previews: some View { - BallPulse() + BallPulse(duration: 0.75) } } diff --git a/Sources/BallPulseSync.swift b/Sources/BallPulseSync.swift index ecfac0e..c49fdd3 100644 --- a/Sources/BallPulseSync.swift +++ b/Sources/BallPulseSync.swift @@ -10,16 +10,26 @@ import SwiftUI public struct BallPulseSync: View { private let beginTimes = [0.07, 0.14, 0.21] - private let duration = 0.6 + private let duration: Double + private let defaultDuration = 0.6 private let timingFunction = TimingFunction.easeInOut - private let keyTimes = [0, 0.33, 0.66, 1] + private var keyTimes = [0, 0.33, 0.66, 1] private let directionValues: [CGFloat] = [0, 1, -1, 0] public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.33*duration, 0.66*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -46,6 +56,6 @@ public struct BallPulseSync: View { struct BallPulseSync_Previews: PreviewProvider { static var previews: some View { - BallPulseSync() + BallPulseSync(duration: 0.6) } } diff --git a/Sources/BallRotate.swift b/Sources/BallRotate.swift index 1ea180b..2e1b197 100644 --- a/Sources/BallRotate.swift +++ b/Sources/BallRotate.swift @@ -27,9 +27,10 @@ fileprivate struct MyCircles: View { public struct BallRotate: View { - private let duration = 1.0 + private let duration: Double + private let defaultDuration = 1.0 private let timingFunction = TimingFunction.timingCurve(c0x: 0.7, c0y: -0.13, c1x: 0.22, c1y: 0.86) - private let keyTimes = [0, 0.5, 1] + private var keyTimes = [0, 0.5, 1] private let scaleValues: [CGFloat] = [1, 0.6, 1] private let rotationValues = [0.0, .pi, 2 * .pi] @@ -37,7 +38,16 @@ public struct BallRotate: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.5*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -57,6 +67,6 @@ public struct BallRotate: View { struct BallRotate_Previews: PreviewProvider { static var previews: some View { - BallRotate() + BallRotate(duration: 1.0) } } diff --git a/Sources/BallScale.swift b/Sources/BallScale.swift index ba3e276..6802b77 100644 --- a/Sources/BallScale.swift +++ b/Sources/BallScale.swift @@ -9,9 +9,10 @@ import SwiftUI public struct BallScale: View { - private let duration = 1.0 + private let duration: Double + private let defaultDuration = 1.0 private let timingFunction = TimingFunction.easeInOut - private let keyTimes = [0.0, 1.0] + private var keyTimes = [0.0, 1.0] private let scaleValues: [CGFloat] = [0.0, 1.0] private let opacityValues = [1.0, 0.0] @@ -19,7 +20,16 @@ public struct BallScale: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -39,6 +49,6 @@ public struct BallScale: View { struct BallScale_Previews: PreviewProvider { static var previews: some View { - BallScale() + BallScale(duration: 1.0) } } diff --git a/Sources/BallScaleRipple.swift b/Sources/BallScaleRipple.swift index 170581b..514b5d3 100644 --- a/Sources/BallScaleRipple.swift +++ b/Sources/BallScaleRipple.swift @@ -20,9 +20,10 @@ struct Ring: Shape { } public struct BallScaleRipple: View { - private let duration = 1.0 + private let duration: Double + private let defaultDuration = 1.0 private let timingFunction = TimingFunction.timingCurve(c0x: 0.21, c0y: 0.53, c1x: 0.56, c1y: 0.8) - private let keyTimes = [0, 0.7, 1] + private var keyTimes = [0, 0.7, 1] private let scaleValues: [CGFloat] = [0.1, 1, 1] private let opacityValues = [1, 0.7, 0] @@ -30,7 +31,16 @@ public struct BallScaleRipple: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.7*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -50,6 +60,6 @@ public struct BallScaleRipple: View { struct BallScaleRipple_Previews: PreviewProvider { static var previews: some View { - BallScaleRipple() + BallScaleRipple(duration: 1.0) } } diff --git a/Sources/BallScaleRippleMultiple.swift b/Sources/BallScaleRippleMultiple.swift index 3f62f5f..d5b206e 100644 --- a/Sources/BallScaleRippleMultiple.swift +++ b/Sources/BallScaleRippleMultiple.swift @@ -10,9 +10,10 @@ import SwiftUI public struct BallScaleRippleMultiple: View { private let beginTimes = [0, 0.2, 0.4] - private let duration = 1.25 + private let duration: Double + private let defaultDuration = 1.25 private let timingFunction = TimingFunction.timingCurve(c0x: 0.21, c0y: 0.53, c1x: 0.56, c1y: 0.8) - private let keyTimes = [0, 0.7, 1] + private var keyTimes = [0, 0.7, 1] private let scaleValues: [CGFloat] = [0.1, 1, 1] private let opacityValues = [1, 0.7, 0] @@ -20,7 +21,16 @@ public struct BallScaleRippleMultiple: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.7*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -46,6 +56,6 @@ public struct BallScaleRippleMultiple: View { struct BallScaleRippleMultiple_Previews: PreviewProvider { static var previews: some View { - BallScaleRippleMultiple() + BallScaleRippleMultiple(duration: 1.25) } } diff --git a/Sources/BallTrianglePath.swift b/Sources/BallTrianglePath.swift index fbb6fa0..767efb5 100644 --- a/Sources/BallTrianglePath.swift +++ b/Sources/BallTrianglePath.swift @@ -19,9 +19,10 @@ fileprivate struct SmallRing: Shape { } public struct BallTrianglePath: View { - private let duration = 2.0 + private let duration:Double + private let defaultDuration = 2.0 private let timingFunction = TimingFunction.easeInOut - private let keyTimes = [0, 0.33, 0.66, 1] + private var keyTimes = [0, 0.33, 0.66, 1] private let directionValues: [[UnitPoint]] = [[.zero, .init(x: 0.5, y: 1), .init(x: -0.5, y: 1), .zero], [.zero, .init(x: -1, y: 0), .init(x: -0.5, y: -1), .zero], [.zero, .init(x: 0.5, y: -1), .init(x: 1, y: 0), .zero]] @@ -30,7 +31,16 @@ public struct BallTrianglePath: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.33*duration, 0.66*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -65,6 +75,6 @@ public struct BallTrianglePath: View { struct BallTrianglePath_Previews: PreviewProvider { static var previews: some View { - BallTrianglePath() + BallTrianglePath(duration: 2.0) } } diff --git a/Sources/BallZigZag.swift b/Sources/BallZigZag.swift index 91c36d2..27b0ca5 100644 --- a/Sources/BallZigZag.swift +++ b/Sources/BallZigZag.swift @@ -9,9 +9,10 @@ import SwiftUI public struct BallZigZag: View { - private let duration = 0.7 + private let duration:Double + private let defaultDuration = 0.7 private let timingFunction = TimingFunction.linear - private let keyTimes = [0, 0.33, 0.66, 1] + private var keyTimes = [0, 0.33, 0.66, 1] private let directionValues: [[UnitPoint]] = [[.zero, .init(x: -1, y: -1), .init(x: 1, y: -1), .zero], [.zero, .init(x: 1, y: 1), .init(x: -1, y: 1), .zero]] @@ -19,7 +20,16 @@ public struct BallZigZag: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.33*duration, 0.66*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -50,6 +60,6 @@ public struct BallZigZag: View { struct BallZigZag_Previews: PreviewProvider { static var previews: some View { - BallZigZag() + BallZigZag(duration: 0.7) } } diff --git a/Sources/BallZigZagDeflect.swift b/Sources/BallZigZagDeflect.swift index e7991f5..71fc86a 100644 --- a/Sources/BallZigZagDeflect.swift +++ b/Sources/BallZigZagDeflect.swift @@ -9,9 +9,10 @@ import SwiftUI public struct BallZigZagDeflect: View { - private let duration = 1.5 + private let duration: Double + private let defaultDuration = 1.5 private let timingFunction = TimingFunction.linear - private let keyTimes = [0, 0.16, 0.33, 0.5, 0.66, 0.83, 1] + private var keyTimes = [0, 0.16, 0.33, 0.5, 0.66, 0.83, 1] private let directionValues: [[UnitPoint]] = [[.zero, .init(x: -1, y: -1), .init(x: 1, y: -1), .zero, .init(x: 1, y: -1), .init(x: -1, y: -1), .zero], [.zero, .init(x: 1, y: 1), .init(x: -1, y: 1), .zero, .init(x: -1, y: 1), .init(x: 1, y: 1), .zero]] @@ -19,7 +20,16 @@ public struct BallZigZagDeflect: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.16*duration, 0.33*duration, 0.5*duration, 0.66*duration, 0.83*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -50,6 +60,6 @@ public struct BallZigZagDeflect: View { struct BallZigZagDeflect_Previews: PreviewProvider { static var previews: some View { - BallZigZagDeflect() + BallZigZagDeflect(duration: 1.5) } } diff --git a/Sources/CubeTransition.swift b/Sources/CubeTransition.swift index 7789307..ca8e770 100644 --- a/Sources/CubeTransition.swift +++ b/Sources/CubeTransition.swift @@ -9,9 +9,10 @@ import SwiftUI public struct CubeTransition: View { - private let duration = 1.6 + private let duration: Double + private let defaultDuration = 1.6 private let timingFunction = TimingFunction.easeInOut - private let keyTimes = [0, 0.25, 0.5, 0.75, 1] + private var keyTimes = [0, 0.25, 0.5, 0.75, 1] private let scaleValues: [CGFloat] = [1, 0.5, 1, 0.5, 1] private let rotationValues = [0.0, -.pi / 2, -.pi, -1.5 * .pi, -2 * .pi] private let translationDirectionValues: [[UnitPoint]] = [[.zero, .init(x: 1, y: 0), .init(x: 1, y: 1), .init(x: 0, y: 1), .zero], @@ -21,7 +22,16 @@ public struct CubeTransition: View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.25*duration, 0.5*duration, 0.75*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -57,6 +67,6 @@ public struct CubeTransition: View { struct CubeTransition_Previews: PreviewProvider { static var previews: some View { - CubeTransition() + CubeTransition(duration: 1.6) } } diff --git a/Sources/LineScale.swift b/Sources/LineScale.swift index 969a068..9d2c8a4 100644 --- a/Sources/LineScale.swift +++ b/Sources/LineScale.swift @@ -10,16 +10,26 @@ import SwiftUI public struct LineScale: View { private let beginTimes = [0.1, 0.2, 0.3, 0.4, 0.5] - private let duration = 1.0 + private let duration: Double + private let defaultDuration = 1.0 private let timingFunction = TimingFunction.timingCurve(c0x: 0.2, c0y: 0.68, c1x: 0.18, c1y: 1.08) - private let keyTimes = [0, 0.5, 1] + private var keyTimes = [0, 0.5, 1] private let values: [CGFloat] = [1, 0.4, 1] public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.5*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -43,6 +53,6 @@ public struct LineScale: View { struct LineScale_Previews: PreviewProvider { static var previews: some View { - LineScale() + LineScale(duration: 1.0) } } diff --git a/Sources/LineScalePulseOut.swift b/Sources/LineScalePulseOut.swift index 7f48530..2bddc5d 100644 --- a/Sources/LineScalePulseOut.swift +++ b/Sources/LineScalePulseOut.swift @@ -10,16 +10,26 @@ import SwiftUI public struct LineScalePulseOut: View { private let beginTimes = [0.4, 0.2, 0, 0.2, 0.4] - private let duration = 1.0 + private let duration: Double + private let defaultDuration = 1.0 private let timingFunction = TimingFunction.timingCurve(c0x: 0.85, c0y: 0.25, c1x: 0.37, c1y: 0.85) - private let keyTimes = [0, 0.5, 1] + private var keyTimes = [0, 0.5, 1] private let values: [CGFloat] = [1, 0.4, 1] public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.5*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -43,6 +53,6 @@ public struct LineScalePulseOut: View { struct LineScalePulseOut_Previews: PreviewProvider { static var previews: some View { - LineScalePulseOut() + LineScalePulseOut(duration: 1.0) } } diff --git a/Sources/LineScalePulseOutRapid.swift b/Sources/LineScalePulseOutRapid.swift index 4c07626..e25634e 100644 --- a/Sources/LineScalePulseOutRapid.swift +++ b/Sources/LineScalePulseOutRapid.swift @@ -10,17 +10,27 @@ import SwiftUI public struct LineScalePulseOutRapid: View { private let beginTimes = [0.5, 0.25, 0, 0.25, 0.5] - private let duration = 0.9 + private let duration: Double + private let defaultDuration = 0.9 private let timingFunction = TimingFunction.timingCurve(c0x: 0.11, c0y: 0.49, c1x: 0.38, c1y: 0.78) - private let keyTimes = [0, 0.8, 0.9] + private var keyTimes = [0, 0.8, 0.9] private let values: [CGFloat] = [1, 0.3, 1] public var body: some View { GeometryReader(content: self.render) } - public init() { } - + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.8*duration, 0.9*duration] + } + } + func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) let spacing = dimension / 9 @@ -43,6 +53,6 @@ public struct LineScalePulseOutRapid: View { struct LineScalePulseOutRapid_Previews: PreviewProvider { static var previews: some View { - LineScalePulseOutRapid() + LineScalePulseOutRapid(duration: 0.9) } } diff --git a/Sources/LoadingUI.swift b/Sources/LoadingUI.swift new file mode 100644 index 0000000..b95f494 --- /dev/null +++ b/Sources/LoadingUI.swift @@ -0,0 +1,99 @@ +// +// File.swift +// +// +// Created by Morris Richman on 2/6/22. +// + +import Foundation +import SwiftUI + +struct LoadingUI: View { + @State var selectedType: types + @State var duration: Double + enum types { + case ballPulse + case ballGridPulse + case ballClipRotate + case squareSpin + case ballClipRotatePulse + case ballClipRotateMultiple + case ballRotate + case cubeTransition + case ballZigZag + case ballZigZagDeflect + case ballTrianglePath + case ballScale + case lineScale + case lineScaleParty + case ballPulseSync + case ballBeat + case lineScalePulseOut + case lineScalePulseOutRapid + case ballScaleRipple + case ballScaleRippleMultiple + case triangleSkewSpin + case ballGridBeat + case semiCircleSpin + } + var body: some View { + Group { + switch selectedType { + case .ballPulse: + BallPulse(duration: duration) + case .ballGridPulse: + BallGridPulse() + case .ballClipRotate: + BallClipRotate(duration: duration) + case .squareSpin: + SquareSpin(duration: duration) + case .ballClipRotatePulse: + BallClipRotatePulse(duration: duration) + case .ballClipRotateMultiple: + BallClipRotateMultiple(duration: duration) + case .ballRotate: + BallRotate(duration: duration) + case .cubeTransition: + CubeTransition(duration: duration) + case .ballZigZag: + BallZigZag(duration: duration) + case .ballZigZagDeflect: + BallZigZagDeflect(duration: duration) + case .ballTrianglePath: + BallTrianglePath(duration: duration) + case .ballScale: + BallScale(duration: duration) + case .lineScale: + LineScale(duration: duration) + case .lineScaleParty: + LineScaleParty() + case .ballPulseSync: + BallPulseSync(duration: duration) + case .ballBeat: + BallBeat(duration: duration) + case .lineScalePulseOut: + LineScalePulseOut(duration: duration) + case .lineScalePulseOutRapid: + LineScalePulseOutRapid(duration: duration) + case .ballScaleRipple: + BallScaleRipple(duration: duration) + case .ballScaleRippleMultiple: + BallScaleRippleMultiple(duration: duration) + case .triangleSkewSpin: + TriangleSkewSpin(duration: duration) + case .ballGridBeat: + BallGridBeat() + case .semiCircleSpin: + SemiCircleSpin(duration: duration) + } + } +// .frame(width: 20, height: 20) + } +} + +struct LoadingUI_Previews: PreviewProvider { + static var previews: some View { + LoadingUI(selectedType: .ballBeat, duration: 0.0) + } +} + diff --git a/Sources/SemiCircleSpin.swift b/Sources/SemiCircleSpin.swift index 43bfbf4..97d8c70 100644 --- a/Sources/SemiCircleSpin.swift +++ b/Sources/SemiCircleSpin.swift @@ -24,16 +24,26 @@ fileprivate struct SemiCircle: Shape { } public struct SemiCircleSpin: View { - private let duration = 0.6 + private let duration: Double + private let defaultDuration = 0.6 private let timingFunction = TimingFunction.linear - private let keyTimes = [0, 1.0] + private var keyTimes = [0, 1.0] private let value = [0, 2 * Double.pi] public var body: some View { GeometryReader(content: render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -52,6 +62,6 @@ public struct SemiCircleSpin: View { struct SemiCircleSpin_Previews: PreviewProvider { static var previews: some View { - SemiCircleSpin() + SemiCircleSpin(duration: 0.6) } } diff --git a/Sources/SquareSpin.swift b/Sources/SquareSpin.swift index b3e882f..f3c266a 100644 --- a/Sources/SquareSpin.swift +++ b/Sources/SquareSpin.swift @@ -28,16 +28,26 @@ fileprivate struct FlipEffect: AnimatableModifier { } public struct SquareSpin: View { - private let duration = 3.0 + private let duration:Double + private let defaultDuration = 3.0 private let timingFunction = TimingFunction.timingCurve(c0x: 0.09, c0y: 0.57, c1x: 0.49, c1y: 0.9) - private let keyTimes = [0, 0.25, 0.5, 0.75, 1] + private var keyTimes = [0, 0.25, 0.5, 0.75, 1] private let values = [(0.0, 0.0, 0.0, 0.0), (Double.pi, 1.0, 0.0, 0.0), (Double.pi, 0.0, 0.0, 1.0), (Double.pi, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 0.0)] // The last one should rotate to left on y axis public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration <= defaultDuration { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.25*duration, 0.5*duration, 0.75*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -55,6 +65,6 @@ public struct SquareSpin: View { struct SquareSpin_Previews: PreviewProvider { static var previews: some View { - SquareSpin() + SquareSpin(duration: 3.0) } } diff --git a/Sources/TriangleSkewSpin.swift b/Sources/TriangleSkewSpin.swift index fb10134..5c3241a 100644 --- a/Sources/TriangleSkewSpin.swift +++ b/Sources/TriangleSkewSpin.swift @@ -24,16 +24,26 @@ fileprivate struct Triangle: Shape { } public struct TriangleSkewSpin: View { - private let duration = 3.0 + private let duration: Double + private let defaultDuration = 3.0 private let timingFunction = TimingFunction.timingCurve(c0x: 0.09, c0y: 0.57, c1x: 0.49, c1y: 0.9) - private let keyTimes = [0, 0.25, 0.5, 0.75, 1] + private var keyTimes = [0, 0.25, 0.5, 0.75, 1] private let values = [(0.0, 0.0, 0.0, 0.0), (Double.pi, 1.0, 0.0, 0.0), (Double.pi, 0.0, 0.0, 1.0), (Double.pi, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 0.0)] // The last one should rotate to left on y axis public var body: some View { GeometryReader(content: self.render) } - public init() { } + public init(duration: Double) { + if duration == 0.0 { + self.duration = defaultDuration + } else { + self.duration = duration + } + if duration > defaultDuration { + keyTimes = [0, 0.25*duration, 0.5*duration, 0.75*duration, duration] + } + } func render(geometry: GeometryProxy) -> some View { let dimension = min(geometry.size.width, geometry.size.height) @@ -54,6 +64,6 @@ public struct TriangleSkewSpin: View { struct TriangleSkewSpin_Previews: PreviewProvider { static var previews: some View { - TriangleSkewSpin() + TriangleSkewSpin(duration: 3.0) } }