diff --git a/Examples/PureGenius/PureGenius.playground/Contents.swift b/Examples/PureGenius/PureGenius.playground/Contents.swift new file mode 100644 index 0000000..d64a5eb --- /dev/null +++ b/Examples/PureGenius/PureGenius.playground/Contents.swift @@ -0,0 +1,81 @@ +import PlaygroundSupport +import SwiftUI + +struct PureGeniusView: View { + var body: some View { + ZStack { + Rectangle() + .fill() + .foregroundColor(.init(hue: 0.57, saturation: 0.25, brightness: 1)) + Circle() + .frame(width: 320, height: 320) + .foregroundColor(.init(hue: 0.8, saturation: 0.25, brightness: 0.75)) + VStack { + PGWordView(word: ["P", "U", "R", "E"]).offset(x: 0, y: 20) + PGWordView(word: ["G", "E", "N", "I", "U", "S"]).offset(x: 0, y: -20) + } + } + } +} + +struct PGWordView: View { + var word: [String] + var body: some View { + HStack { + ForEach(word.identified(by: \.self)) { letter in + PGLetterView(text: letter) + } + } + } +} + +struct PGLetterView: View { + var text: String + var body: some View { + ZStack { + MovingLetterView(text: text, color: .init(hue: 0.14, saturation: 0.56, brightness: 0.98)) + MovingLetterView(text: text, color: .init(hue: 0.37, saturation: 0.52, brightness: 0.7)) + } + } +} + +struct MovingLetterView: View { + var text: String + var color: Color + + @State var position: CGPoint = .zero + @State var activeTimer: Timer = nil + + private let animationDuration: Double = 2 + private let maxOffset: CGFloat = 10 + private var timer: Timer { + return Timer.scheduledTimer(withTimeInterval: self.animationDuration * 0.25, repeats: true) {_ in + let x = CGFloat(arc4random_uniform(UInt32(self.maxOffset))) - (self.maxOffset / 2) + let y = CGFloat(arc4random_uniform(UInt32(self.maxOffset))) - (self.maxOffset / 2) + self.position = CGPoint.init(x: x, y: y) + } + } + + var body: some View { + Text(text) + .color(self.color) + .font(Font.custom("Baskerville-Bold", size: 40)) + .bold() + .offset(by: self.position) + .animation(.basic(duration: self.animationDuration, curve: .easeInOut)) + .onAppear { + self.activeTimer = self.timer + } + .onDisappear { + self.activeTimer = nil + } + } +} + +extension View { + public func offset(by offset: CGPoint) -> Self.Modified<_OffsetEffect> { + self.offset(x: offset.x, y: offset.y) + } +} + +PlaygroundPage.current.liveView = UIHostingController(rootView: PureGeniusView()) diff --git a/Examples/PureGenius/PureGenius.playground/contents.xcplayground b/Examples/PureGenius/PureGenius.playground/contents.xcplayground new file mode 100644 index 0000000..5da2641 --- /dev/null +++ b/Examples/PureGenius/PureGenius.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/README.md b/README.md index 59acd2c..7e86c2b 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ See project [awesome-ios-ui](https://github.com/ivanvorobei/awesome-ios-ui) or v - [Animating Views And Transitions](#animating-views-and-transitions) - [Jike](#jike) - [Flux](#flux) +- [PureGenius](#puregenius) Also include: - Movie @@ -132,6 +133,10 @@ Also include: +#### PureGenius + + + #### Authors Thanks for [Jinxiansen](https://github.com/Jinxiansen), [ra1028](https://github.com/ra1028), [timdonnelly](https://github.com/timdonnelly), [TwoLivesLeft](https://github.com/TwoLivesLeft), [devxoul](https://github.com/devxoul), [cmtrounce](https://github.com/cmtrounce), [unixzii](https://github.com/unixzii), [ra1028](https://github.com/ra1028) for examples project. diff --git a/Resources/PureGenius.gif b/Resources/PureGenius.gif new file mode 100644 index 0000000..f538a1d Binary files /dev/null and b/Resources/PureGenius.gif differ