├── .travis.yml ├── Cartfile.resolved ├── Carthage └── Build │ └── iOS │ ├── 04BF2A7D-66CE-3F86-B5F4-63F27CD81E10.bcsymbolmap │ ├── 606D9ABB-D3D8-36C3-86CB-C50A0CCD2B2E.bcsymbolmap │ ├── AD87FA74-D7DD-3D31-B584-CE1A434CDD09.bcsymbolmap │ ├── B0A91A2F-DEE4-33E5-9145-CE7AE04AD4B6.bcsymbolmap │ ├── E17F6DD3-E41B-3903-A200-819DA6E97DE1.bcsymbolmap │ ├── FC36580D-9EB2-3A3A-A3CD-FCD3F10DEA18.bcsymbolmap │ ├── Stellar.framework.dSYM │ └── Contents │ │ ├── Info.plist │ │ └── Resources │ │ └── DWARF │ │ └── Stellar │ └── Stellar.framework │ ├── Headers │ ├── Stellar-Swift.h │ └── Stellar.h │ ├── Info.plist │ ├── Modules │ ├── Stellar.swiftmodule │ │ ├── arm.swiftdoc │ │ ├── arm.swiftmodule │ │ ├── arm64.swiftdoc │ │ ├── arm64.swiftmodule │ │ ├── i386.swiftdoc │ │ ├── i386.swiftmodule │ │ ├── x86_64.swiftdoc │ │ └── x86_64.swiftmodule │ └── module.modulemap │ └── Stellar ├── LICENSE ├── Package.swift ├── README.md ├── Sources ├── AnimationContext.swift ├── AnimationSequence.swift ├── AnimationStep.swift ├── AnimationType.swift ├── AnimatorCoordinator.swift ├── AttachmentConfigurable.swift ├── BasicChainable.swift ├── BasicConfigurable.swift ├── CALayer+AnimateBehavior.swift ├── CALayer+DriveAnimationBehaviors.swift ├── CALayer+Stellar.swift ├── Chainable.swift ├── DriveAnimateBehaviors.swift ├── DynamicItem+Behavior.swift ├── DynamicItem.swift ├── DynamicItemBasic.swift ├── DynamicItemGravity.swift ├── GravityConfigurable.swift ├── Interpolatable.swift ├── Physical.swift ├── SnapConfigurable.swift ├── StepControllable.swift ├── TimingFunction.swift ├── TimingSolvable.swift ├── TimingType.swift ├── UIDynamicBehavior+Commit.swift ├── UIView+AnimateBehavior.swift ├── UIView+Stellar.swift ├── UnitBezier.swift ├── Value+Physical.swift └── Vectorial.swift ├── Stellar.podspec ├── StellarDemo ├── Stellar │ ├── Info.plist │ └── Stellar.h ├── StellarDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── August.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ ├── xcshareddata │ │ └── xcschemes │ │ │ ├── Stellar.xcscheme │ │ │ └── StellarDemo.xcscheme │ └── xcuserdata │ │ └── August.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── StellarDemo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Ball.swift │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Example1ViewController.swift │ ├── Example2ViewController.swift │ ├── Example3ViewController.swift │ ├── Example4ViewController.swift │ ├── Example5ViewController.swift │ ├── Example6ViewController.swift │ ├── Example7ViewController.swift │ ├── Example8ViewController.swift │ ├── Info.plist │ ├── LiquidView.swift │ └── MyPlayground.playground │ │ ├── Contents.swift │ │ ├── Sources │ │ ├── Ball.swift │ │ └── Sources │ │ │ ├── AnimationContext.swift │ │ │ ├── AnimationSequence.swift │ │ │ ├── AnimationStep.swift │ │ │ ├── AnimationType.swift │ │ │ ├── AnimatorCoordinator.swift │ │ │ ├── AttachmentConfigurable.swift │ │ │ ├── BasicChainable.swift │ │ │ ├── BasicConfigurable.swift │ │ │ ├── CALayer+AnimateBehavior.swift │ │ │ ├── CALayer+DriveAnimationBehaviors.swift │ │ │ ├── CALayer+Stellar.swift │ │ │ ├── Chainable.swift │ │ │ ├── DriveAnimateBehaviors.swift │ │ │ ├── DynamicItem+Behavior.swift │ │ │ ├── DynamicItem.swift │ │ │ ├── DynamicItemBasic.swift │ │ │ ├── DynamicItemGravity.swift │ │ │ ├── GravityConfigurable.swift │ │ │ ├── Interpolatable.swift │ │ │ ├── Physical.swift │ │ │ ├── SnapConfigurable.swift │ │ │ ├── StepControllable.swift │ │ │ ├── TimingFunction.swift │ │ │ ├── TimingSolvable.swift │ │ │ ├── TimingType.swift │ │ │ ├── UIDynamicBehavior+Commit.swift │ │ │ ├── UILabel+Stellar.swift │ │ │ ├── UITextView+Stellar.swift │ │ │ ├── UIView+AnimateBehavior.swift │ │ │ ├── UIView+FileConfigurable.swift │ │ │ ├── UIView+Stellar.swift │ │ │ ├── UnitBezier.swift │ │ │ ├── Value+Physical.swift │ │ │ └── Vectorial.swift │ │ ├── contents.xcplayground │ │ └── timeline.xctimeline ├── StellarDemoTests │ ├── Info.plist │ └── StellarDemoTests.swift ├── StellarDemoUITests │ ├── Info.plist │ └── StellarDemoUITests.swift └── StellarTests │ ├── Info.plist │ └── StellarTests.swift ├── attachmentCurve.gif ├── balls.gif ├── basicCurve.gif ├── example4.gif ├── example5.gif ├── example6.gif ├── gravityCurve.gif ├── layers.gif ├── lines.gif ├── pushCurve.gif ├── snapCurve.gif └── title.png /.travis.yml: -------------------------------------------------------------------------------- 1 | language: Swift 2 | xcode_project: StellarDemo.xcodeproj 3 | before_install: 4 | - brew update 5 | - brew install carthage 6 | install: carthage bootstrap --verbose 7 | xcode_scheme: [Stellar, StellarDemo] 8 | xcode_sdk: [iphonesimulator8.3] 9 | osx_image: xcode7.3.1 10 | 11 | matrix: 12 | exclude: 13 | - xcode_scheme: Stellar 14 | xcode_sdk: iphonesimulator8.3 15 | 16 | branches: 17 | only: 18 | - master 19 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Cartfile.resolved -------------------------------------------------------------------------------- /Carthage/Build/iOS/B0A91A2F-DEE4-33E5-9145-CE7AE04AD4B6.bcsymbolmap: -------------------------------------------------------------------------------- 1 | BCSymbolMap Version: 2.0 2 | Apple LLVM version 8.1.0 (clang-802.0.41) 3 | /Users/baidu/Library/Developer/Xcode/DerivedData/StellarDemo-bdrzozoakxfmsidxdfvqkvpaffyx/Build/Intermediates/StellarDemo.build/Release-iphoneos/Stellar.build/DerivedSources/Stellar_vers.c 4 | /Users/baidu/MyVendors/Stellar/StellarDemo 5 | -------------------------------------------------------------------------------- /Carthage/Build/iOS/E17F6DD3-E41B-3903-A200-819DA6E97DE1.bcsymbolmap: -------------------------------------------------------------------------------- 1 | BCSymbolMap Version: 2.0 2 | Apple LLVM version 8.1.0 (clang-802.0.41) 3 | /Users/baidu/Library/Developer/Xcode/DerivedData/StellarDemo-bdrzozoakxfmsidxdfvqkvpaffyx/Build/Intermediates/StellarDemo.build/Release-iphoneos/Stellar.build/DerivedSources/Stellar_vers.c 4 | /Users/baidu/MyVendors/Stellar/StellarDemo 5 | -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework.dSYM/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>English</string> 7 | <key>CFBundleIdentifier</key> 8 | <string>com.apple.xcode.dsym.AR.Stellar</string> 9 | <key>CFBundleInfoDictionaryVersion</key> 10 | <string>6.0</string> 11 | <key>CFBundlePackageType</key> 12 | <string>dSYM</string> 13 | <key>CFBundleSignature</key> 14 | <string>????</string> 15 | <key>CFBundleShortVersionString</key> 16 | <string>1.0</string> 17 | <key>CFBundleVersion</key> 18 | <string>1</string> 19 | </dict> 20 | </plist> 21 | -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework.dSYM/Contents/Resources/DWARF/Stellar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework.dSYM/Contents/Resources/DWARF/Stellar -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Headers/Stellar.h: -------------------------------------------------------------------------------- 1 | // 2 | // Stellar.h 3 | // Stellar 4 | // 5 | // Created by AugustRush on 6/6/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | //! Project version number for Stellar. 12 | FOUNDATION_EXPORT double StellarVersionNumber; 13 | 14 | //! Project version string for Stellar. 15 | FOUNDATION_EXPORT const unsigned char StellarVersionString[]; 16 | #import "Stellar-Swift.h" 17 | // In this header, you should import all the public headers of your framework using statements like #import <Stellar/PublicHeader.h> 18 | 19 | 20 | -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Info.plist -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm64.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm64.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/arm64.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/i386.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/i386.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/i386.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/i386.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/x86_64.swiftdoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/x86_64.swiftdoc -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/x86_64.swiftmodule: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Modules/Stellar.swiftmodule/x86_64.swiftmodule -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module Stellar { 2 | umbrella header "Stellar.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | 8 | module Stellar.Swift { 9 | header "Stellar-Swift.h" 10 | } 11 | -------------------------------------------------------------------------------- /Carthage/Build/iOS/Stellar.framework/Stellar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/Carthage/Build/iOS/Stellar.framework/Stellar -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | //EasyLayout 2 | //Copyright (c) 2016 3 | // 4 | //Permission is hereby granted, free of charge, to any person obtaining a copy 5 | //of this software and associated documentation files (the "Software"), to deal 6 | //in the Software without restriction, including without limitation the rights 7 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | //copies of the Software, and to permit persons to whom the Software is 9 | //furnished to do so, subject to the following conditions: 10 | // 11 | //The above copyright notice and this permission notice shall be included in all 12 | //copies or substantial portions of the Software. 13 | // 14 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | //SOFTWARE. 21 | 22 | import PackageDescription 23 | 24 | let package = Package(name: "Stellar") -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | <img src="https://github.com/AugustRush/Stellar/blob/master/title.png"> 2 | 3 | [](https://github.com/Carthage/Carthage) 4 |  [](https://github.com/AugustRush/Stellar/blob/master/LICENSE.md) [](https://codebeat.co/projects/github-com-augustrush-stellar) []() []() 5 | 6 | A fantastic Physical animation library for swift(Not Just Spring !!!), it is base on UIDynamic and extension to it, friendly APIs make you use it or custom your own animation very easily! 7 | 8 | ## Support 9 | 10 | ### Integration 11 | #### Cocoapods(iOS 8+) 12 | * You can use [Cocoapods](https://cocoapods.org/) to install Stellar by adding it to your Podfile: 13 | 14 | ``` 15 | platform :ios, '8.0' 16 | use_frameworks! 17 | 18 | target 'YourApp' do 19 | pod 'Stellar', :git => 'https://github.com/AugustRush/Stellar.git' 20 | end 21 | ``` 22 | 23 | #### Carthage (iOS 8+) 24 | * You can use [Carthage](https://github.com/Carthage/Carthage) to install Stellar by adding it to your Cartfile: 25 | 26 | ``` 27 | github "AugustRush/Stellar" 28 | ``` 29 | 30 | #### Manually (iOS 8+) 31 | To use this library in your project manually you may: 32 | 33 | - for Projects, just drag Stellar [Sources](https://github.com/AugustRush/Stellar/tree/master/Sources) to the project tree 34 | - for Workspaces, include the whole StellarDemo.xcodeproj 35 | 36 | ### Features 37 | ``` 38 | - View's Animation 39 | - Layer's Animation 40 | - Chainable (every step can be observed) 41 | - File configurable (come soon) 42 | ``` 43 | ### Animations 44 | ``` 45 | - Basic 46 | - Gravity 47 | - Snap 48 | - Attachment 49 | - Push 50 | - Collsion(come soon) 51 | ``` 52 | ### Animatable type 53 | ``` 54 | - Float 55 | - CGFloat 56 | - Double 57 | - CGSize 58 | - CGPoint 59 | - CGRect 60 | - UIColor 61 | - ......(Any Intrpolatable) 62 | ``` 63 | ### Easing Curve (Base Animation) 64 | 65 | ```swift 66 | - Default 67 | - EaseIn 68 | - EaseOut 69 | - EaseInEaseOut 70 | - Linear 71 | - SwiftOut 72 | - BackEaseIn 73 | - BackEaseOut 74 | - BackEaseInOut 75 | - BounceOut 76 | - Sine 77 | - Circ 78 | - ExponentialIn 79 | - ExponentialOut 80 | - ElasticIn 81 | - ElasticOut 82 | - BounceReverse 83 | - Custom(Double, Double, Double, Double) 84 | ``` 85 | ## On display 86 | 87 | #### Funny demo's gif(s) 88 | <img src="https://github.com/AugustRush/Stellar/blob/master/example5.gif" width="320"> 89 | <img src="https://github.com/AugustRush/Stellar/blob/master/balls.gif" width="320"> 90 | <img src="https://github.com/AugustRush/Stellar/blob/master/layers.gif" width="320"> 91 | <img src="https://github.com/AugustRush/Stellar/blob/master/example6.gif" width="320"> 92 | 93 | #### Chainable 94 | 95 | 1) Common</br> 96 | 97 | <img src="https://github.com/AugustRush/Stellar/blob/master/lines.gif" width="200"> 98 | 99 | ``` swift 100 | for (index,line) in leftLines.enumerate() { 101 | let delay = Double(index) * 0.2 102 | 103 | line.moveX(200).duration(2).easing(.SwiftOut).delay(delay) 104 | .then().moveX(-200).rotateY(1.43).easing(.SwiftOut) 105 | .makeColor(UIColor.greenColor()).repeatCount(100) 106 | .autoreverses().duration(2).animate() 107 | } 108 | 109 | for (index,line) in rightLines.enumerate() { 110 | let delay = Double(index) * 0.2 111 | 112 | line.moveX(-200).duration(2).easing(.SwiftOut).delay(delay) 113 | .then().moveX(200).rotateY(1.43).easing(.SwiftOut) 114 | .makeColor(UIColor.purpleColor()).repeatCount(100) 115 | .autoreverses().duration(2).animate() 116 | } 117 | ``` 118 | 119 | 2) every step completion observable </br> 120 | 121 | <img src="https://github.com/AugustRush/Stellar/blob/master/example4.gif" width="200"> 122 | 123 | ``` swift 124 | animateView.makeSize(CGSizeMake(50, 150)).snap(0.3).completion({ 125 | print("First step") 126 | }) 127 | .then().moveX(-100).moveY(-50).anchorPoint(CGPointMake(1, 1)).duration(1).completion({ 128 | print("Second step!") 129 | }) 130 | .then().rotate(CGFloat(M_PI)).attachment(0.3, frequency: 0.8).completion({ 131 | print("Third step!") 132 | }) 133 | .then().moveY(500).completion({ 134 | print("last step, all completion") 135 | }) 136 | .animate() 137 | ``` 138 | 139 | ---------- 140 | #### Snap Curve 141 | <img src="https://github.com/AugustRush/Stellar/blob/master/snapCurve.gif"> 142 | 143 | #### Attachment Curve 144 | <img src="https://github.com/AugustRush/Stellar/blob/master/attachmentCurve.gif"> 145 | 146 | #### Gravity Curve 147 | <img src="https://github.com/AugustRush/Stellar/blob/master/gravityCurve.gif"> 148 | 149 | #### Push Curve 150 | <img src="https://github.com/AugustRush/Stellar/blob/master/pushCurve.gif"> 151 | 152 | #### Basic Curve 153 | <img src="https://github.com/AugustRush/Stellar/blob/master/basicCurve.gif"> 154 | 155 | ### To do 156 | ``` 157 | - File configurable 158 | - Easily Interactive Animations 159 | - Collision 160 | - Mutilple View/Layer performance 161 | - More demos 162 | ``` 163 | ### Licence 164 | ``` 165 | Copyright (c) 2016 166 | 167 | Permission is hereby granted, free of charge, to any person obtaining a copy 168 | of this software and associated documentation files (the "Software"), to deal 169 | in the Software without restriction, including without limitation the rights 170 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 171 | copies of the Software, and to permit persons to whom the Software is 172 | furnished to do so, subject to the following conditions: 173 | 174 | The above copyright notice and this permission notice shall be included in all 175 | copies or substantial portions of the Software. 176 | 177 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 179 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 180 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 181 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 182 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 183 | SOFTWARE. 184 | ``` 185 | -------------------------------------------------------------------------------- /Sources/AnimationContext.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal class AnimationContext: NSObject, UIDynamicAnimatorDelegate, AnimationSequenceDelegate { 12 | fileprivate weak var object: DriveAnimateBehaviors! 13 | fileprivate var mutipleSequences = [AnimationSequence]() 14 | 15 | //MARK: init method 16 | init(object: DriveAnimateBehaviors) { 17 | self.object = object 18 | } 19 | 20 | //MARK: public methods 21 | func addAnimationType(_ type: AnimationType) { 22 | let step = lastStep() 23 | step.types.append(type) 24 | } 25 | 26 | func changeDuration(_ d: CFTimeInterval) { 27 | let step = lastStep() 28 | step.duration = d 29 | } 30 | 31 | func changeDelay(_ d: CFTimeInterval) { 32 | let step = lastStep() 33 | step.delay = d 34 | } 35 | 36 | func changeAutoreverses(_ a: Bool) { 37 | let step = lastStep() 38 | step.autoreverses = a 39 | } 40 | 41 | func changeRepeatCount(_ count: Int) { 42 | let step = lastStep() 43 | step.repeatCount = count 44 | } 45 | 46 | func changeCompletion(_ c: @escaping () -> Void) { 47 | let step = lastStep() 48 | step.completion = c 49 | } 50 | 51 | func changeEasing(_ e: TimingFunctionType) { 52 | let step = lastStep() 53 | step.timing = e 54 | } 55 | 56 | func changeMainType(_ type: AnimationStyle) { 57 | let step = lastStep() 58 | let lastAnimationType = step.types.last 59 | guard let _ = lastAnimationType else { 60 | print("You should defined animaton first!") 61 | return 62 | } 63 | 64 | lastAnimationType!.mainType = type 65 | } 66 | 67 | func makeNextStep() { 68 | let step = AnimationStep() 69 | lastSequence().addStep(step) 70 | } 71 | 72 | @discardableResult 73 | func makeNextSequence() -> AnimationSequence { 74 | let sequence = AnimationSequence(object: self.object) 75 | sequence.delegate = self 76 | mutipleSequences.append(sequence) 77 | 78 | return sequence 79 | } 80 | 81 | func commit() { 82 | //start all sequence 83 | for sequence in mutipleSequences { 84 | sequence.start() 85 | } 86 | //make a temple sequence for next step 87 | makeNextSequence() 88 | } 89 | 90 | func removeAllRemaining() { 91 | for sequence in mutipleSequences { 92 | sequence.removeAllSteps() 93 | } 94 | mutipleSequences.removeAll() 95 | } 96 | 97 | 98 | //MARK: private methods 99 | 100 | fileprivate func lastSequence() -> AnimationSequence { 101 | var sequence = mutipleSequences.last 102 | if sequence == nil { 103 | sequence = makeNextSequence() 104 | } 105 | 106 | return sequence! 107 | } 108 | 109 | fileprivate func lastStep() -> AnimationStep { 110 | let sequence = lastSequence() 111 | var step = sequence.last() 112 | if step == nil { 113 | step = AnimationStep() 114 | sequence.addStep(step!) 115 | } 116 | return step! 117 | } 118 | 119 | //MARK: AnimationSequenceDelegate methods 120 | 121 | func animationSequenceDidComplete(_ sequence: AnimationSequence) { 122 | let index = mutipleSequences.firstIndex(of: sequence) 123 | if index != nil { 124 | mutipleSequences.remove(at: index!) 125 | } 126 | } 127 | } 128 | 129 | -------------------------------------------------------------------------------- /Sources/AnimationSequence.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | protocol AnimationSequenceDelegate: class { 12 | func animationSequenceDidComplete(_ sequence: AnimationSequence); 13 | } 14 | 15 | internal class AnimationSequence: NSObject, UIDynamicAnimatorDelegate { 16 | var steps: [AnimationStep] = Array() 17 | weak var view: DriveAnimateBehaviors! 18 | weak var delegate: AnimationSequenceDelegate? 19 | var isRuning = false 20 | lazy var animator: UIDynamicAnimator = { 21 | let animator = UIDynamicAnimator() 22 | animator.delegate = self 23 | return animator 24 | }() 25 | 26 | //MARK: init method 27 | 28 | init(object: DriveAnimateBehaviors) { 29 | self.view = object 30 | } 31 | 32 | //MARK: internal method 33 | func addStep(_ step: AnimationStep) { 34 | steps.append(step) 35 | } 36 | 37 | func last() -> AnimationStep? { 38 | return steps.last 39 | } 40 | 41 | func start() { 42 | if !isRuning { 43 | isRuning = true 44 | excuteFirstStepIfExist() 45 | } 46 | } 47 | 48 | func removeAllSteps() { 49 | steps.removeAll() 50 | } 51 | 52 | fileprivate func excuteFirstStepIfExist() { 53 | 54 | if self.view == nil { 55 | return 56 | } 57 | 58 | let step = steps.first 59 | 60 | if let step = step { 61 | //if step has no animation types it must be the last temple step 62 | if step.types.count == 0 { 63 | steps.removeFirst() 64 | popFirstStepIfExsist() 65 | return 66 | } 67 | 68 | for type in step.types { 69 | let behavior = view.behavior(forType: type, step: step) 70 | animator.addBehavior(behavior) 71 | } 72 | 73 | } else { 74 | popFirstStepIfExsist() 75 | } 76 | } 77 | 78 | fileprivate func popFirstStepIfExsist() { 79 | if !steps.isEmpty { 80 | let step = steps.first! 81 | //excute completion 82 | step.completion?() 83 | steps.removeFirst() 84 | } else { 85 | // all steps has completion 86 | self.delegate?.animationSequenceDidComplete(self) 87 | } 88 | } 89 | 90 | //MARK: UIDynamicAnimatorDelegate methods 91 | func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) { 92 | animator.removeAllBehaviors() 93 | popFirstStepIfExsist() 94 | excuteFirstStepIfExist() 95 | } 96 | 97 | func dynamicAnimatorWillResume(_ animator: UIDynamicAnimator) { 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Sources/AnimationStep.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal class AnimationStep { 12 | var types = [AnimationType]() 13 | var duration: CFTimeInterval = 0.25 14 | var timing: TimingFunctionType = .default 15 | var delay: CFTimeInterval = 0.0 16 | var autoreverses: Bool = false 17 | var repeatCount: Int = 0 18 | var completion: (() -> Void)? 19 | } 20 | -------------------------------------------------------------------------------- /Sources/AnimationType.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | enum AnimationSubType { 12 | case moveX(CGFloat) 13 | case moveY(CGFloat) 14 | case moveXY(CGFloat,CGFloat)//Layer 15 | case moveTo(CGPoint) 16 | case color(UIColor) 17 | case alpha(CGFloat) 18 | case opacity(Float)//Layer 19 | case rotateX(CGFloat) 20 | case rotateY(CGFloat) 21 | case rotate(CGFloat) 22 | case rotateXY(CGFloat) 23 | case width(CGFloat) 24 | case height(CGFloat) 25 | case size(CGSize) 26 | case frame(CGRect) 27 | case bounds(CGRect) 28 | case scaleX(CGFloat) 29 | case scaleY(CGFloat) 30 | case scaleXY(CGFloat,CGFloat) 31 | case cornerRadius(CGFloat) 32 | case borderWidth(CGFloat) 33 | case shadowRadius(CGFloat) 34 | case zPosition(CGFloat) 35 | case anchorPoint(CGPoint) 36 | case anchorPointZ(CGFloat) 37 | case shadowOffset(CGSize) 38 | case shadowColor(UIColor) 39 | case shadowOpacity(Float) 40 | case tintColor(UIColor) 41 | // UILabel,UITextView... 42 | case textColor(UIColor) 43 | } 44 | 45 | //temp record for animation type 46 | internal class AnimationType { 47 | var mainType: AnimationStyle 48 | var subType: AnimationSubType 49 | 50 | init (type: AnimationStyle, subType: AnimationSubType) { 51 | self.mainType = type 52 | self.subType = subType 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/AnimatorCoordinator.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal class AnimatorCoordinator: NSObject, UIDynamicAnimatorDelegate { 12 | static let shared = AnimatorCoordinator() 13 | fileprivate var activedAnimators: [UIDynamicAnimator] = Array() 14 | fileprivate var basicAnimator = UIDynamicAnimator() 15 | 16 | //MARK: public methods 17 | func addBasicBehavior(_ b: UIDynamicBehavior) { 18 | basicAnimator.addBehavior(b) 19 | } 20 | func addBehavior(_ b: UIDynamicBehavior) { 21 | addBehaviors([b]) 22 | } 23 | 24 | func addBehaviors(_ behaviors: [UIDynamicBehavior]) { 25 | 26 | let animator = activedAnimators.last 27 | for b in behaviors { 28 | 29 | if let exsist = animator { 30 | switch b { 31 | case b as UIGravityBehavior: 32 | fallthrough 33 | case b as UICollisionBehavior: 34 | createAnimator(b) 35 | default: 36 | exsist.addBehavior(b) 37 | } 38 | 39 | } else { 40 | createAnimator(b) 41 | } 42 | } 43 | } 44 | 45 | fileprivate func createAnimator(_ behavior: UIDynamicBehavior) { 46 | let animator = UIDynamicAnimator() 47 | animator.delegate = self 48 | animator.addBehavior(behavior) 49 | activedAnimators.append(animator) 50 | } 51 | 52 | 53 | //MARK: UIDynamicAnimatorDelegate methods 54 | 55 | func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) { 56 | let index = activedAnimators.firstIndex(of: animator) 57 | activedAnimators.remove(at: index!) 58 | } 59 | 60 | func dynamicAnimatorWillResume(_ animator: UIDynamicAnimator) { 61 | // 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Sources/AttachmentConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol AttachmentConfigurable: BasicChainable { 12 | func attachment(_ damping: CGFloat, frequency: CGFloat) -> Self 13 | } 14 | -------------------------------------------------------------------------------- /Sources/BasicChainable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol BasicChainable: Chainable { 12 | func moveX(_ increment: CGFloat) -> Self 13 | func moveY(_ increment: CGFloat) -> Self 14 | func moveTo(_ point: CGPoint) -> Self 15 | func makeColor(_ color: UIColor) -> Self 16 | func makeAlpha(_ alpha: CGFloat) -> Self 17 | func rotate(_ z: CGFloat) -> Self 18 | func rotateX(_ x: CGFloat) -> Self 19 | func rotateY(_ y: CGFloat) -> Self 20 | func rotateXY(_ xy: CGFloat) -> Self 21 | func makeWidth(_ width: CGFloat) -> Self 22 | func makeHeight(_ height: CGFloat) -> Self 23 | func makeSize(_ size: CGSize) -> Self 24 | func makeFrame(_ frame: CGRect) -> Self 25 | func makeBounds(_ bounds: CGRect) -> Self 26 | func scaleX(_ x: CGFloat) -> Self 27 | func scaleY(_ y: CGFloat) -> Self 28 | func scaleXY(_ x: CGFloat, _ y: CGFloat) -> Self 29 | func cornerRadius(_ radius: CGFloat) -> Self 30 | func borderWidth(_ width: CGFloat) -> Self 31 | func shadowRadius(_ radius: CGFloat) -> Self 32 | func zPosition(_ position: CGFloat) -> Self 33 | func anchorPoint(_ point: CGPoint) -> Self 34 | func anchorPointZ(_ z: CGFloat) -> Self 35 | func shadowOffset(_ offset: CGSize) -> Self 36 | func shadowColor(_ color: UIColor) -> Self 37 | func shadowOpacity(_ opacity: Float) -> Self 38 | func makeTintColor(_ color: UIColor) -> Self 39 | func completion(_ c: @escaping () -> Void) -> Self 40 | } 41 | -------------------------------------------------------------------------------- /Sources/BasicConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol BasicConfigurable: BasicChainable { 12 | func duration(_ d: CFTimeInterval) -> Self 13 | func easing(_ type: TimingFunctionType) -> Self 14 | func delay(_ d: CFTimeInterval) -> Self 15 | func reverses() -> Self 16 | func repeatCount(_ count: Int) -> Self 17 | } 18 | -------------------------------------------------------------------------------- /Sources/CALayer+DriveAnimationBehaviors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+DriveAnimationBehaviors.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/21/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /Sources/Chainable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol Chainable { 12 | //Chainable methods 13 | func then() -> Self 14 | func animate() -> Void 15 | } 16 | -------------------------------------------------------------------------------- /Sources/DriveAnimateBehaviors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DriveAnimateBehaviors.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/21/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol DriveAnimateBehaviors: class { 12 | func behavior(forType type: AnimationType, step: AnimationStep) -> UIDynamicBehavior 13 | } 14 | -------------------------------------------------------------------------------- /Sources/DynamicItem+Behavior.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | enum PhysicalDirection { 12 | case left 13 | case right 14 | case up 15 | case down 16 | case Angle(CGFloat) 17 | case vector(CGFloat,CGFloat) 18 | 19 | func angle() -> CGFloat { 20 | switch self { 21 | case .Angle(let a): 22 | return a 23 | case .vector(let x, let y): 24 | return atan2(y, x) 25 | case .left: 26 | return atan2(0, -1) 27 | case .right: 28 | return atan2(0, 1) 29 | case .up: 30 | return atan2(-1, 0) 31 | case .down: 32 | return atan2(1, 0) 33 | } 34 | } 35 | } 36 | 37 | extension UIDynamicItem { 38 | 39 | //gravity 40 | func gravityBehavior(_ magnitude: CGFloat = 1.0, direction: PhysicalDirection = .down) -> UIGravityBehavior { 41 | let gravity = UIGravityBehavior() 42 | switch direction { 43 | case .Angle(let a): 44 | gravity.setAngle(a, magnitude: magnitude) 45 | case .left: 46 | gravity.gravityDirection = CGVector(dx: -1, dy: 0) 47 | case .right: 48 | gravity.gravityDirection = CGVector(dx: 1, dy: 0) 49 | case .up: 50 | gravity.gravityDirection = CGVector(dx: 0, dy: -1) 51 | case .down: 52 | gravity.gravityDirection = CGVector(dx: 0, dy: 1) 53 | case .vector(let x, let y): 54 | gravity.gravityDirection = CGVector(dx: x, dy: y) 55 | } 56 | gravity.magnitude = magnitude 57 | gravity.addItem(self) 58 | return gravity 59 | } 60 | 61 | //snap 62 | func snapBehavior(_ toPoint: CGPoint, damping: CGFloat = 0.5) -> UISnapBehavior { 63 | let snap = UISnapBehavior(item: self,snapTo: toPoint) 64 | snap.damping = damping 65 | return snap 66 | } 67 | 68 | //attachment 69 | func attachmentBehavior(_ toAnchor: CGPoint, length: CGFloat = 0.0, damping: CGFloat = 0.5, frequency: CGFloat = 1.0) -> UIAttachmentBehavior { 70 | let attachment = UIAttachmentBehavior(item: self,attachedToAnchor: toAnchor) 71 | attachment.length = length 72 | attachment.damping = damping 73 | attachment.frequency = frequency 74 | return attachment 75 | } 76 | 77 | func attachmentBehavior(_ toItem: UIDynamicItem, damping: CGFloat = 0.5, frequency: CGFloat = 1.0) -> UIAttachmentBehavior { 78 | let attachment = UIAttachmentBehavior(item: self,attachedTo: toItem) 79 | attachment.damping = damping 80 | attachment.frequency = frequency 81 | return attachment 82 | } 83 | 84 | func attachmentBehavior(_ toItem: UIDynamicItem, damping: CGFloat = 0.5, frequency: CGFloat = 1.0, length: CGFloat = 0.0) -> UIAttachmentBehavior { 85 | let attachment = UIAttachmentBehavior(item: self,attachedTo: toItem) 86 | attachment.damping = damping 87 | attachment.length = length 88 | attachment.frequency = frequency 89 | return attachment 90 | } 91 | 92 | //push 93 | func pushBehavior(_ direction: CGVector, mode:UIPushBehavior.Mode = .instantaneous, magnitude: CGFloat = 1.0) -> UIPushBehavior { 94 | let push = UIPushBehavior(items: [self], mode: mode) 95 | push.pushDirection = direction 96 | push.magnitude = magnitude 97 | return push 98 | } 99 | 100 | func pushBehavior(_ direction: PhysicalDirection, mode:UIPushBehavior.Mode = .continuous, magnitude: CGFloat = 1.0) -> UIPushBehavior { 101 | let push = UIPushBehavior(items: [self], mode: mode) 102 | switch direction { 103 | case .Angle(let a): 104 | push.setAngle(a, magnitude: magnitude) 105 | case .left: 106 | push.pushDirection = CGVector(dx: -1, dy: 0) 107 | case .right: 108 | push.pushDirection = CGVector(dx: 1, dy: 0) 109 | case .up: 110 | push.pushDirection = CGVector(dx: 0, dy: -1) 111 | case .down: 112 | push.pushDirection = CGVector(dx: 0, dy: 1) 113 | case .vector(let x, let y): 114 | push.pushDirection = CGVector(dx: x, dy: y) 115 | } 116 | 117 | push.magnitude = magnitude 118 | return push 119 | } 120 | 121 | 122 | func pushBehavior(_ angle: CGFloat, mode:UIPushBehavior.Mode = .instantaneous, magnitude: CGFloat = 1.0) -> UIPushBehavior { 123 | let push = UIPushBehavior(items: [self], mode: mode) 124 | push.angle = angle 125 | push.magnitude = magnitude 126 | return push 127 | } 128 | 129 | //collision 130 | func collisionBehavior(_ mode: UICollisionBehavior.Mode = .boundaries) -> UICollisionBehavior { 131 | let collision = UICollisionBehavior() 132 | collision.collisionMode = mode 133 | collision.addItem(self) 134 | return collision 135 | } 136 | 137 | func collisionBehavior(_ mode: UICollisionBehavior.Mode = .boundaries, path: UIBezierPath) -> UICollisionBehavior { 138 | let collision = UICollisionBehavior() 139 | collision.collisionMode = mode 140 | let identifier = String(describing: Unmanaged.passUnretained(self).toOpaque()) 141 | collision.addBoundary(withIdentifier: identifier as NSCopying, for: path) 142 | collision.addItem(self) 143 | return collision 144 | } 145 | 146 | func collisionBehavior(_ mode: UICollisionBehavior.Mode = .boundaries, fromPoint: CGPoint, toPoint: CGPoint) -> UICollisionBehavior { 147 | let collision = UICollisionBehavior() 148 | collision.collisionMode = mode 149 | let identifier = String(describing: Unmanaged.passUnretained(self).toOpaque()) 150 | collision.addBoundary(withIdentifier: identifier as NSCopying, from: fromPoint, to: toPoint) 151 | collision.addItem(self) 152 | return collision 153 | } 154 | 155 | //itemBehavior 156 | func itemBehavior(_ elasticity: CGFloat = 0.5, friction: CGFloat = 0.5, density: CGFloat = 1, resistance: CGFloat = 0, angularResistance: CGFloat = 0, allowsRotation: Bool = true) -> UIDynamicItemBehavior { 157 | let behavior = UIDynamicItemBehavior() 158 | behavior.addItem(self) 159 | behavior.elasticity = elasticity 160 | behavior.friction = friction 161 | behavior.density = density 162 | behavior.resistance = resistance 163 | behavior.angularResistance = angularResistance 164 | behavior.allowsRotation = allowsRotation 165 | return behavior 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Sources/DynamicItem.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | //for 4 latitude 12 | final class DynamicItem<T: Vectorial>: NSObject, UIDynamicItem { 13 | 14 | var from: T 15 | var to: T 16 | var render: (T) -> Void 17 | var complete = false 18 | var boundaryLimit = false 19 | var completion: (() -> Void)? 20 | internal var fromR: Vector4 21 | internal var toR: Vector4 22 | weak var behavior: UIDynamicBehavior! 23 | fileprivate var change: (x: Double,y: Double,z: Double,w: Double) 24 | var referenceChangeLength: Double 25 | 26 | init(from: T, to: T, render: @escaping (T) -> Void) { 27 | self.from = from 28 | self.to = to 29 | self.render = render 30 | // 31 | self.fromR = from.reverse() 32 | self.toR = to.reverse() 33 | // 34 | let x = toR.one - fromR.one 35 | let y = toR.two - fromR.two 36 | let z = toR.three - fromR.three 37 | let w = toR.four - fromR.four 38 | self.change = (x,y,z,w) 39 | // 40 | let originChange = sqrt(x*x + y*y) 41 | let sizeChange = sqrt(z*z + w*w) 42 | self.referenceChangeLength = max(originChange, sizeChange) 43 | } 44 | 45 | deinit { 46 | self.render(to) 47 | complete = true 48 | completion?() 49 | } 50 | 51 | //MARK: Update frame 52 | 53 | func updateFrame() { 54 | let yChange = fabs(Double(center.y)) 55 | let progress = yChange / referenceChangeLength 56 | let curX = fromR.one + change.x * progress; 57 | let curY = fromR.two + change.y * progress; 58 | let curZ = fromR.three + change.z * progress; 59 | let curW = fromR.four + change.w * progress; 60 | 61 | let rect = Vector4.init((curX.isNaN ? 0 : curX,curY.isNaN ? 0 : curY,curZ.isNaN ? 0 : curZ,curW.isNaN ? 0 : curZ)) 62 | var curV = from.convert(rect) 63 | if progress >= 1.0 { 64 | if boundaryLimit { 65 | curV = to 66 | behavior.cancel() 67 | complete = true 68 | } 69 | } 70 | self.render(curV) 71 | } 72 | 73 | //MARK: UIDynamicItem protocol 74 | var center: CGPoint = CGPoint.zero { 75 | didSet { 76 | updateFrame() 77 | } 78 | } 79 | 80 | var transform: CGAffineTransform = CGAffineTransform.identity 81 | var bounds: CGRect { 82 | get { 83 | return CGRect(x: -50.0, y: -50.0, width: 100.0, height: 100.0) 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Sources/DynamicItemBasic.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | private let SolveForReverse = { (f: CFTimeInterval) in 12 | return 1 - f 13 | } 14 | 15 | private let SolveForUnReverse = { (f: CFTimeInterval) in 16 | return f 17 | } 18 | 19 | final class DynamicItemBasic<T: Interpolatable>: NSObject, UIDynamicItem, TimingType { 20 | 21 | var duration: CFTimeInterval = 0.25 22 | var delay: CFTimeInterval = 0.0 23 | var timingFunction: TimingSolvable = TimingFunctionType.default.easing() 24 | var from: T 25 | var to: T 26 | var render: (T) -> Void 27 | var autoreverses = false 28 | var repeatCount = 0 29 | var completion: ((Bool) -> Void)? 30 | var speed: Double = 1.0 31 | var timeOffset: CFTimeInterval = 0.0 { 32 | didSet { 33 | updateFrame() 34 | } 35 | } 36 | 37 | weak var behavior: UIDynamicBehavior? 38 | //External data to store (performance) 39 | fileprivate var externalData: Any? 40 | fileprivate var complete = false 41 | fileprivate var isReversing = false 42 | fileprivate var solveProgress = SolveForUnReverse 43 | fileprivate lazy var beginTime: CFTimeInterval = { 44 | return CACurrentMediaTime() 45 | }() 46 | fileprivate lazy var epsilon: Double = { 47 | return 1.0 / (self.duration * 1000.0) 48 | }() 49 | 50 | //MARK: Life cycle methods 51 | init(from: T, to: T, render: @escaping (T) -> Void) { 52 | self.from = from 53 | self.to = to 54 | self.render = render 55 | 56 | if let fromColor = from as? UIColor { 57 | let fromInfo = fromColor.colorInfo() 58 | let toColor = to as! UIColor 59 | let toInfo = toColor.colorInfo() 60 | self.externalData = (fromInfo,toInfo) 61 | } 62 | } 63 | 64 | deinit { 65 | //do some thing 66 | } 67 | 68 | //MARK: update frame 69 | fileprivate func updateFrame() { 70 | let startTime = beginTime 71 | var currentTime = CACurrentMediaTime() - startTime - delay 72 | currentTime = max(0, currentTime) * speed + timeOffset 73 | var progress = currentTime / duration 74 | if progress >= 1.0 { 75 | isReversing = autoreverses ? !isReversing : false 76 | if repeatCount == 0 { 77 | if isReversing { 78 | progress = 0.0 79 | beginTime = CACurrentMediaTime() 80 | solveProgress = SolveForReverse 81 | } else { 82 | progress = 1.0 83 | behavior?.cancel() 84 | complete = true 85 | self.completion?(complete) 86 | } 87 | }else { 88 | if isReversing == false { 89 | repeatCount -= 1 90 | solveProgress = SolveForUnReverse 91 | } else { 92 | solveProgress = SolveForReverse 93 | } 94 | progress = 0.0 95 | beginTime = CACurrentMediaTime() 96 | } 97 | } 98 | let solveP = solveProgress(progress) 99 | let adjustProgress = timingFunction.solveOn(solveP, epslion: epsilon) 100 | let value = from.interpolate(adjustProgress, to: to, externalData: externalData) 101 | self.render(value) 102 | } 103 | 104 | //MARK: UIDynamicItem protocol 105 | var center: CGPoint = CGPoint.zero { 106 | didSet { 107 | updateFrame() 108 | } 109 | } 110 | 111 | var transform: CGAffineTransform = CGAffineTransform.identity 112 | var bounds: CGRect { 113 | get { 114 | return CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0) 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Sources/DynamicItemGravity.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | class DynamicItemGravity<T: Interpolatable>: NSObject, UIDynamicItem { 12 | 13 | var from: T! 14 | var to: T! 15 | var magnitude = 1.0 16 | var render: (T) -> Void 17 | var completion: (() -> Void)? 18 | var boundary = true 19 | weak var behavior: UIDynamicBehavior? 20 | //private vars 21 | fileprivate var referenceChangedLength: Double = 0.0 22 | //External data to store (performance) 23 | fileprivate var externalData: Any? 24 | fileprivate lazy var beginTime = { 25 | return CACurrentMediaTime() 26 | }() 27 | 28 | //MARK: init method 29 | init(from: T, to: T, render: @escaping (T) -> Void) { 30 | self.from = from 31 | self.to = to 32 | self.render = render 33 | super.init() 34 | caculateReferenceChangedLength() 35 | } 36 | 37 | deinit { 38 | self.completion?() 39 | } 40 | 41 | //MARK: private methods 42 | fileprivate func caculateReferenceChangedLength() { 43 | switch from { 44 | case let f as CGFloat: 45 | let t = to as! CGFloat 46 | referenceChangedLength = Double(abs(t - f)) 47 | 48 | case let f as Float: 49 | let t = to as! Float 50 | referenceChangedLength = Double(abs(t - f)) 51 | 52 | case let f as Double: 53 | let t = to as! Double 54 | referenceChangedLength = abs(t - f) 55 | 56 | case let f as CGSize: 57 | let t = to as! CGSize 58 | let w = abs(t.width - f.width) 59 | let h = abs(t.height - f.height) 60 | referenceChangedLength = max(Double(w), Double(h)) 61 | 62 | case let f as CGPoint: 63 | let t = to as! CGPoint 64 | let x = abs(t.x - f.x) 65 | let y = abs(t.y - f.y) 66 | referenceChangedLength = max(Double(x), Double(y)) 67 | 68 | case let f as CGRect: 69 | let t = to as! CGRect 70 | let xChange = abs(t.minX - f.minX) 71 | let yChange = abs(t.minY - f.minY) 72 | let wChange = abs(t.width - f.width) 73 | let hChange = abs(t.height - f.height) 74 | let originC = hypot(xChange, yChange) 75 | let sizeC = hypot(wChange, hChange) 76 | referenceChangedLength = max(Double(originC), Double(sizeC)) 77 | 78 | case let f as UIColor: 79 | let t = to as! UIColor 80 | let fromInfo = f.colorInfo() 81 | let toInfo = t.colorInfo() 82 | let hueChange = abs(toInfo.hue - fromInfo.hue) 83 | let brightnessChange = abs(toInfo.brightness - fromInfo.brightness) 84 | let saturationChange = abs(toInfo.saturation - fromInfo.saturation) 85 | let alphaChange = abs(toInfo.alpha - fromInfo.alpha) 86 | let oneC = hypot(hueChange, saturationChange) * 1000.0 87 | let twoC = hypot(brightnessChange, alphaChange) * 1000.0 88 | referenceChangedLength = max(Double(oneC), Double(twoC)) 89 | externalData = (fromInfo,toInfo) 90 | 91 | default: 92 | referenceChangedLength = 1000.0 93 | 94 | } 95 | } 96 | 97 | fileprivate func updateFrame() { 98 | if referenceChangedLength <= 0.0 { 99 | behavior?.cancel() 100 | return 101 | } 102 | var currentTime = CACurrentMediaTime() - beginTime 103 | currentTime = max(0.0, currentTime) 104 | let offset = gravityOffset(currentTime) 105 | var progress = offset / referenceChangedLength 106 | if progress >= 1.0 { 107 | if boundary { 108 | progress = 1.0 109 | behavior?.cancel() 110 | } 111 | } 112 | 113 | let value = from.interpolate(progress, to: to, externalData: externalData) 114 | render(value) 115 | } 116 | 117 | fileprivate func gravityOffset(_ t: CFTimeInterval) -> Double { 118 | return t * t * 1000.0 * magnitude; 119 | } 120 | 121 | //MARK: UIDynamicItem protocol 122 | var center: CGPoint = CGPoint.zero { 123 | didSet { 124 | updateFrame() 125 | } 126 | } 127 | 128 | var transform: CGAffineTransform = CGAffineTransform.identity 129 | var bounds: CGRect { 130 | get { 131 | return CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0) 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Sources/GravityConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol GravityConfigurable: BasicChainable { 12 | func gravity(_ magnitude: Double) -> Self 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Interpolatable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | 11 | public protocol Interpolatable: Vectorial { 12 | func interpolate(_ progress: Double, to: Self, externalData: Any?) -> Self 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Physical.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol Physical: Interpolatable {} 12 | 13 | extension Physical { 14 | public func fall(to: Self,magnitude: Double = 1.0, render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 15 | let item = DynamicItemGravity(from: self, to: to, render: render) 16 | let push = item.pushBehavior(.down) 17 | item.behavior = push 18 | item.magnitude = magnitude 19 | item.completion = completion 20 | push.commitToBasic() 21 | } 22 | 23 | public func snap(to: Self, damping: CGFloat = 0.5,render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 24 | let item = DynamicItem(from: self, to: to, render: render) 25 | let toP = CGPoint.init(x: 0, y: CGFloat(item.referenceChangeLength)) 26 | let snap = item.snapBehavior(toP, damping: damping) 27 | item.behavior = snap 28 | item.completion = completion 29 | snap.commit() 30 | } 31 | 32 | public func attachment(to: Self,damping: CGFloat = 0.5, frequency: CGFloat = 0.5,render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 33 | let item = DynamicItem(from: self, to: to,render: render) 34 | let toP = CGPoint.init(x: 0, y: CGFloat(item.referenceChangeLength)) 35 | let attachment = item.attachmentBehavior(toP, length: 0.0, damping: damping, frequency: frequency) 36 | item.behavior = attachment 37 | item.completion = completion 38 | attachment.commit() 39 | } 40 | 41 | public func pushed(to: Self,render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 42 | let item = DynamicItem(from: self,to: to,render: render) 43 | let direction = CGVector(dx: item.toR.one - item.fromR.one, dy: item.toR.two - item.fromR.two) 44 | let push = item.pushBehavior(direction, mode: .instantaneous, magnitude: 1.0) 45 | item.behavior = push 46 | item.boundaryLimit = true 47 | item.completion = completion 48 | push.commit() 49 | } 50 | 51 | public func animate(to: Self, duration: CFTimeInterval = 0.25, delay: CFTimeInterval = 0.0, type: TimingFunctionType = .default, autoreverses: Bool = false, repeatCount: Int = 0, render: @escaping (Self) -> Void, completion: ((Bool) -> Void)? = nil) { 52 | let basicItem = DynamicItemBasic(from: self, to: to, render: render) 53 | let push = basicItem.pushBehavior(.down) 54 | basicItem.behavior = push 55 | basicItem.duration = duration 56 | basicItem.timingFunction = type.easing() 57 | basicItem.completion = completion 58 | basicItem.delay = delay 59 | basicItem.autoreverses = autoreverses 60 | push.commitToBasic() 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /Sources/SnapConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol SnapConfigurable: BasicChainable { 12 | func snap(_ damping: CGFloat) -> Self 13 | } 14 | -------------------------------------------------------------------------------- /Sources/StepControllable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | 11 | public protocol StepControllable { 12 | //remove all remaining from excute sequence 13 | func cancelAllRemaining() 14 | //will add more methods to control animation steps 15 | } -------------------------------------------------------------------------------- /Sources/TimingFunction.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | import Foundation 9 | 10 | /// A set of preset bezier curves. 11 | public enum TimingFunctionType { 12 | /// Equivalent to `kCAMediaTimingFunctionDefault`. 13 | case `default` 14 | 15 | /// Equivalent to `kCAMediaTimingFunctionEaseIn`. 16 | case easeIn 17 | 18 | /// Equivalent to `kCAMediaTimingFunctionEaseOut`. 19 | case easeOut 20 | 21 | /// Equivalent to `kCAMediaTimingFunctionEaseInEaseOut`. 22 | case easeInEaseOut 23 | 24 | /// No easing. 25 | case linear 26 | 27 | /// Inspired by the default curve in Google Material Design. 28 | case swiftOut 29 | /// 30 | case backEaseIn 31 | /// 32 | case backEaseOut 33 | /// 34 | case backEaseInOut 35 | /// 36 | case bounceOut 37 | /// 38 | case sine 39 | /// 40 | case circ 41 | /// 42 | case exponentialIn 43 | /// 44 | case exponentialOut 45 | /// 46 | case elasticIn 47 | /// 48 | case bounceReverse 49 | /// 50 | case elasticOut 51 | /// custom 52 | case custom(Double, Double, Double, Double) 53 | 54 | 55 | func easing() -> TimingSolvable { 56 | switch self { 57 | case .default: 58 | return UnitBezier(p1x: 0.25, p1y: 0.1, p2x: 0.25, p2y: 1.0) 59 | case .easeIn: 60 | return UnitBezier(p1x: 0.42, p1y: 0.0, p2x: 1.0, p2y: 1.0) 61 | case .easeOut: 62 | return UnitBezier(p1x: 0.0, p1y: 0.0, p2x: 0.58, p2y: 1.0) 63 | case .easeInEaseOut: 64 | return UnitBezier(p1x: 0.42, p1y: 0.0, p2x: 0.58, p2y: 1.0) 65 | case .linear: 66 | return UnitBezier(p1x: 0.0, p1y: 0.0, p2x: 1.0, p2y: 1.0) 67 | case .swiftOut: 68 | return UnitBezier(p1x: 0.4, p1y: 0.0, p2x: 0.2, p2y: 1.0) 69 | case .backEaseIn: 70 | return EasingContainer(easing: { (t: Double) in 71 | return t * t * t - t * sin(t * .pi) 72 | }) 73 | case .backEaseOut: 74 | return EasingContainer(easing: { (t: Double) in 75 | let f = (1 - t); 76 | return 1 - (f * f * f - f * sin(f * .pi)); 77 | }) 78 | case .backEaseInOut: 79 | return EasingContainer(easing: { (t: Double) in 80 | if(t < 0.5) { 81 | let f = 2 * t; 82 | return 0.5 * (f * f * f - f * sin(f * .pi)); 83 | } else { 84 | let f = (1.0 - (2.0 * t - 1.0)); 85 | let cubic = f * f * f 86 | return 0.5 * (1.0 - (cubic - f * sin(f * .pi))) + 0.5; 87 | } 88 | }) 89 | case .bounceOut: 90 | return EasingContainer(easing: { (t: Double) in 91 | if(t < 4/11.0){ 92 | return (121 * t * t)/16.0; 93 | } else if(t < 8/11.0){ 94 | return (363/40.0 * t * t) - (99/10.0 * t) + 17/5.0; 95 | }else if(t < 9/10.0){ 96 | return (4356/361.0 * t * t) - (35442/1805.0 * t) + 16061/1805.0; 97 | }else{ 98 | return (54/5.0 * t * t) - (513/25.0 * t) + 268/25.0; 99 | } 100 | }) 101 | case .sine: 102 | return EasingContainer(easing: { (t: Double) in 103 | return 1 - cos( t * .pi / 2.0) 104 | }) 105 | case .circ: 106 | return EasingContainer(easing: { (t: Double) in 107 | return 1 - sqrt( 1.0 - t * t ) 108 | }) 109 | case .exponentialIn: 110 | return EasingContainer(easing: { (t: Double) in 111 | return (t == 0.0) ? t : pow(2, 10 * (t - 1)) 112 | }) 113 | case .exponentialOut: 114 | return EasingContainer(easing: { (t: Double) in 115 | return (t == 1.0) ? t : 1 - pow(2, -10 * t) 116 | }) 117 | case .elasticIn: 118 | return EasingContainer(easing: { (t: Double) in 119 | return sin(13.0 * (.pi / 2.0) * t) * pow(2, 10 * (t - 1)) 120 | }) 121 | case .elasticOut: 122 | return EasingContainer(easing: { (t: Double) in 123 | return sin(-13.0 * (.pi / 2.0) * (t + 1)) * pow(2, -10 * t) + 1.0; 124 | }) 125 | case .bounceReverse: 126 | return EasingContainer(easing: { (t: Double) in 127 | var bounce: Double = 4.0 128 | var pow2 = 0.0 129 | 130 | repeat { 131 | bounce = bounce - 1.0 132 | pow2 = pow(2, bounce) 133 | } while (t < (pow2 - 1.0 ) / 11.0) 134 | 135 | return 1 / pow( 4, 3 - bounce ) - 7.5625 * pow( ( pow2 * 3 - 2 ) / 22 - t, 2 ); 136 | }) 137 | case .custom(let p1x,let p1y,let p2x,let p2y): 138 | return UnitBezier(p1x: p1x, p1y: p1y, p2x: p2x, p2y: p2y) 139 | } 140 | } 141 | } 142 | 143 | class EasingContainer: TimingSolvable { 144 | let easing: (Double) -> Double 145 | 146 | init(easing: @escaping (Double) -> Double) { 147 | self.easing = easing 148 | } 149 | 150 | // 151 | func solveOn(_ time: Double, epslion: Double) -> Double { 152 | return self.easing(time) 153 | } 154 | } 155 | 156 | 157 | -------------------------------------------------------------------------------- /Sources/TimingSolvable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimingSolvable.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/28/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol TimingSolvable { 12 | func solveOn(_ time: Double, epslion: Double) -> Double 13 | } 14 | -------------------------------------------------------------------------------- /Sources/TimingType.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | 11 | protocol TimingType { 12 | var duration: CFTimeInterval { get set } 13 | var delay: CFTimeInterval { get set } 14 | var timingFunction: TimingSolvable { get set } 15 | var autoreverses: Bool { get set } 16 | var repeatCount: Int { get set } 17 | var speed: Double { get set } 18 | var timeOffset: CFTimeInterval { get set } 19 | } -------------------------------------------------------------------------------- /Sources/UIDynamicBehavior+Commit.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal extension UIDynamicBehavior { 12 | 13 | func commit() { 14 | AnimatorCoordinator.shared.addBehavior(self) 15 | } 16 | 17 | func cancel() { 18 | self.dynamicAnimator?.removeBehavior(self) 19 | } 20 | 21 | func commitToBasic() { 22 | AnimatorCoordinator.shared.addBasicBehavior(self) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/UnitBezier.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | import CoreGraphics 11 | 12 | public typealias Scalar = Double 13 | /// A bezier curve, often used to calculate timing functions. 14 | public struct UnitBezier { 15 | 16 | /// The horizontal component of the first control point. 17 | public var p1x: Scalar 18 | 19 | /// The vertical component of the first control point. 20 | public var p1y: Scalar 21 | 22 | /// The horizontal component of the second control point. 23 | public var p2x: Scalar 24 | 25 | /// The vertical component of the second control point. 26 | public var p2y: Scalar 27 | 28 | /// Creates a new `UnitBezier` instance. 29 | public init(p1x: Scalar, p1y: Scalar, p2x: Scalar, p2y: Scalar) { 30 | self.p1x = p1x 31 | self.p1y = p1y 32 | self.p2x = p2x 33 | self.p2y = p2y 34 | } 35 | 36 | /// Calculates the resulting `y` for given `x`. 37 | /// 38 | /// - parameter x: The value to solve for. 39 | /// - parameter epsilon: The required precision of the result (where `x * epsilon` is the maximum time segment to be evaluated). 40 | /// - returns: The solved `y` value. 41 | public func solve(_ x: Scalar, epsilon: Scalar) -> Scalar { 42 | return UnitBezierSolver(bezier: self).solve(x, eps: epsilon) 43 | } 44 | } 45 | 46 | extension UnitBezier: Equatable { } 47 | 48 | extension UnitBezier: TimingSolvable { 49 | func solveOn(_ time: Double, epslion: Double) -> Double { 50 | return self.solve(time, epsilon: epslion) 51 | } 52 | } 53 | 54 | /// Equatable. 55 | public func ==(lhs: UnitBezier, rhs: UnitBezier) -> Bool { 56 | return lhs.p1x == rhs.p1x 57 | && lhs.p1y == rhs.p1y 58 | && lhs.p2x == rhs.p2x 59 | && lhs.p2y == rhs.p2y 60 | } 61 | 62 | 63 | // Ported to Swift from WebCore: 64 | // http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h 65 | 66 | /* 67 | * Copyright (C) 2008 Apple Inc. All Rights Reserved. 68 | * 69 | * Redistribution and use in source and binary forms, with or without 70 | * modification, are permitted provided that the following conditions 71 | * are met: 72 | * 1. Redistributions of source code must retain the above copyright 73 | * notice, this list of conditions and the following disclaimer. 74 | * 2. Redistributions in binary form must reproduce the above copyright 75 | * notice, this list of conditions and the following disclaimer in the 76 | * documentation and/or other materials provided with the distribution. 77 | * 78 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 79 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 81 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 82 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 83 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 84 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 85 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 86 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 87 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 88 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 89 | */ 90 | 91 | 92 | private struct UnitBezierSolver { 93 | 94 | fileprivate let ax: Scalar 95 | fileprivate let bx: Scalar 96 | fileprivate let cx: Scalar 97 | 98 | fileprivate let ay: Scalar 99 | fileprivate let by: Scalar 100 | fileprivate let cy: Scalar 101 | 102 | init(bezier: UnitBezier) { 103 | self.init(p1x: bezier.p1x, p1y: bezier.p1y, p2x: bezier.p2x, p2y: bezier.p2y) 104 | } 105 | 106 | init(p1x: Scalar, p1y: Scalar, p2x: Scalar, p2y: Scalar) { 107 | 108 | // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). 109 | cx = 3.0 * p1x 110 | bx = 3.0 * (p2x - p1x) - cx 111 | ax = 1.0 - cx - bx 112 | 113 | cy = 3.0 * p1y 114 | by = 3.0 * (p2y - p1y) - cy 115 | ay = 1.0 - cy - by 116 | } 117 | 118 | func sampleCurveX(_ t: Scalar) -> Scalar { 119 | return ((ax * t + bx) * t + cx) * t 120 | } 121 | 122 | func sampleCurveY(_ t: Scalar) -> Scalar { 123 | return ((ay * t + by) * t + cy) * t 124 | } 125 | 126 | func sampleCurveDerivativeX(_ t: Scalar) -> Scalar { 127 | return (3.0 * ax * t + 2.0 * bx) * t + cx 128 | } 129 | 130 | func solveCurveX(_ x: Scalar, eps: Scalar) -> Scalar { 131 | var t0: Scalar = 0.0 132 | var t1: Scalar = 0.0 133 | var t2: Scalar = 0.0 134 | var x2: Scalar = 0.0 135 | var d2: Scalar = 0.0 136 | 137 | // First try a few iterations of Newton's method -- normally very fast. 138 | t2 = x 139 | for _ in 0..<8 { 140 | x2 = sampleCurveX(t2) - x 141 | if abs(x2) < eps { 142 | return t2 143 | } 144 | d2 = sampleCurveDerivativeX(t2) 145 | if abs(d2) < 1e-6 { 146 | break 147 | } 148 | t2 = t2 - x2 / d2 149 | } 150 | 151 | // Fall back to the bisection method for reliability. 152 | t0 = 0.0 153 | t1 = 1.0 154 | t2 = x 155 | 156 | if t2 < t0 { 157 | return t0 158 | } 159 | if t2 > t1 { 160 | return t1 161 | } 162 | 163 | while t0 < t1 { 164 | x2 = sampleCurveX(t2) 165 | if abs(x2-x) < eps { 166 | return t2 167 | } 168 | if x > x2 { 169 | t0 = t2 170 | } else { 171 | t1 = t2 172 | } 173 | t2 = (t1-t0) * 0.5 + t0 174 | } 175 | 176 | return t2 177 | } 178 | 179 | func solve(_ x: Scalar, eps: Scalar) -> Scalar { 180 | return sampleCurveY(solveCurveX(x, eps: eps)) 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Sources/Vectorial.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public class Vector4 { 12 | var one: Double = 0 13 | var two: Double = 0 14 | var three: Double = 0 15 | var four: Double = 0 16 | 17 | convenience init(_ fourLatitude: (Double,Double,Double,Double)) { 18 | self.init() 19 | self.one = fourLatitude.0 20 | self.two = fourLatitude.1 21 | self.three = fourLatitude.2 22 | self.four = fourLatitude.3 23 | } 24 | } 25 | 26 | public protocol Vectorial { 27 | func convert(_ p: Vector4) -> Self 28 | func reverse() -> Vector4 29 | } 30 | -------------------------------------------------------------------------------- /Stellar.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "Stellar" 3 | s.version = "0.67" 4 | s.summary = "An Awesome Physical animation library base on UIDynamic. " 5 | s.description = "A fantastic Physical animation library for swift(Not Just Spring !!!), it is base on UIDynamic and extension to it, friendly APIs make you use it or custom your own animation very easily!" 6 | s.homepage = "https://github.com/AugustRush/Stellar" 7 | s.license = "LICENSE" 8 | s.author = { "AugustRush" => "819373341@qq.com" } 9 | s.source = { :git => "https://github.com/AugustRush/Stellar.git", :tag => "0.67" } 10 | s.source_files = "Sources", "Sources/*.swift" 11 | s.platform = :ios, "8.0" 12 | s.frameworks = "UIKit", "Foundation" 13 | end 14 | -------------------------------------------------------------------------------- /StellarDemo/Stellar/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>en</string> 7 | <key>CFBundleExecutable</key> 8 | <string>$(EXECUTABLE_NAME)</string> 9 | <key>CFBundleIdentifier</key> 10 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 11 | <key>CFBundleInfoDictionaryVersion</key> 12 | <string>6.0</string> 13 | <key>CFBundleName</key> 14 | <string>$(PRODUCT_NAME)</string> 15 | <key>CFBundlePackageType</key> 16 | <string>FMWK</string> 17 | <key>CFBundleShortVersionString</key> 18 | <string>1.0</string> 19 | <key>CFBundleSignature</key> 20 | <string>????</string> 21 | <key>CFBundleVersion</key> 22 | <string>$(CURRENT_PROJECT_VERSION)</string> 23 | <key>NSPrincipalClass</key> 24 | <string></string> 25 | </dict> 26 | </plist> 27 | -------------------------------------------------------------------------------- /StellarDemo/Stellar/Stellar.h: -------------------------------------------------------------------------------- 1 | // 2 | // Stellar.h 3 | // Stellar 4 | // 5 | // Created by AugustRush on 6/6/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | #import <UIKit/UIKit.h> 10 | 11 | //! Project version number for Stellar. 12 | FOUNDATION_EXPORT double StellarVersionNumber; 13 | 14 | //! Project version string for Stellar. 15 | FOUNDATION_EXPORT const unsigned char StellarVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import <Stellar/PublicHeader.h> 18 | 19 | 20 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Workspace 3 | version = "1.0"> 4 | <FileRef 5 | location = "self:"> 6 | </FileRef> 7 | </Workspace> 8 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo.xcodeproj/project.xcworkspace/xcuserdata/August.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/StellarDemo/StellarDemo.xcodeproj/project.xcworkspace/xcuserdata/August.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /StellarDemo/StellarDemo.xcodeproj/xcshareddata/xcschemes/Stellar.xcscheme: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Scheme 3 | LastUpgradeVersion = "1010" 4 | version = "1.3"> 5 | <BuildAction 6 | parallelizeBuildables = "YES" 7 | buildImplicitDependencies = "YES"> 8 | <BuildActionEntries> 9 | <BuildActionEntry 10 | buildForTesting = "YES" 11 | buildForRunning = "YES" 12 | buildForProfiling = "YES" 13 | buildForArchiving = "YES" 14 | buildForAnalyzing = "YES"> 15 | <BuildableReference 16 | BuildableIdentifier = "primary" 17 | BlueprintIdentifier = "97019FD51D054ECD00FD6644" 18 | BuildableName = "Stellar.framework" 19 | BlueprintName = "Stellar" 20 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 21 | </BuildableReference> 22 | </BuildActionEntry> 23 | </BuildActionEntries> 24 | </BuildAction> 25 | <TestAction 26 | buildConfiguration = "Debug" 27 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 28 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 29 | shouldUseLaunchSchemeArgsEnv = "YES"> 30 | <Testables> 31 | </Testables> 32 | <AdditionalOptions> 33 | </AdditionalOptions> 34 | </TestAction> 35 | <LaunchAction 36 | buildConfiguration = "Debug" 37 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 38 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 39 | launchStyle = "0" 40 | useCustomWorkingDirectory = "NO" 41 | ignoresPersistentStateOnLaunch = "NO" 42 | debugDocumentVersioning = "YES" 43 | debugServiceExtension = "internal" 44 | allowLocationSimulation = "YES"> 45 | <MacroExpansion> 46 | <BuildableReference 47 | BuildableIdentifier = "primary" 48 | BlueprintIdentifier = "97019FD51D054ECD00FD6644" 49 | BuildableName = "Stellar.framework" 50 | BlueprintName = "Stellar" 51 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 52 | </BuildableReference> 53 | </MacroExpansion> 54 | <AdditionalOptions> 55 | </AdditionalOptions> 56 | </LaunchAction> 57 | <ProfileAction 58 | buildConfiguration = "Release" 59 | shouldUseLaunchSchemeArgsEnv = "YES" 60 | savedToolIdentifier = "" 61 | useCustomWorkingDirectory = "NO" 62 | debugDocumentVersioning = "YES"> 63 | <MacroExpansion> 64 | <BuildableReference 65 | BuildableIdentifier = "primary" 66 | BlueprintIdentifier = "97019FD51D054ECD00FD6644" 67 | BuildableName = "Stellar.framework" 68 | BlueprintName = "Stellar" 69 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 70 | </BuildableReference> 71 | </MacroExpansion> 72 | </ProfileAction> 73 | <AnalyzeAction 74 | buildConfiguration = "Debug"> 75 | </AnalyzeAction> 76 | <ArchiveAction 77 | buildConfiguration = "Release" 78 | revealArchiveInOrganizer = "YES"> 79 | </ArchiveAction> 80 | </Scheme> 81 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo.xcodeproj/xcshareddata/xcschemes/StellarDemo.xcscheme: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Scheme 3 | LastUpgradeVersion = "1010" 4 | version = "1.3"> 5 | <BuildAction 6 | parallelizeBuildables = "YES" 7 | buildImplicitDependencies = "YES"> 8 | <BuildActionEntries> 9 | <BuildActionEntry 10 | buildForTesting = "YES" 11 | buildForRunning = "YES" 12 | buildForProfiling = "YES" 13 | buildForArchiving = "YES" 14 | buildForAnalyzing = "YES"> 15 | <BuildableReference 16 | BuildableIdentifier = "primary" 17 | BlueprintIdentifier = "97BE88BD1CDDDAD000240523" 18 | BuildableName = "StellarDemo.app" 19 | BlueprintName = "StellarDemo" 20 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 21 | </BuildableReference> 22 | </BuildActionEntry> 23 | </BuildActionEntries> 24 | </BuildAction> 25 | <TestAction 26 | buildConfiguration = "Debug" 27 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 28 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 29 | shouldUseLaunchSchemeArgsEnv = "YES"> 30 | <Testables> 31 | <TestableReference 32 | skipped = "NO"> 33 | <BuildableReference 34 | BuildableIdentifier = "primary" 35 | BlueprintIdentifier = "97BE88D11CDDDAD000240523" 36 | BuildableName = "StellarDemoTests.xctest" 37 | BlueprintName = "StellarDemoTests" 38 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 39 | </BuildableReference> 40 | </TestableReference> 41 | <TestableReference 42 | skipped = "NO"> 43 | <BuildableReference 44 | BuildableIdentifier = "primary" 45 | BlueprintIdentifier = "97BE88DC1CDDDAD000240523" 46 | BuildableName = "StellarDemoUITests.xctest" 47 | BlueprintName = "StellarDemoUITests" 48 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 49 | </BuildableReference> 50 | </TestableReference> 51 | <TestableReference 52 | skipped = "NO"> 53 | <BuildableReference 54 | BuildableIdentifier = "primary" 55 | BlueprintIdentifier = "97019FDE1D054ECD00FD6644" 56 | BuildableName = "StellarTests.xctest" 57 | BlueprintName = "StellarTests" 58 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 59 | </BuildableReference> 60 | </TestableReference> 61 | </Testables> 62 | <MacroExpansion> 63 | <BuildableReference 64 | BuildableIdentifier = "primary" 65 | BlueprintIdentifier = "97BE88BD1CDDDAD000240523" 66 | BuildableName = "StellarDemo.app" 67 | BlueprintName = "StellarDemo" 68 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 69 | </BuildableReference> 70 | </MacroExpansion> 71 | <AdditionalOptions> 72 | </AdditionalOptions> 73 | </TestAction> 74 | <LaunchAction 75 | buildConfiguration = "Debug" 76 | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 77 | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 78 | launchStyle = "0" 79 | useCustomWorkingDirectory = "NO" 80 | ignoresPersistentStateOnLaunch = "NO" 81 | debugDocumentVersioning = "YES" 82 | debugServiceExtension = "internal" 83 | allowLocationSimulation = "YES"> 84 | <BuildableProductRunnable 85 | runnableDebuggingMode = "0"> 86 | <BuildableReference 87 | BuildableIdentifier = "primary" 88 | BlueprintIdentifier = "97BE88BD1CDDDAD000240523" 89 | BuildableName = "StellarDemo.app" 90 | BlueprintName = "StellarDemo" 91 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 92 | </BuildableReference> 93 | </BuildableProductRunnable> 94 | <AdditionalOptions> 95 | </AdditionalOptions> 96 | </LaunchAction> 97 | <ProfileAction 98 | buildConfiguration = "Release" 99 | shouldUseLaunchSchemeArgsEnv = "YES" 100 | savedToolIdentifier = "" 101 | useCustomWorkingDirectory = "NO" 102 | debugDocumentVersioning = "YES"> 103 | <BuildableProductRunnable 104 | runnableDebuggingMode = "0"> 105 | <BuildableReference 106 | BuildableIdentifier = "primary" 107 | BlueprintIdentifier = "97BE88BD1CDDDAD000240523" 108 | BuildableName = "StellarDemo.app" 109 | BlueprintName = "StellarDemo" 110 | ReferencedContainer = "container:StellarDemo.xcodeproj"> 111 | </BuildableReference> 112 | </BuildableProductRunnable> 113 | </ProfileAction> 114 | <AnalyzeAction 115 | buildConfiguration = "Debug"> 116 | </AnalyzeAction> 117 | <ArchiveAction 118 | buildConfiguration = "Release" 119 | revealArchiveInOrganizer = "YES"> 120 | </ArchiveAction> 121 | </Scheme> 122 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo.xcodeproj/xcuserdata/August.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <Bucket 3 | type = "1" 4 | version = "2.0"> 5 | <Breakpoints> 6 | <BreakpointProxy 7 | BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint"> 8 | <BreakpointContent 9 | shouldBeEnabled = "Yes" 10 | ignoreCount = "0" 11 | continueAfterRunningActions = "No" 12 | symbolName = "" 13 | moduleName = ""> 14 | <Locations> 15 | </Locations> 16 | </BreakpointContent> 17 | </BreakpointProxy> 18 | <BreakpointProxy 19 | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> 20 | <BreakpointContent 21 | shouldBeEnabled = "Yes" 22 | ignoreCount = "0" 23 | continueAfterRunningActions = "No" 24 | filePath = "../Sources/UIView+AnimateBehavior.swift" 25 | timestampString = "516163535.849267" 26 | startingColumnNumber = "9223372036854775807" 27 | endingColumnNumber = "9223372036854775807" 28 | startingLineNumber = "236" 29 | endingLineNumber = "236" 30 | landmarkName = "createDynamicBehavior(withStyle:subType:step:)" 31 | landmarkType = "7"> 32 | </BreakpointContent> 33 | </BreakpointProxy> 34 | <BreakpointProxy 35 | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> 36 | <BreakpointContent 37 | shouldBeEnabled = "Yes" 38 | ignoreCount = "0" 39 | continueAfterRunningActions = "No" 40 | filePath = "../Sources/UIView+AnimateBehavior.swift" 41 | timestampString = "516163535.849267" 42 | startingColumnNumber = "9223372036854775807" 43 | endingColumnNumber = "9223372036854775807" 44 | startingLineNumber = "166" 45 | endingLineNumber = "166" 46 | landmarkName = "createDynamicBehavior(withStyle:subType:step:)" 47 | landmarkType = "7"> 48 | </BreakpointContent> 49 | </BreakpointProxy> 50 | <BreakpointProxy 51 | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> 52 | <BreakpointContent 53 | shouldBeEnabled = "Yes" 54 | ignoreCount = "0" 55 | continueAfterRunningActions = "No" 56 | filePath = "../Sources/UIView+AnimateBehavior.swift" 57 | timestampString = "516163535.849267" 58 | startingColumnNumber = "9223372036854775807" 59 | endingColumnNumber = "9223372036854775807" 60 | startingLineNumber = "239" 61 | endingLineNumber = "239" 62 | landmarkName = "createDynamicBehavior(withStyle:subType:step:)" 63 | landmarkType = "7"> 64 | </BreakpointContent> 65 | </BreakpointProxy> 66 | <BreakpointProxy 67 | BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> 68 | <BreakpointContent 69 | shouldBeEnabled = "Yes" 70 | ignoreCount = "0" 71 | continueAfterRunningActions = "No" 72 | filePath = "../Sources/DynamicItem.swift" 73 | timestampString = "516081338.922453" 74 | startingColumnNumber = "9223372036854775807" 75 | endingColumnNumber = "9223372036854775807" 76 | startingLineNumber = "27" 77 | endingLineNumber = "27" 78 | landmarkName = "init(from:to:render:)" 79 | landmarkType = "7"> 80 | </BreakpointContent> 81 | </BreakpointProxy> 82 | </Breakpoints> 83 | </Bucket> 84 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo.xcodeproj/xcuserdata/August.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>SchemeUserState</key> 6 | <dict> 7 | <key>StellarDemo.xcscheme_^#shared#^_</key> 8 | <dict> 9 | <key>orderHint</key> 10 | <integer>0</integer> 11 | </dict> 12 | </dict> 13 | <key>SuppressBuildableAutocreation</key> 14 | <dict> 15 | <key>97019FD51D054ECD00FD6644</key> 16 | <dict> 17 | <key>primary</key> 18 | <true/> 19 | </dict> 20 | <key>97019FDE1D054ECD00FD6644</key> 21 | <dict> 22 | <key>primary</key> 23 | <true/> 24 | </dict> 25 | <key>97BE88BD1CDDDAD000240523</key> 26 | <dict> 27 | <key>primary</key> 28 | <true/> 29 | </dict> 30 | <key>97BE88D11CDDDAD000240523</key> 31 | <dict> 32 | <key>primary</key> 33 | <true/> 34 | </dict> 35 | <key>97BE88DC1CDDDAD000240523</key> 36 | <dict> 37 | <key>primary</key> 38 | <true/> 39 | </dict> 40 | </dict> 41 | </dict> 42 | </plist> 43 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 5/7/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Ball.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Ball.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 5/26/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @IBDesignable 12 | class Ball: UIView { 13 | 14 | @IBInspectable var cornerRadius: CGFloat = 15 { 15 | didSet { 16 | self.layer.cornerRadius = cornerRadius 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM"> 3 | <dependencies> 4 | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/> 5 | </dependencies> 6 | <scenes> 7 | <!--View Controller--> 8 | <scene sceneID="EHf-IW-A2E"> 9 | <objects> 10 | <viewController id="01J-lp-oVM" sceneMemberID="viewController"> 11 | <layoutGuides> 12 | <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/> 13 | <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/> 14 | </layoutGuides> 15 | <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> 16 | <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> 17 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 18 | <animations/> 19 | <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> 20 | </view> 21 | </viewController> 22 | <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> 23 | </objects> 24 | <point key="canvasLocation" x="53" y="375"/> 25 | </scene> 26 | </scenes> 27 | </document> 28 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example1ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GravityViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 5/25/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example1ViewController: UIViewController { 12 | 13 | 14 | @IBOutlet var balls: [UIView]! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | self.view.backgroundColor = UIColor(red: 0.97,green: 0.97,blue: 0.97,alpha: 1.0) 20 | 21 | self.title = "Basic" 22 | } 23 | 24 | override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 25 | super.touchesBegan(touches, with: event) 26 | 27 | let point = touches.first?.location(in: self.view) 28 | 29 | for (index,ball) in balls.enumerated() { 30 | let center = ball.center 31 | let interval = 0.1 * Double(index) 32 | 33 | center.animate(to: point!, 34 | duration: 0.8, 35 | delay: interval, 36 | type: .swiftOut, 37 | render: { (p) in 38 | 39 | ball.center = p 40 | 41 | }, completion: { (f) in 42 | 43 | ball.backgroundColor?.animate(to: UIColor.red, 44 | duration: 1.4, 45 | type: .swiftOut, 46 | autoreverses: true, 47 | render: { (c) in 48 | 49 | ball.backgroundColor = c 50 | }) 51 | 52 | ball.center.snap(to: center, damping: 0.1 53 | , render: { (p) in 54 | ball.center = p 55 | }) 56 | }) 57 | } 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example2ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 5/7/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example2ViewController: UIViewController { 12 | 13 | 14 | @IBOutlet var balls: [UIView]! 15 | 16 | var attachment: UIAttachmentBehavior! 17 | var animator = UIDynamicAnimator() 18 | 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | self.view.backgroundColor = UIColor(red: 0.98,green: 0.98,blue: 0.98,alpha: 1.0) 24 | 25 | self.title = "Chainable" 26 | } 27 | 28 | override func didReceiveMemoryWarning() { 29 | super.didReceiveMemoryWarning() 30 | } 31 | 32 | 33 | override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 34 | super.touchesBegan(touches, with: event) 35 | 36 | for (index, ball) in balls.enumerated() { 37 | let move = CGFloat(-20 + index * 20) 38 | let opacity = Float(1 - 0.2 * CGFloat(index)) 39 | let size = CGSize(width: 20 - CGFloat(index) * 5, height: 20 - CGFloat(index) * 5) 40 | ball.shadowOpacity(opacity).shadowOffset(size).shadowRadius(5).moveX(-move).moveY(-move).shadowColor(UIColor.gray).duration(2).easing(.bounceOut) 41 | .then().moveY(move).moveX(move).shadowOpacity(0).shadowOffset(CGSize.zero).shadowColor(UIColor.clear).duration(1).easing(.bounceOut) 42 | .completion({ 43 | print("all completion") 44 | }).animate() 45 | } 46 | 47 | 48 | } 49 | 50 | override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 51 | super.touchesMoved(touches, with: event) 52 | 53 | } 54 | 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example3ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example3ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 5/30/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example3ViewController: UIViewController { 12 | 13 | @IBOutlet var leftLines: [Ball]! 14 | @IBOutlet var rightLines: [Ball]! 15 | 16 | override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 17 | super.touchesEnded(touches, with: event) 18 | 19 | for (index,line) in leftLines.enumerated() { 20 | let delay = Double(index) * 0.2 21 | line.moveX(200).duration(2).delay(delay) 22 | .then().moveX(-200).makeColor(UIColor.green).easing(.linear).repeatCount(100).reverses().duration(2).animate() 23 | line.makeWidth(80).delay(delay).duration(1).reverses().easing(.linear).repeatCount(100).animate() 24 | } 25 | 26 | for (index,line) in rightLines.enumerated() { 27 | let delay = Double(index) * 0.2 28 | line.moveX(-200).duration(2).delay(delay) 29 | .then().moveX(200).makeColor(UIColor.purple).easing(.linear).repeatCount(100).reverses().duration(2).animate() 30 | line.makeWidth(80).delay(delay).duration(1).reverses().easing(.linear).repeatCount(100).animate() 31 | } 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example4ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example4ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/1/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example4ViewController: UIViewController { 12 | 13 | 14 | @IBOutlet weak var animateView: Ball! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | } 20 | 21 | override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 22 | super.touchesEnded(touches, with: event) 23 | 24 | animateView.makeSize(CGSize(width: 50, height: 150)).snap(0.3).completion({ 25 | print("First step") 26 | }) 27 | .then().moveX(-100).moveY(-50).anchorPoint(CGPoint(x: 1, y: 1)).duration(1).completion({ 28 | print("Second step!") 29 | }) 30 | .then().rotate(.pi).attachment(0.3, frequency: 0.8).completion({ 31 | print("Third step!") 32 | }) 33 | .then().moveY(500).gravity().completion({ 34 | print("last step, all completion") 35 | }) 36 | .animate() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example5ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example5ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/1/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example5ViewController: UIViewController { 12 | 13 | @IBOutlet weak var cyanView: UIView! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | } 19 | 20 | override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 21 | super.touchesBegan(touches, with: event) 22 | 23 | let rotation: CGFloat = .pi * 20.0 24 | cyanView.makeSize(CGSize(width: 100, height: 30)).snap() 25 | .then().moveY(-100).snap(1) 26 | .then().rotate(rotation) 27 | .duration(2) 28 | .easing(.swiftOut) 29 | .makeHeight(100) 30 | .cornerRadius(50) 31 | .then().moveY(100).gravity() 32 | .then().moveY(-80) 33 | .then().moveY(80).gravity() 34 | .then().moveY(-40) 35 | .then().moveY(40).gravity() 36 | .then().makeWidth(120) 37 | .makeHeight(30) 38 | .cornerRadius(15) 39 | .easing(.swiftOut) 40 | .makeColor(UIColor.brown) 41 | .animate() 42 | 43 | } 44 | 45 | override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 46 | super.touchesEnded(touches, with: event) 47 | //will cancel all remaining animations 48 | // cyanView.cancelAllRemaining() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example6ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example6ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/1/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example6ViewController: UIViewController { 12 | 13 | //should be have more easily APIs to do 14 | 15 | @IBOutlet var views: [UIView]! 16 | var centerItems: [DynamicItemBasic<CGPoint>] = Array() 17 | var colorItems: [DynamicItemBasic<UIColor>] = Array() 18 | 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | for view in views { 24 | let basic = DynamicItemBasic(from: view.center,to: CGPoint(x: 160, y: 200), render: { (p) in 25 | view.center = p 26 | }) 27 | basic.duration = 1.0 28 | basic.speed = 0.0 29 | basic.timingFunction = TimingFunctionType.swiftOut.easing() 30 | centerItems.append(basic) 31 | 32 | let color = view.backgroundColor! 33 | let basic1 = DynamicItemBasic(from: color, to: UIColor.red, render: { (c) in 34 | view.backgroundColor = c 35 | }) 36 | basic1.duration = 1.0 37 | basic1.speed = 0.0 38 | basic1.timingFunction = TimingFunctionType.swiftOut.easing() 39 | colorItems.append(basic1) 40 | 41 | } 42 | 43 | } 44 | 45 | @IBAction func sliderValueChanged(_ sender: UISlider) { 46 | let offset = Double(sender.value) 47 | for item in centerItems { 48 | item.timeOffset = offset 49 | } 50 | 51 | for item in colorItems { 52 | item.timeOffset = offset 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example7ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example7ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/8/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example7ViewController: UIViewController { 12 | 13 | @IBOutlet weak var button: UIButton! 14 | 15 | @IBAction func loadFromJSON(_ sender: AnyObject) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Example8ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Example8ViewController.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/29/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Example8ViewController: UIViewController { 12 | @IBOutlet weak var animateView: Ball! 13 | 14 | @IBAction func segment1ValueChanged(_ sender: UISegmentedControl) { 15 | 16 | let index = sender.selectedSegmentIndex; 17 | 18 | switch index { 19 | case 0: 20 | animateView.moveX(200).duration(1.0).easing(.default).reverses().animate() 21 | case 1: 22 | animateView.moveX(200).duration(1.0).easing(.easeIn).reverses().animate() 23 | case 2: 24 | animateView.moveX(200).duration(1.0).easing(.easeOut).reverses().animate() 25 | case 3: 26 | animateView.moveX(200).duration(1.0).easing(.easeInEaseOut).reverses().animate() 27 | default: 28 | print("") 29 | } 30 | 31 | } 32 | @IBAction func segment2ValueChanged(_ sender: UISegmentedControl) { 33 | animateView.frame = CGRect(x: 20,y: 120,width: 40,height: 40) 34 | let index = sender.selectedSegmentIndex; 35 | 36 | switch index { 37 | case 0: 38 | animateView.moveX(200).duration(1.0).easing(.linear).reverses().animate() 39 | case 1: 40 | animateView.moveX(200).duration(1.0).easing(.swiftOut).reverses().animate() 41 | case 2: 42 | animateView.moveX(200).duration(1.0).easing(.backEaseIn).reverses().animate() 43 | case 3: 44 | animateView.moveX(200).duration(1.0).easing(.backEaseOut).reverses().animate() 45 | default: 46 | print("") 47 | } 48 | 49 | } 50 | @IBAction func segment3ValueChanged(_ sender: UISegmentedControl) { 51 | animateView.frame = CGRect(x: 20,y: 120,width: 40,height: 40) 52 | let index = sender.selectedSegmentIndex; 53 | 54 | switch index { 55 | case 0: 56 | animateView.moveX(200).duration(1.0).easing(.backEaseInOut).reverses().animate() 57 | case 1: 58 | animateView.moveX(200).duration(1.0).easing(.bounceOut).reverses().animate() 59 | case 2: 60 | animateView.moveX(200).duration(1.0).easing(.sine).reverses().animate() 61 | case 3: 62 | animateView.moveX(200).duration(1.0).easing(.circ).reverses().animate() 63 | default: 64 | print("") 65 | } 66 | 67 | } 68 | 69 | @IBAction func segment4ValueChanged(_ sender: UISegmentedControl) { 70 | animateView.frame = CGRect(x: 20,y: 120,width: 40,height: 40) 71 | let index = sender.selectedSegmentIndex; 72 | 73 | switch index { 74 | case 0: 75 | animateView.moveX(200).duration(1.0).easing(.exponentialIn).reverses().animate() 76 | case 1: 77 | animateView.moveX(200).duration(1.0).easing(.exponentialOut).reverses().animate() 78 | case 2: 79 | animateView.moveX(200).duration(1.0).easing(.elasticIn).reverses().animate() 80 | case 3: 81 | animateView.moveX(200).duration(1.0).easing(.elasticOut).reverses().animate() 82 | default: 83 | print("") 84 | } 85 | 86 | } 87 | 88 | @IBAction func segment5ValueChanged(_ sender: UISegmentedControl) { 89 | animateView.frame = CGRect(x: 20,y: 120,width: 40,height: 40) 90 | let index = sender.selectedSegmentIndex; 91 | 92 | switch index { 93 | case 0: 94 | animateView.moveX(200).duration(1.0).easing(.bounceReverse).reverses().animate() 95 | case 1: 96 | 100.0.animate(to: 200, duration: 1.0, delay: 0.0, type: .swiftOut, autoreverses: false, repeatCount: 0, render: { (d) in 97 | print("current value is \(d)") 98 | }, completion: nil) 99 | case 2: 100 | 100.0.attachment(to: 200, render: { (d) in 101 | print("current value is \(d)") 102 | }) 103 | 104 | case 3: 105 | fallthrough 106 | default: 107 | print("") 108 | } 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>en</string> 7 | <key>CFBundleExecutable</key> 8 | <string>$(EXECUTABLE_NAME)</string> 9 | <key>CFBundleIdentifier</key> 10 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 11 | <key>CFBundleInfoDictionaryVersion</key> 12 | <string>6.0</string> 13 | <key>CFBundleName</key> 14 | <string>$(PRODUCT_NAME)</string> 15 | <key>CFBundlePackageType</key> 16 | <string>APPL</string> 17 | <key>CFBundleShortVersionString</key> 18 | <string>1.0</string> 19 | <key>CFBundleSignature</key> 20 | <string>????</string> 21 | <key>CFBundleVersion</key> 22 | <string>1</string> 23 | <key>LSRequiresIPhoneOS</key> 24 | <true/> 25 | <key>UILaunchStoryboardName</key> 26 | <string>LaunchScreen</string> 27 | <key>UIMainStoryboardFile</key> 28 | <string>Main</string> 29 | <key>UIRequiredDeviceCapabilities</key> 30 | <array> 31 | <string>armv7</string> 32 | </array> 33 | <key>UISupportedInterfaceOrientations</key> 34 | <array> 35 | <string>UIInterfaceOrientationPortrait</string> 36 | <string>UIInterfaceOrientationLandscapeLeft</string> 37 | <string>UIInterfaceOrientationLandscapeRight</string> 38 | </array> 39 | <key>UISupportedInterfaceOrientations~ipad</key> 40 | <array> 41 | <string>UIInterfaceOrientationPortrait</string> 42 | <string>UIInterfaceOrientationPortraitUpsideDown</string> 43 | <string>UIInterfaceOrientationLandscapeLeft</string> 44 | <string>UIInterfaceOrientationLandscapeRight</string> 45 | </array> 46 | </dict> 47 | </plist> 48 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/LiquidView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LiquidView.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/3/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LiquidView: UIView { 12 | 13 | override class func layerClass() -> AnyClass { 14 | return CAShapeLayer.self 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | import PlaygroundSupport 4 | 5 | let container = UIView(frame: CGRect.init(x: 0, y: 0, width: 600, height: 600)) 6 | 7 | container.backgroundColor = UIColor(red: 0.97,green: 0.97,blue: 0.97,alpha: 1.0) 8 | 9 | //var balls: [Ball] = Array() 10 | //for i in 0...5 { 11 | // let ball = Ball(frame: CGRectMake(10,10 + 60 * CGFloat(i),50,50)) 12 | // ball.backgroundColor = UIColor.redColor() 13 | // container.addSubview(ball) 14 | // balls.append(ball) 15 | // 16 | // ball.moveX(200).duration(2) 17 | // .delay(Double(i) * 0.1).repeatCount(1) 18 | // .autoreverses() 19 | // .animate() 20 | // 21 | // ball.makeWidth(200).duration(2).autoreverses().animate() 22 | //} 23 | 24 | let ball = Ball(frame: CGRect.init(x: 100, y: 100, width: 25, height: 25)) 25 | ball.backgroundColor = UIColor.cyan 26 | container.addSubview(ball) 27 | 28 | //ball.moveX(100).moveY(100).duration(2.5) 29 | // .then().makeColor(UIColor.purple) 30 | // .animate() 31 | 32 | ball.moveX(100).moveY(100).delay(0.5).duration(2) 33 | .then().makeWidth(160).duration(2).anchorPoint(CGPoint.init(x: 0, y: 0.5)) 34 | .then().rotate(1.5).snap(0.2) 35 | .then().moveY(500).gravity(100) 36 | .animate() 37 | 38 | //let rotation: CGFloat = CGFloat(M_PI) * 20.0 39 | //ball.makeSize(CGSizeMake(100, 30)).gravity() 40 | // .then().moveY(-100).snap(1) 41 | // .then().rotate(rotation).duration(2).easing(.SwiftOut).makeHeight(100).cornerRadius(50) 42 | // .then().moveY(100).gravity() 43 | // .then().moveY(-80) 44 | // .then().moveY(80).gravity() 45 | // .then().moveY(-40) 46 | // .then().moveY(40).gravity() 47 | // .then().makeWidth(120).makeHeight(30).cornerRadius(15).easing(.SwiftOut).makeColor(UIColor.brownColor()) 48 | // .animate() 49 | 50 | /** 51 | * @brief Easing Curve 52 | * 53 | * @param 200 move foreard 54 | */ 55 | //ball.moveX(200).easing(.BounceOut).delay(0.5).duration(1).animate() 56 | //ball.moveX(200).easing(.ElasticIn).delay(0.5).duration(1).animate() 57 | //ball.moveX(200).easing(.ElasticOut).delay(0.5).duration(1).animate() 58 | //ball.moveX(200).easing(.Sine).delay(0.5).duration(1).animate() 59 | //ball.moveX(200).easing(.Circ).delay(0.5).duration(1).animate() 60 | //ball.moveX(200).easing(.ExponentialOut).delay(0.5).duration(1).animate() 61 | //ball.moveX(200).easing(.ExponentialIn).delay(0.5).duration(1).animate() 62 | 63 | ball.moveX(200).easing(.bounceReverse).delay(0.5).duration(3).autoreverses().animate() 64 | 65 | PlaygroundPage.current.liveView = container 66 | 67 | //basic curve 68 | 69 | 100.0.animate(to: 300, duration: 1, delay: 0.0, type: .custom(0.0, 1.39, 1.0, -0.55), autoreverses: false, repeatCount: 0, render: { (d) in 70 | let y = d 71 | }, completion: nil) 72 | 73 | 74 | 100.0.pushed(to: 300, render: { (d) in 75 | let y = d 76 | }, completion: nil) 77 | 78 | 79 | 100.0.snap(to: 150, damping: 0.8, render: { (d) in 80 | let t = d 81 | }, completion: nil) 82 | 83 | 100.0.attachment(to: 200, damping: 0.3, frequency: 1, render: { (d) in 84 | let y = d 85 | }, completion: nil) 86 | 87 | //100.0.fallTo(200, magnitude: 0.6, render: { (d) in 88 | // let y = d 89 | // }, completion: nil) 90 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Ball.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Ball.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 5/26/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @IBDesignable 12 | public class Ball: UIView { 13 | 14 | @IBInspectable var cornerRadius: CGFloat = 15 { 15 | didSet { 16 | self.layer.cornerRadius = cornerRadius 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/AnimationContext.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal class AnimationContext: NSObject, UIDynamicAnimatorDelegate, AnimationSequenceDelegate { 12 | fileprivate weak var object: DriveAnimateBehaviors! 13 | fileprivate var mutipleSequences = [AnimationSequence]() 14 | 15 | //MARK: init method 16 | init(object: DriveAnimateBehaviors) { 17 | self.object = object 18 | } 19 | 20 | //MARK: public methods 21 | func addAnimationType(_ type: AnimationType) { 22 | let step = lastStep() 23 | step.types.append(type) 24 | } 25 | 26 | func changeDuration(_ d: CFTimeInterval) { 27 | let step = lastStep() 28 | step.duration = d 29 | } 30 | 31 | func changeDelay(_ d: CFTimeInterval) { 32 | let step = lastStep() 33 | step.delay = d 34 | } 35 | 36 | func changeAutoreverses(_ a: Bool) { 37 | let step = lastStep() 38 | step.autoreverses = a 39 | } 40 | 41 | func changeRepeatCount(_ count: Int) { 42 | let step = lastStep() 43 | step.repeatCount = count 44 | } 45 | 46 | func changeCompletion(_ c: @escaping () -> Void) { 47 | let step = lastStep() 48 | step.completion = c 49 | } 50 | 51 | func changeEasing(_ e: TimingFunctionType) { 52 | let step = lastStep() 53 | step.timing = e 54 | } 55 | 56 | func changeMainType(_ type: AnimationStyle) { 57 | let step = lastStep() 58 | let lastAnimationType = step.types.last 59 | guard let _ = lastAnimationType else { 60 | print("You should defined animaton first!") 61 | return 62 | } 63 | 64 | lastAnimationType!.mainType = type 65 | } 66 | 67 | func makeNextStep() { 68 | let step = AnimationStep() 69 | lastSequence().addStep(step) 70 | } 71 | 72 | @discardableResult 73 | func makeNextSequence() -> AnimationSequence { 74 | let sequence = AnimationSequence(object: self.object) 75 | sequence.delegate = self 76 | mutipleSequences.append(sequence) 77 | 78 | return sequence 79 | } 80 | 81 | func commit() { 82 | //start all sequence 83 | for sequence in mutipleSequences { 84 | sequence.start() 85 | } 86 | //make a temple sequence for next step 87 | makeNextSequence() 88 | } 89 | 90 | func removeAllRemaining() { 91 | for sequence in mutipleSequences { 92 | sequence.removeAllSteps() 93 | } 94 | mutipleSequences.removeAll() 95 | } 96 | 97 | 98 | //MARK: private methods 99 | 100 | fileprivate func lastSequence() -> AnimationSequence { 101 | var sequence = mutipleSequences.last 102 | if sequence == nil { 103 | sequence = makeNextSequence() 104 | } 105 | 106 | return sequence! 107 | } 108 | 109 | fileprivate func lastStep() -> AnimationStep { 110 | let sequence = lastSequence() 111 | var step = sequence.last() 112 | if step == nil { 113 | step = AnimationStep() 114 | sequence.addStep(step!) 115 | } 116 | return step! 117 | } 118 | 119 | //MARK: AnimationSequenceDelegate methods 120 | 121 | func animationSequenceDidComplete(_ sequence: AnimationSequence) { 122 | let index = mutipleSequences.index(of: sequence) 123 | if index != nil { 124 | mutipleSequences.remove(at: index!) 125 | } 126 | } 127 | } 128 | 129 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/AnimationSequence.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | protocol AnimationSequenceDelegate: class { 12 | func animationSequenceDidComplete(_ sequence: AnimationSequence); 13 | } 14 | 15 | internal class AnimationSequence: NSObject, UIDynamicAnimatorDelegate { 16 | var steps: [AnimationStep] = Array() 17 | weak var view: DriveAnimateBehaviors! 18 | weak var delegate: AnimationSequenceDelegate? 19 | var isRuning = false 20 | lazy var animator: UIDynamicAnimator = { 21 | let animator = UIDynamicAnimator() 22 | animator.delegate = self 23 | return animator 24 | }() 25 | 26 | //MARK: init method 27 | 28 | init(object: DriveAnimateBehaviors) { 29 | self.view = object 30 | } 31 | 32 | //MARK: internal method 33 | func addStep(_ step: AnimationStep) { 34 | steps.append(step) 35 | } 36 | 37 | func last() -> AnimationStep? { 38 | return steps.last 39 | } 40 | 41 | func start() { 42 | if !isRuning { 43 | isRuning = true 44 | excuteFirstStepIfExist() 45 | } 46 | } 47 | 48 | func removeAllSteps() { 49 | steps.removeAll() 50 | } 51 | 52 | fileprivate func excuteFirstStepIfExist() { 53 | 54 | if self.view == nil { 55 | return 56 | } 57 | 58 | let step = steps.first 59 | 60 | if let step = step { 61 | //if step has no animation types it must be the last temple step 62 | if step.types.count == 0 { 63 | steps.removeFirst() 64 | popFirstStepIfExsist() 65 | return 66 | } 67 | 68 | for type in step.types { 69 | let behavior = view.behavior(forType: type, step: step) 70 | animator.addBehavior(behavior) 71 | } 72 | 73 | } else { 74 | popFirstStepIfExsist() 75 | } 76 | } 77 | 78 | fileprivate func popFirstStepIfExsist() { 79 | if !steps.isEmpty { 80 | let step = steps.first! 81 | //excute completion 82 | step.completion?() 83 | steps.removeFirst() 84 | } else { 85 | // all steps has completion 86 | self.delegate?.animationSequenceDidComplete(self) 87 | } 88 | } 89 | 90 | //MARK: UIDynamicAnimatorDelegate methods 91 | func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) { 92 | animator.removeAllBehaviors() 93 | popFirstStepIfExsist() 94 | excuteFirstStepIfExist() 95 | } 96 | 97 | func dynamicAnimatorWillResume(_ animator: UIDynamicAnimator) { 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/AnimationStep.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal class AnimationStep { 12 | var types = [AnimationType]() 13 | var duration: CFTimeInterval = 0.25 14 | var timing: TimingFunctionType = .default 15 | var delay: CFTimeInterval = 0.0 16 | var autoreverses: Bool = false 17 | var repeatCount: Int = 0 18 | var completion: (() -> Void)? 19 | } 20 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/AnimationType.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | enum AnimationSubType { 12 | case moveX(CGFloat) 13 | case moveY(CGFloat) 14 | case moveXY(CGFloat,CGFloat)//Layer 15 | case moveTo(CGPoint) 16 | case color(UIColor) 17 | case alpha(CGFloat) 18 | case opacity(Float)//Layer 19 | case rotateX(CGFloat) 20 | case rotateY(CGFloat) 21 | case rotate(CGFloat) 22 | case rotateXY(CGFloat) 23 | case width(CGFloat) 24 | case height(CGFloat) 25 | case size(CGSize) 26 | case frame(CGRect) 27 | case bounds(CGRect) 28 | case scaleX(CGFloat) 29 | case scaleY(CGFloat) 30 | case scaleXY(CGFloat,CGFloat) 31 | case cornerRadius(CGFloat) 32 | case borderWidth(CGFloat) 33 | case shadowRadius(CGFloat) 34 | case zPosition(CGFloat) 35 | case anchorPoint(CGPoint) 36 | case anchorPointZ(CGFloat) 37 | case shadowOffset(CGSize) 38 | case shadowColor(UIColor) 39 | case shadowOpacity(Float) 40 | case tintColor(UIColor) 41 | // UILabel,UITextView... 42 | // case TextColor(UIColor) 43 | } 44 | 45 | //temp record for animation type 46 | internal class AnimationType { 47 | var mainType: AnimationStyle 48 | var subType: AnimationSubType 49 | 50 | init (type: AnimationStyle, subType: AnimationSubType) { 51 | self.mainType = type 52 | self.subType = subType 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/AnimatorCoordinator.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal class AnimatorCoordinator: NSObject, UIDynamicAnimatorDelegate { 12 | static let shared = AnimatorCoordinator() 13 | fileprivate var activedAnimators: [UIDynamicAnimator] = Array() 14 | fileprivate var basicAnimator = UIDynamicAnimator() 15 | 16 | //MARK: public methods 17 | func addBasicBehavior(_ b: UIDynamicBehavior) { 18 | basicAnimator.addBehavior(b) 19 | } 20 | func addBehavior(_ b: UIDynamicBehavior) { 21 | addBehaviors([b]) 22 | } 23 | 24 | func addBehaviors(_ behaviors: [UIDynamicBehavior]) { 25 | 26 | let animator = activedAnimators.last 27 | for b in behaviors { 28 | 29 | if let exsist = animator { 30 | switch b { 31 | case b as UIGravityBehavior: 32 | fallthrough 33 | case b as UICollisionBehavior: 34 | createAnimator(b) 35 | default: 36 | exsist.addBehavior(b) 37 | } 38 | 39 | } else { 40 | createAnimator(b) 41 | } 42 | } 43 | } 44 | 45 | fileprivate func createAnimator(_ behavior: UIDynamicBehavior) { 46 | let animator = UIDynamicAnimator() 47 | animator.delegate = self 48 | animator.addBehavior(behavior) 49 | activedAnimators.append(animator) 50 | } 51 | 52 | 53 | //MARK: UIDynamicAnimatorDelegate methods 54 | 55 | func dynamicAnimatorDidPause(_ animator: UIDynamicAnimator) { 56 | let index = activedAnimators.index(of: animator) 57 | activedAnimators.remove(at: index!) 58 | } 59 | 60 | func dynamicAnimatorWillResume(_ animator: UIDynamicAnimator) { 61 | // 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/AttachmentConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol AttachmentConfigurable: BasicChainable { 12 | func attachment(_ damping: CGFloat, frequency: CGFloat) -> AttachmentConfigurable 13 | } 14 | 15 | public protocol AttachmentConfigurable1: BasicChainable1 { 16 | func attachment(_ damping: CGFloat, frequency: CGFloat) -> AttachmentConfigurable1 17 | } 18 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/BasicChainable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol BasicChainable: Chainable { 12 | func moveX(_ increment: CGFloat) -> UIView 13 | func moveY(_ increment: CGFloat) -> UIView 14 | func moveTo(_ point: CGPoint) -> UIView 15 | func makeColor(_ color: UIColor) -> UIView 16 | func makeAlpha(_ alpha: CGFloat) -> UIView 17 | func rotate(_ z: CGFloat) -> UIView 18 | func rotateX(_ x: CGFloat) -> UIView 19 | func rotateY(_ y: CGFloat) -> UIView 20 | func rotateXY(_ xy: CGFloat) -> UIView 21 | func makeWidth(_ width: CGFloat) -> UIView 22 | func makeHeight(_ height: CGFloat) -> UIView 23 | func makeSize(_ size: CGSize) -> UIView 24 | func makeFrame(_ frame: CGRect) -> UIView 25 | func makeBounds(_ bounds: CGRect) -> UIView 26 | func scaleX(_ x: CGFloat) -> UIView 27 | func scaleY(_ y: CGFloat) -> UIView 28 | func scaleXY(_ x: CGFloat, _ y: CGFloat) -> UIView 29 | func cornerRadius(_ radius: CGFloat) -> UIView 30 | func borderWidth(_ width: CGFloat) -> UIView 31 | func shadowRadius(_ radius: CGFloat) -> UIView 32 | func zPosition(_ position: CGFloat) -> UIView 33 | func anchorPoint(_ point: CGPoint) -> UIView 34 | func anchorPointZ(_ z: CGFloat) -> UIView 35 | func shadowOffset(_ offset: CGSize) -> UIView 36 | func shadowColor(_ color: UIColor) -> UIView 37 | func shadowOpacity(_ opacity: Float) -> UIView 38 | func makeTintColor(_ color: UIColor) -> UIView 39 | func completion(_ c: @escaping () -> Void) -> UIView 40 | } 41 | 42 | //CALayer 43 | public protocol BasicChainable1: Chainable1 { 44 | func moveTo(_ point: CGPoint) -> CALayer 45 | func makeColor(_ color: UIColor) -> CALayer 46 | func makeOpacity(_ opacity: Float) -> CALayer 47 | func rotate(_ z: CGFloat) -> CALayer 48 | func rotateX(_ x: CGFloat) -> CALayer 49 | func rotateY(_ y: CGFloat) -> CALayer 50 | func rotateXY(_ xy: CGFloat) -> CALayer 51 | func makeWidth(_ width: CGFloat) -> CALayer 52 | func makeHeight(_ height: CGFloat) -> CALayer 53 | func makeSize(_ size: CGSize) -> CALayer 54 | func makeFrame(_ frame: CGRect) -> CALayer 55 | func makeBounds(_ bounds: CGRect) -> CALayer 56 | func scaleX(_ x: CGFloat) -> CALayer 57 | func scaleY(_ y: CGFloat) -> CALayer 58 | func scaleXY(_ x: CGFloat, _ y: CGFloat) -> CALayer 59 | func cornerRadius(_ radius: CGFloat) -> CALayer 60 | func borderWidth(_ width: CGFloat) -> CALayer 61 | func shadowRadius(_ radius: CGFloat) -> CALayer 62 | func zPosition(_ position: CGFloat) -> CALayer 63 | func anchorPoint(_ point: CGPoint) -> CALayer 64 | func anchorPointZ(_ z: CGFloat) -> CALayer 65 | func shadowOffset(_ offset: CGSize) -> CALayer 66 | func shadowColor(_ color: UIColor) -> CALayer 67 | func shadowOpacity(_ opacity: Float) -> CALayer 68 | func completion(_ c: @escaping () -> Void) -> CALayer 69 | } 70 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/BasicConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol BasicConfigurable: BasicChainable { 12 | func duration(_ d: CFTimeInterval) -> BasicConfigurable 13 | func easing(_ type: TimingFunctionType) -> BasicConfigurable 14 | func delay(_ d: CFTimeInterval) -> BasicConfigurable 15 | func reverses() -> BasicConfigurable 16 | func repeatCount(_ count: Int) -> BasicConfigurable 17 | } 18 | 19 | //CALayer 20 | public protocol BasicConfigurable1: BasicChainable1 { 21 | func duration(_ d: CFTimeInterval) -> BasicConfigurable1 22 | func easing(_ type: TimingFunctionType) -> BasicConfigurable1 23 | func delay(_ d: CFTimeInterval) -> BasicConfigurable1 24 | func reverses() -> BasicConfigurable1 25 | func repeatCount(_ count: Int) -> BasicConfigurable1 26 | } 27 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/CALayer+DriveAnimationBehaviors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+DriveAnimationBehaviors.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/21/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/Chainable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol Chainable { 12 | //Chainable methods 13 | func then() -> UIView 14 | func animate() -> Void 15 | } 16 | 17 | //CALayer 18 | public protocol Chainable1 { 19 | //Chainable methods 20 | func then() -> CALayer 21 | func animate() -> Void 22 | } 23 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/DriveAnimateBehaviors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DriveAnimateBehaviors.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/21/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol DriveAnimateBehaviors: class { 12 | func behavior(forType type: AnimationType, step: AnimationStep) -> UIDynamicBehavior 13 | } 14 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/DynamicItem+Behavior.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | enum PhysicalDirection { 12 | case left 13 | case right 14 | case up 15 | case down 16 | case Angle(CGFloat) 17 | case vector(CGFloat,CGFloat) 18 | 19 | func angle() -> CGFloat { 20 | switch self { 21 | case .Angle(let a): 22 | return a 23 | case .vector(let x, let y): 24 | return atan2(y, x) 25 | case .left: 26 | return atan2(0, -1) 27 | case .right: 28 | return atan2(0, 1) 29 | case .up: 30 | return atan2(-1, 0) 31 | case .down: 32 | return atan2(1, 0) 33 | } 34 | } 35 | } 36 | 37 | extension UIDynamicItem { 38 | 39 | //gravity 40 | func gravityBehavior(_ magnitude: CGFloat = 1.0, direction: PhysicalDirection = .down) -> UIGravityBehavior { 41 | let gravity = UIGravityBehavior() 42 | switch direction { 43 | case .Angle(let a): 44 | gravity.setAngle(a, magnitude: magnitude) 45 | case .left: 46 | gravity.gravityDirection = CGVector(dx: -1, dy: 0) 47 | case .right: 48 | gravity.gravityDirection = CGVector(dx: 1, dy: 0) 49 | case .up: 50 | gravity.gravityDirection = CGVector(dx: 0, dy: -1) 51 | case .down: 52 | gravity.gravityDirection = CGVector(dx: 0, dy: 1) 53 | case .vector(let x, let y): 54 | gravity.gravityDirection = CGVector(dx: x, dy: y) 55 | } 56 | gravity.magnitude = magnitude 57 | gravity.addItem(self) 58 | return gravity 59 | } 60 | 61 | //snap 62 | func snapBehavior(_ toPoint: CGPoint, damping: CGFloat = 0.5) -> UISnapBehavior { 63 | let snap = UISnapBehavior(item: self,snapTo: toPoint) 64 | snap.damping = damping 65 | return snap 66 | } 67 | 68 | //attachment 69 | func attachmentBehavior(_ toAnchor: CGPoint, length: CGFloat = 0.0, damping: CGFloat = 0.5, frequency: CGFloat = 1.0) -> UIAttachmentBehavior { 70 | let attachment = UIAttachmentBehavior(item: self,attachedToAnchor: toAnchor) 71 | attachment.length = length 72 | attachment.damping = damping 73 | attachment.frequency = frequency 74 | return attachment 75 | } 76 | 77 | func attachmentBehavior(_ toItem: UIDynamicItem, damping: CGFloat = 0.5, frequency: CGFloat = 1.0) -> UIAttachmentBehavior { 78 | let attachment = UIAttachmentBehavior(item: self,attachedTo: toItem) 79 | attachment.damping = damping 80 | attachment.frequency = frequency 81 | return attachment 82 | } 83 | 84 | func attachmentBehavior(_ toItem: UIDynamicItem, damping: CGFloat = 0.5, frequency: CGFloat = 1.0, length: CGFloat = 0.0) -> UIAttachmentBehavior { 85 | let attachment = UIAttachmentBehavior(item: self,attachedTo: toItem) 86 | attachment.damping = damping 87 | attachment.length = length 88 | attachment.frequency = frequency 89 | return attachment 90 | } 91 | 92 | //push 93 | func pushBehavior(_ direction: CGVector, mode:UIPushBehaviorMode = .instantaneous, magnitude: CGFloat = 1.0) -> UIPushBehavior { 94 | let push = UIPushBehavior(items: [self], mode: mode) 95 | push.pushDirection = direction 96 | push.magnitude = magnitude 97 | return push 98 | } 99 | 100 | func pushBehavior(_ direction: PhysicalDirection, mode:UIPushBehaviorMode = .instantaneous, magnitude: CGFloat = 1.0) -> UIPushBehavior { 101 | let push = UIPushBehavior(items: [self], mode: mode) 102 | switch direction { 103 | case .Angle(let a): 104 | push.setAngle(a, magnitude: magnitude) 105 | case .left: 106 | push.pushDirection = CGVector(dx: -1, dy: 0) 107 | case .right: 108 | push.pushDirection = CGVector(dx: 1, dy: 0) 109 | case .up: 110 | push.pushDirection = CGVector(dx: 0, dy: -1) 111 | case .down: 112 | push.pushDirection = CGVector(dx: 0, dy: 1) 113 | case .vector(let x, let y): 114 | push.pushDirection = CGVector(dx: x, dy: y) 115 | } 116 | 117 | push.magnitude = magnitude 118 | return push 119 | } 120 | 121 | 122 | func pushBehavior(_ angle: CGFloat, mode:UIPushBehaviorMode = .instantaneous, magnitude: CGFloat = 1.0) -> UIPushBehavior { 123 | let push = UIPushBehavior(items: [self], mode: mode) 124 | push.angle = angle 125 | push.magnitude = magnitude 126 | return push 127 | } 128 | 129 | //collision 130 | func collisionBehavior(_ mode: UICollisionBehaviorMode = .boundaries) -> UICollisionBehavior { 131 | let collision = UICollisionBehavior() 132 | collision.collisionMode = mode 133 | collision.addItem(self) 134 | return collision 135 | } 136 | 137 | func collisionBehavior(_ mode: UICollisionBehaviorMode = .boundaries, path: UIBezierPath) -> UICollisionBehavior { 138 | let collision = UICollisionBehavior() 139 | collision.collisionMode = mode 140 | let identifier = String(describing: Unmanaged.passUnretained(self).toOpaque()) 141 | collision.addBoundary(withIdentifier: identifier as NSCopying, for: path) 142 | collision.addItem(self) 143 | return collision 144 | } 145 | 146 | func collisionBehavior(_ mode: UICollisionBehaviorMode = .boundaries, fromPoint: CGPoint, toPoint: CGPoint) -> UICollisionBehavior { 147 | let collision = UICollisionBehavior() 148 | collision.collisionMode = mode 149 | let identifier = String(describing: Unmanaged.passUnretained(self).toOpaque()) 150 | collision.addBoundary(withIdentifier: identifier as NSCopying, from: fromPoint, to: toPoint) 151 | collision.addItem(self) 152 | return collision 153 | } 154 | 155 | //itemBehavior 156 | func itemBehavior(_ elasticity: CGFloat = 0.5, friction: CGFloat = 0.5, density: CGFloat = 1, resistance: CGFloat = 0, angularResistance: CGFloat = 0, allowsRotation: Bool = true) -> UIDynamicItemBehavior { 157 | let behavior = UIDynamicItemBehavior() 158 | behavior.addItem(self) 159 | behavior.elasticity = elasticity 160 | behavior.friction = friction 161 | behavior.density = density 162 | behavior.resistance = resistance 163 | behavior.angularResistance = angularResistance 164 | behavior.allowsRotation = allowsRotation 165 | return behavior 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/DynamicItem.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | //for 4 latitude 12 | final class DynamicItem<T: Vectorial>: NSObject, UIDynamicItem { 13 | 14 | var from: T 15 | var to: T 16 | var render: (T) -> Void 17 | var complete = false 18 | var boundaryLimit = false 19 | var completion: (() -> Void)? 20 | internal var fromR: Vector4 21 | internal var toR: Vector4 22 | weak var behavior: UIDynamicBehavior! 23 | fileprivate var change: (x: Double,y: Double,z: Double,w: Double) 24 | var referenceChangeLength: Double 25 | 26 | init(from: T, to: T, render: @escaping (T) -> Void) { 27 | self.from = from 28 | self.to = to 29 | self.render = render 30 | // 31 | self.fromR = from.reverse() 32 | self.toR = to.reverse() 33 | // 34 | let x = toR.one - fromR.one 35 | let y = toR.two - fromR.two 36 | let z = toR.three - fromR.three 37 | let w = toR.four - fromR.four 38 | self.change = (x,y,z,w) 39 | // 40 | let originChange = sqrt(x*x + y*y) 41 | let sizeChange = sqrt(z*z + w*w) 42 | self.referenceChangeLength = max(originChange, sizeChange) 43 | } 44 | 45 | deinit { 46 | self.render(to) 47 | complete = true 48 | completion?() 49 | } 50 | 51 | //MARK: Update frame 52 | 53 | func updateFrame() { 54 | let yChange = fabs(Double(center.y)) 55 | let progress = yChange / referenceChangeLength 56 | let curX = fromR.one + change.x * progress; 57 | let curY = fromR.two + change.y * progress; 58 | let curZ = fromR.three + change.z * progress; 59 | let curW = fromR.four + change.w * progress; 60 | 61 | let rect = Vector4.init((curX,curY,curZ,curW)) 62 | var curV = from.convert(rect) 63 | if progress >= 1.0 { 64 | if boundaryLimit { 65 | curV = to 66 | behavior.cancel() 67 | complete = true 68 | } 69 | } 70 | self.render(curV) 71 | } 72 | 73 | //MARK: UIDynamicItem protocol 74 | var center: CGPoint = CGPoint.zero { 75 | didSet { 76 | updateFrame() 77 | } 78 | } 79 | 80 | var transform: CGAffineTransform = CGAffineTransform.identity 81 | var bounds: CGRect { 82 | get { 83 | return CGRect(x: -50.0, y: -50.0, width: 100.0, height: 100.0) 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/DynamicItemBasic.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | private let SolveForReverse = { (f: CFTimeInterval) in 12 | return 1 - f 13 | } 14 | 15 | private let SolveForUnReverse = { (f: CFTimeInterval) in 16 | return f 17 | } 18 | 19 | final class DynamicItemBasic<T: Interpolatable>: NSObject, UIDynamicItem, TimingType { 20 | 21 | var duration: CFTimeInterval = 0.25 22 | var delay: CFTimeInterval = 0.0 23 | var timingFunction: TimingSolvable = TimingFunctionType.default.easing() 24 | var from: T 25 | var to: T 26 | var render: (T) -> Void 27 | var autoreverses = false 28 | var repeatCount = 0 29 | var completion: ((Bool) -> Void)? 30 | var speed: Double = 1.0 31 | var timeOffset: CFTimeInterval = 0.0 { 32 | didSet { 33 | updateFrame() 34 | } 35 | } 36 | 37 | weak var behavior: UIDynamicBehavior? 38 | //External data to store (performance) 39 | fileprivate var externalData: Any? 40 | fileprivate var complete = false 41 | fileprivate var isReversing = false 42 | fileprivate var solveProgress = SolveForUnReverse 43 | fileprivate lazy var beginTime: CFTimeInterval = { 44 | return CACurrentMediaTime() 45 | }() 46 | fileprivate lazy var epsilon: Double = { 47 | return 1.0 / (self.duration * 1000.0) 48 | }() 49 | 50 | //MARK: Life cycle methods 51 | init(from: T, to: T, render: @escaping (T) -> Void) { 52 | self.from = from 53 | self.to = to 54 | self.render = render 55 | 56 | if let fromColor = from as? UIColor { 57 | let fromInfo = fromColor.colorInfo() 58 | let toColor = to as! UIColor 59 | let toInfo = toColor.colorInfo() 60 | self.externalData = (fromInfo,toInfo) 61 | } 62 | } 63 | 64 | deinit { 65 | //do some thing 66 | } 67 | 68 | //MARK: update frame 69 | fileprivate func updateFrame() { 70 | let startTime = beginTime 71 | var currentTime = CACurrentMediaTime() - startTime - delay 72 | currentTime = max(0, currentTime) * speed + timeOffset 73 | var progress = currentTime / duration 74 | if progress >= 1.0 { 75 | isReversing = autoreverses ? !isReversing : false 76 | if repeatCount == 0 { 77 | if isReversing { 78 | progress = 0.0 79 | beginTime = CACurrentMediaTime() 80 | solveProgress = SolveForReverse 81 | } else { 82 | progress = 1.0 83 | behavior?.cancel() 84 | complete = true 85 | self.completion?(complete) 86 | } 87 | }else { 88 | if isReversing == false { 89 | repeatCount -= 1 90 | solveProgress = SolveForUnReverse 91 | } else { 92 | solveProgress = SolveForReverse 93 | } 94 | progress = 0.0 95 | beginTime = CACurrentMediaTime() 96 | } 97 | } 98 | let solveP = solveProgress(progress) 99 | let adjustProgress = timingFunction.solveOn(solveP, epslion: epsilon) 100 | let value = from.interpolate(adjustProgress, to: to, externalData: externalData) 101 | self.render(value) 102 | } 103 | 104 | //MARK: UIDynamicItem protocol 105 | var center: CGPoint = CGPoint.zero { 106 | didSet { 107 | updateFrame() 108 | } 109 | } 110 | 111 | var transform: CGAffineTransform = CGAffineTransform.identity 112 | var bounds: CGRect { 113 | get { 114 | return CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0) 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/DynamicItemGravity.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | class DynamicItemGravity<T: Interpolatable>: NSObject, UIDynamicItem { 12 | 13 | var from: T! 14 | var to: T! 15 | var magnitude = 1.0 16 | var render: (T) -> Void 17 | var completion: (() -> Void)? 18 | var boundary = true 19 | weak var behavior: UIDynamicBehavior? 20 | //private vars 21 | fileprivate var referenceChangedLength: Double = 0.0 22 | //External data to store (performance) 23 | fileprivate var externalData: Any? 24 | fileprivate lazy var beginTime = { 25 | return CACurrentMediaTime() 26 | }() 27 | 28 | //MARK: init method 29 | init(from: T, to: T, render: @escaping (T) -> Void) { 30 | self.from = from 31 | self.to = to 32 | self.render = render 33 | super.init() 34 | caculateReferenceChangedLength() 35 | } 36 | 37 | deinit { 38 | self.completion?() 39 | } 40 | 41 | //MARK: private methods 42 | fileprivate func caculateReferenceChangedLength() { 43 | switch from { 44 | case let f as CGFloat: 45 | let t = to as! CGFloat 46 | referenceChangedLength = Double(fabs(t - f)) 47 | 48 | case let f as Float: 49 | let t = to as! Float 50 | referenceChangedLength = Double(fabs(t - f)) 51 | 52 | case let f as Double: 53 | let t = to as! Double 54 | referenceChangedLength = fabs(t - f) 55 | 56 | case let f as CGSize: 57 | let t = to as! CGSize 58 | let w = fabs(t.width - f.width) 59 | let h = fabs(t.height - f.height) 60 | referenceChangedLength = max(Double(w), Double(h)) 61 | 62 | case let f as CGPoint: 63 | let t = to as! CGPoint 64 | let x = fabs(t.x - f.x) 65 | let y = fabs(t.y - f.y) 66 | referenceChangedLength = max(Double(x), Double(y)) 67 | 68 | case let f as CGRect: 69 | let t = to as! CGRect 70 | let xChange = fabs(t.minX - f.minX) 71 | let yChange = fabs(t.minY - f.minY) 72 | let wChange = fabs(t.width - f.width) 73 | let hChange = fabs(t.height - f.height) 74 | let originC = hypot(xChange, yChange) 75 | let sizeC = hypot(wChange, hChange) 76 | referenceChangedLength = max(Double(originC), Double(sizeC)) 77 | 78 | case let f as UIColor: 79 | let t = to as! UIColor 80 | let fromInfo = f.colorInfo() 81 | let toInfo = t.colorInfo() 82 | let hueChange = fabs(toInfo.hue - fromInfo.hue) 83 | let brightnessChange = fabs(toInfo.brightness - fromInfo.brightness) 84 | let saturationChange = fabs(toInfo.saturation - fromInfo.saturation) 85 | let alphaChange = fabs(toInfo.alpha - fromInfo.alpha) 86 | let oneC = hypot(hueChange, saturationChange) * 1000.0 87 | let twoC = hypot(brightnessChange, alphaChange) * 1000.0 88 | referenceChangedLength = max(Double(oneC), Double(twoC)) 89 | externalData = (fromInfo,toInfo) 90 | 91 | default: 92 | referenceChangedLength = 1000.0 93 | 94 | } 95 | } 96 | 97 | fileprivate func updateFrame() { 98 | if referenceChangedLength <= 0.0 { 99 | behavior?.cancel() 100 | return 101 | } 102 | var currentTime = CACurrentMediaTime() - beginTime 103 | currentTime = max(0.0, currentTime) 104 | let offset = gravityOffset(currentTime) 105 | var progress = offset / referenceChangedLength 106 | if progress >= 1.0 { 107 | if boundary { 108 | progress = 1.0 109 | behavior?.cancel() 110 | } 111 | } 112 | 113 | let value = from.interpolate(progress, to: to, externalData: externalData) 114 | render(value) 115 | } 116 | 117 | fileprivate func gravityOffset(_ t: CFTimeInterval) -> Double { 118 | return t * t * 1000.0 * magnitude; 119 | } 120 | 121 | //MARK: UIDynamicItem protocol 122 | var center: CGPoint = CGPoint.zero { 123 | didSet { 124 | updateFrame() 125 | } 126 | } 127 | 128 | var transform: CGAffineTransform = CGAffineTransform.identity 129 | var bounds: CGRect { 130 | get { 131 | return CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0) 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/GravityConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol GravityConfigurable: BasicChainable { 12 | func gravity(_ magnitude: Double) -> GravityConfigurable 13 | } 14 | 15 | public protocol GravityConfigurable1: BasicChainable1 { 16 | func gravity(_ magnitude: Double) -> GravityConfigurable1 17 | } 18 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/Interpolatable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | 11 | public protocol Interpolatable: Vectorial { 12 | func interpolate(_ progress: Double, to: Self, externalData: Any?) -> Self 13 | } 14 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/Physical.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol Physical: Interpolatable {} 12 | 13 | extension Physical { 14 | public func fall(to: Self,magnitude: Double = 1.0, render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 15 | let item = DynamicItemGravity(from: self, to: to, render: render) 16 | let push = item.pushBehavior(.down) 17 | item.behavior = push 18 | item.magnitude = magnitude 19 | item.completion = completion 20 | push.commitToBasic() 21 | } 22 | 23 | public func snap(to: Self, damping: CGFloat = 0.5,render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 24 | let item = DynamicItem(from: self, to: to, render: render) 25 | let toP = CGPoint.init(x: 0, y: CGFloat(item.referenceChangeLength)) 26 | let snap = item.snapBehavior(toP, damping: damping) 27 | item.behavior = snap 28 | item.completion = completion 29 | snap.commit() 30 | } 31 | 32 | public func attachment(to: Self,damping: CGFloat = 0.5, frequency: CGFloat = 0.5,render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 33 | let item = DynamicItem(from: self, to: to,render: render) 34 | let toP = CGPoint.init(x: 0, y: CGFloat(item.referenceChangeLength)) 35 | let attachment = item.attachmentBehavior(toP, length: 0.0, damping: damping, frequency: frequency) 36 | item.behavior = attachment 37 | item.completion = completion 38 | attachment.commit() 39 | } 40 | 41 | public func pushed(to: Self,render: @escaping (Self) -> Void, completion: (() -> Void)? = nil) { 42 | let item = DynamicItem(from: self,to: to,render: render) 43 | let direction = CGVector(dx: item.toR.one - item.fromR.one, dy: item.toR.two - item.fromR.two) 44 | let push = item.pushBehavior(direction, mode: .instantaneous, magnitude: 1.0) 45 | item.behavior = push 46 | item.boundaryLimit = true 47 | item.completion = completion 48 | push.commit() 49 | } 50 | 51 | public func animate(to: Self, duration: CFTimeInterval = 0.25, delay: CFTimeInterval = 0.0, type: TimingFunctionType = .default, autoreverses: Bool = false, repeatCount: Int = 0, render: @escaping (Self) -> Void, completion: ((Bool) -> Void)? = nil) { 52 | let basicItem = DynamicItemBasic(from: self, to: to, render: render) 53 | let push = basicItem.pushBehavior(.down) 54 | basicItem.behavior = push 55 | basicItem.duration = duration 56 | basicItem.timingFunction = type.easing() 57 | basicItem.completion = completion 58 | basicItem.delay = delay 59 | basicItem.autoreverses = autoreverses 60 | push.commitToBasic() 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/SnapConfigurable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public protocol SnapConfigurable: BasicChainable { 12 | func snap(_ damping: CGFloat) -> SnapConfigurable 13 | } 14 | 15 | public protocol SnapConfigurable1: BasicChainable1 { 16 | func snap(_ damping: CGFloat) -> SnapConfigurable1 17 | } 18 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/StepControllable.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | 11 | public protocol StepControllable { 12 | //remove all remaining from excute sequence 13 | func cancelAllRemaining() 14 | //will add more methods to control animation steps 15 | } -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/TimingFunction.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | import Foundation 9 | 10 | /// A set of preset bezier curves. 11 | public enum TimingFunctionType { 12 | /// Equivalent to `kCAMediaTimingFunctionDefault`. 13 | case `default` 14 | 15 | /// Equivalent to `kCAMediaTimingFunctionEaseIn`. 16 | case easeIn 17 | 18 | /// Equivalent to `kCAMediaTimingFunctionEaseOut`. 19 | case easeOut 20 | 21 | /// Equivalent to `kCAMediaTimingFunctionEaseInEaseOut`. 22 | case easeInEaseOut 23 | 24 | /// No easing. 25 | case linear 26 | 27 | /// Inspired by the default curve in Google Material Design. 28 | case swiftOut 29 | /// 30 | case backEaseIn 31 | /// 32 | case backEaseOut 33 | /// 34 | case backEaseInOut 35 | /// 36 | case bounceOut 37 | /// 38 | case sine 39 | /// 40 | case circ 41 | /// 42 | case exponentialIn 43 | /// 44 | case exponentialOut 45 | /// 46 | case elasticIn 47 | /// 48 | case bounceReverse 49 | /// 50 | case elasticOut 51 | /// custom 52 | case custom(Double, Double, Double, Double) 53 | 54 | 55 | func easing() -> TimingSolvable { 56 | switch self { 57 | case .default: 58 | return UnitBezier(p1x: 0.25, p1y: 0.1, p2x: 0.25, p2y: 1.0) 59 | case .easeIn: 60 | return UnitBezier(p1x: 0.42, p1y: 0.0, p2x: 1.0, p2y: 1.0) 61 | case .easeOut: 62 | return UnitBezier(p1x: 0.0, p1y: 0.0, p2x: 0.58, p2y: 1.0) 63 | case .easeInEaseOut: 64 | return UnitBezier(p1x: 0.42, p1y: 0.0, p2x: 0.58, p2y: 1.0) 65 | case .linear: 66 | return UnitBezier(p1x: 0.0, p1y: 0.0, p2x: 1.0, p2y: 1.0) 67 | case .swiftOut: 68 | return UnitBezier(p1x: 0.4, p1y: 0.0, p2x: 0.2, p2y: 1.0) 69 | case .backEaseIn: 70 | return EasingContainer(easing: { (t: Double) in 71 | return t * t * t - t * sin(t * M_PI) 72 | }) 73 | case .backEaseOut: 74 | return EasingContainer(easing: { (t: Double) in 75 | let f = (1 - t); 76 | return 1 - (f * f * f - f * sin(f * M_PI)); 77 | }) 78 | case .backEaseInOut: 79 | return EasingContainer(easing: { (t: Double) in 80 | if(t < 0.5) { 81 | let f = 2 * t; 82 | return 0.5 * (f * f * f - f * sin(f * M_PI)); 83 | } else { 84 | let f = (1.0 - (2.0 * t - 1.0)); 85 | let cubic = f * f * f 86 | return 0.5 * (1.0 - (cubic - f * sin(f * M_PI))) + 0.5; 87 | } 88 | }) 89 | case .bounceOut: 90 | return EasingContainer(easing: { (t: Double) in 91 | if(t < 4/11.0){ 92 | return (121 * t * t)/16.0; 93 | } else if(t < 8/11.0){ 94 | return (363/40.0 * t * t) - (99/10.0 * t) + 17/5.0; 95 | }else if(t < 9/10.0){ 96 | return (4356/361.0 * t * t) - (35442/1805.0 * t) + 16061/1805.0; 97 | }else{ 98 | return (54/5.0 * t * t) - (513/25.0 * t) + 268/25.0; 99 | } 100 | }) 101 | case .sine: 102 | return EasingContainer(easing: { (t: Double) in 103 | return 1 - cos( t * M_PI / 2.0) 104 | }) 105 | case .circ: 106 | return EasingContainer(easing: { (t: Double) in 107 | return 1 - sqrt( 1.0 - t * t ) 108 | }) 109 | case .exponentialIn: 110 | return EasingContainer(easing: { (t: Double) in 111 | return (t == 0.0) ? t : pow(2, 10 * (t - 1)) 112 | }) 113 | case .exponentialOut: 114 | return EasingContainer(easing: { (t: Double) in 115 | return (t == 1.0) ? t : 1 - pow(2, -10 * t) 116 | }) 117 | case .elasticIn: 118 | return EasingContainer(easing: { (t: Double) in 119 | return sin(13.0 * M_PI_2 * t) * pow(2, 10 * (t - 1)) 120 | }) 121 | case .elasticOut: 122 | return EasingContainer(easing: { (t: Double) in 123 | return sin(-13.0 * M_PI_2 * (t + 1)) * pow(2, -10 * t) + 1.0; 124 | }) 125 | case .bounceReverse: 126 | return EasingContainer(easing: { (t: Double) in 127 | var bounce: Double = 4.0 128 | var pow2 = 0.0 129 | 130 | repeat { 131 | bounce = bounce - 1.0 132 | pow2 = pow(2, bounce) 133 | } while (t < (pow2 - 1.0 ) / 11.0) 134 | 135 | return 1 / pow( 4, 3 - bounce ) - 7.5625 * pow( ( pow2 * 3 - 2 ) / 22 - t, 2 ); 136 | }) 137 | case .custom(let p1x,let p1y,let p2x,let p2y): 138 | return UnitBezier(p1x: p1x, p1y: p1y, p2x: p2x, p2y: p2y) 139 | } 140 | } 141 | } 142 | 143 | class EasingContainer: TimingSolvable { 144 | let easing: (Double) -> Double 145 | 146 | init(easing: @escaping (Double) -> Double) { 147 | self.easing = easing 148 | } 149 | 150 | // 151 | func solveOn(_ time: Double, epslion: Double) -> Double { 152 | return self.easing(time) 153 | } 154 | } 155 | 156 | 157 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/TimingSolvable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimingSolvable.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/28/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol TimingSolvable { 12 | func solveOn(_ time: Double, epslion: Double) -> Double 13 | } 14 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/TimingType.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | 11 | protocol TimingType { 12 | var duration: CFTimeInterval { get set } 13 | var delay: CFTimeInterval { get set } 14 | var timingFunction: TimingSolvable { get set } 15 | var autoreverses: Bool { get set } 16 | var repeatCount: Int { get set } 17 | var speed: Double { get set } 18 | var timeOffset: CFTimeInterval { get set } 19 | } -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/UIDynamicBehavior+Commit.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | internal extension UIDynamicBehavior { 12 | 13 | func commit() { 14 | AnimatorCoordinator.shared.addBehavior(self) 15 | } 16 | 17 | func cancel() { 18 | self.dynamicAnimator?.removeBehavior(self) 19 | } 20 | 21 | func commitToBasic() { 22 | AnimatorCoordinator.shared.addBasicBehavior(self) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/UILabel+Stellar.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | extension UILabel { 12 | 13 | // public func makeTextColor(color: UIColor) -> UIView { 14 | // let type = AnimationType(type: .Basic, subType: .TextColor(color)) 15 | // context.addAnimationType(type) 16 | // return self 17 | // } 18 | } 19 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/UITextView+Stellar.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | extension UITextView { 12 | 13 | // public func makeTextColor(color: UIColor) -> UIView { 14 | // let type = AnimationType(type: .Basic, subType: .TextColor(color)) 15 | // context.addAnimationType(type) 16 | // return self 17 | // } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/UIView+FileConfigurable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+FileConfigurable.swift 3 | // StellarDemo 4 | // 5 | // Created by AugustRush on 6/7/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum ConfigurationError: Error { 12 | case invalidString 13 | case transformedError(Error) 14 | case undefined 15 | } 16 | 17 | extension UIView { 18 | //configure animation with JSON string 19 | public func configureWithJSON(_ str: String) throws -> Void { 20 | let data = str.data(using: String.Encoding.utf8) 21 | guard let _ = data else { 22 | throw ConfigurationError.invalidString 23 | } 24 | do { 25 | let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) 26 | switch json { 27 | case let dict as Dictionary<String,String>: 28 | configureWithDictionary(dict) 29 | default: 30 | throw ConfigurationError.undefined 31 | } 32 | } catch { 33 | throw ConfigurationError.transformedError(error) 34 | } 35 | } 36 | 37 | fileprivate func configureWithDictionary(_ dict: Dictionary<String, String>) -> Void { 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/UnitBezier.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import Foundation 10 | import CoreGraphics 11 | 12 | public typealias Scalar = Double 13 | /// A bezier curve, often used to calculate timing functions. 14 | public struct UnitBezier { 15 | 16 | /// The horizontal component of the first control point. 17 | public var p1x: Scalar 18 | 19 | /// The vertical component of the first control point. 20 | public var p1y: Scalar 21 | 22 | /// The horizontal component of the second control point. 23 | public var p2x: Scalar 24 | 25 | /// The vertical component of the second control point. 26 | public var p2y: Scalar 27 | 28 | /// Creates a new `UnitBezier` instance. 29 | public init(p1x: Scalar, p1y: Scalar, p2x: Scalar, p2y: Scalar) { 30 | self.p1x = p1x 31 | self.p1y = p1y 32 | self.p2x = p2x 33 | self.p2y = p2y 34 | } 35 | 36 | /// Calculates the resulting `y` for given `x`. 37 | /// 38 | /// - parameter x: The value to solve for. 39 | /// - parameter epsilon: The required precision of the result (where `x * epsilon` is the maximum time segment to be evaluated). 40 | /// - returns: The solved `y` value. 41 | public func solve(_ x: Scalar, epsilon: Scalar) -> Scalar { 42 | return UnitBezierSolver(bezier: self).solve(x, eps: epsilon) 43 | } 44 | } 45 | 46 | extension UnitBezier: Equatable { } 47 | 48 | extension UnitBezier: TimingSolvable { 49 | func solveOn(_ time: Double, epslion: Double) -> Double { 50 | return self.solve(time, epsilon: epslion) 51 | } 52 | } 53 | 54 | /// Equatable. 55 | public func ==(lhs: UnitBezier, rhs: UnitBezier) -> Bool { 56 | return lhs.p1x == rhs.p1x 57 | && lhs.p1y == rhs.p1y 58 | && lhs.p2x == rhs.p2x 59 | && lhs.p2y == rhs.p2y 60 | } 61 | 62 | 63 | // Ported to Swift from WebCore: 64 | // http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h 65 | 66 | /* 67 | * Copyright (C) 2008 Apple Inc. All Rights Reserved. 68 | * 69 | * Redistribution and use in source and binary forms, with or without 70 | * modification, are permitted provided that the following conditions 71 | * are met: 72 | * 1. Redistributions of source code must retain the above copyright 73 | * notice, this list of conditions and the following disclaimer. 74 | * 2. Redistributions in binary form must reproduce the above copyright 75 | * notice, this list of conditions and the following disclaimer in the 76 | * documentation and/or other materials provided with the distribution. 77 | * 78 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 79 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 80 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 81 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 82 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 83 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 84 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 85 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 86 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 87 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 88 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 89 | */ 90 | 91 | 92 | private struct UnitBezierSolver { 93 | 94 | fileprivate let ax: Scalar 95 | fileprivate let bx: Scalar 96 | fileprivate let cx: Scalar 97 | 98 | fileprivate let ay: Scalar 99 | fileprivate let by: Scalar 100 | fileprivate let cy: Scalar 101 | 102 | init(bezier: UnitBezier) { 103 | self.init(p1x: bezier.p1x, p1y: bezier.p1y, p2x: bezier.p2x, p2y: bezier.p2y) 104 | } 105 | 106 | init(p1x: Scalar, p1y: Scalar, p2x: Scalar, p2y: Scalar) { 107 | 108 | // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1). 109 | cx = 3.0 * p1x 110 | bx = 3.0 * (p2x - p1x) - cx 111 | ax = 1.0 - cx - bx 112 | 113 | cy = 3.0 * p1y 114 | by = 3.0 * (p2y - p1y) - cy 115 | ay = 1.0 - cy - by 116 | } 117 | 118 | func sampleCurveX(_ t: Scalar) -> Scalar { 119 | return ((ax * t + bx) * t + cx) * t 120 | } 121 | 122 | func sampleCurveY(_ t: Scalar) -> Scalar { 123 | return ((ay * t + by) * t + cy) * t 124 | } 125 | 126 | func sampleCurveDerivativeX(_ t: Scalar) -> Scalar { 127 | return (3.0 * ax * t + 2.0 * bx) * t + cx 128 | } 129 | 130 | func solveCurveX(_ x: Scalar, eps: Scalar) -> Scalar { 131 | var t0: Scalar = 0.0 132 | var t1: Scalar = 0.0 133 | var t2: Scalar = 0.0 134 | var x2: Scalar = 0.0 135 | var d2: Scalar = 0.0 136 | 137 | // First try a few iterations of Newton's method -- normally very fast. 138 | t2 = x 139 | for _ in 0..<8 { 140 | x2 = sampleCurveX(t2) - x 141 | if abs(x2) < eps { 142 | return t2 143 | } 144 | d2 = sampleCurveDerivativeX(t2) 145 | if abs(d2) < 1e-6 { 146 | break 147 | } 148 | t2 = t2 - x2 / d2 149 | } 150 | 151 | // Fall back to the bisection method for reliability. 152 | t0 = 0.0 153 | t1 = 1.0 154 | t2 = x 155 | 156 | if t2 < t0 { 157 | return t0 158 | } 159 | if t2 > t1 { 160 | return t1 161 | } 162 | 163 | while t0 < t1 { 164 | x2 = sampleCurveX(t2) 165 | if abs(x2-x) < eps { 166 | return t2 167 | } 168 | if x > x2 { 169 | t0 = t2 170 | } else { 171 | t1 = t2 172 | } 173 | t2 = (t1-t0) * 0.5 + t0 174 | } 175 | 176 | return t2 177 | } 178 | 179 | func solve(_ x: Scalar, eps: Scalar) -> Scalar { 180 | return sampleCurveY(solveCurveX(x, eps: eps)) 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/Sources/Sources/Vectorial.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2016 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | //The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | import UIKit 10 | 11 | public class Vector4 { 12 | var one: Double = 0 13 | var two: Double = 0 14 | var three: Double = 0 15 | var four: Double = 0 16 | 17 | convenience init(_ fourLatitude: (Double,Double,Double,Double)) { 18 | self.init() 19 | self.one = fourLatitude.0 20 | self.two = fourLatitude.1 21 | self.three = fourLatitude.2 22 | self.four = fourLatitude.3 23 | } 24 | } 25 | 26 | public protocol Vectorial { 27 | func convert(_ p: Vector4) -> Self 28 | func reverse() -> Vector4 29 | } 30 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemo/MyPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 2 | <playground version='5.0' target-platform='ios' auto-termination-delay='50' display-mode='rendered' timelineScrubberEnabled='true' last-migration='0820'> 3 | <timeline fileName='timeline.xctimeline'/> 4 | </playground> -------------------------------------------------------------------------------- /StellarDemo/StellarDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>en</string> 7 | <key>CFBundleExecutable</key> 8 | <string>$(EXECUTABLE_NAME)</string> 9 | <key>CFBundleIdentifier</key> 10 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 11 | <key>CFBundleInfoDictionaryVersion</key> 12 | <string>6.0</string> 13 | <key>CFBundleName</key> 14 | <string>$(PRODUCT_NAME)</string> 15 | <key>CFBundlePackageType</key> 16 | <string>BNDL</string> 17 | <key>CFBundleShortVersionString</key> 18 | <string>1.0</string> 19 | <key>CFBundleSignature</key> 20 | <string>????</string> 21 | <key>CFBundleVersion</key> 22 | <string>1</string> 23 | </dict> 24 | </plist> 25 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemoTests/StellarDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StellarDemoTests.swift 3 | // StellarDemoTests 4 | // 5 | // Created by AugustRush on 5/7/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import StellarDemo 11 | 12 | class StellarDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>en</string> 7 | <key>CFBundleExecutable</key> 8 | <string>$(EXECUTABLE_NAME)</string> 9 | <key>CFBundleIdentifier</key> 10 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 11 | <key>CFBundleInfoDictionaryVersion</key> 12 | <string>6.0</string> 13 | <key>CFBundleName</key> 14 | <string>$(PRODUCT_NAME)</string> 15 | <key>CFBundlePackageType</key> 16 | <string>BNDL</string> 17 | <key>CFBundleShortVersionString</key> 18 | <string>1.0</string> 19 | <key>CFBundleSignature</key> 20 | <string>????</string> 21 | <key>CFBundleVersion</key> 22 | <string>1</string> 23 | </dict> 24 | </plist> 25 | -------------------------------------------------------------------------------- /StellarDemo/StellarDemoUITests/StellarDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StellarDemoUITests.swift 3 | // StellarDemoUITests 4 | // 5 | // Created by AugustRush on 5/7/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class StellarDemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /StellarDemo/StellarTests/Info.plist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 3 | <plist version="1.0"> 4 | <dict> 5 | <key>CFBundleDevelopmentRegion</key> 6 | <string>en</string> 7 | <key>CFBundleExecutable</key> 8 | <string>$(EXECUTABLE_NAME)</string> 9 | <key>CFBundleIdentifier</key> 10 | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> 11 | <key>CFBundleInfoDictionaryVersion</key> 12 | <string>6.0</string> 13 | <key>CFBundleName</key> 14 | <string>$(PRODUCT_NAME)</string> 15 | <key>CFBundlePackageType</key> 16 | <string>BNDL</string> 17 | <key>CFBundleShortVersionString</key> 18 | <string>1.0</string> 19 | <key>CFBundleSignature</key> 20 | <string>????</string> 21 | <key>CFBundleVersion</key> 22 | <string>1</string> 23 | </dict> 24 | </plist> 25 | -------------------------------------------------------------------------------- /StellarDemo/StellarTests/StellarTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StellarTests.swift 3 | // StellarTests 4 | // 5 | // Created by AugustRush on 6/6/16. 6 | // Copyright © 2016 August. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Stellar 11 | 12 | class StellarTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /attachmentCurve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/attachmentCurve.gif -------------------------------------------------------------------------------- /balls.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/balls.gif -------------------------------------------------------------------------------- /basicCurve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/basicCurve.gif -------------------------------------------------------------------------------- /example4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/example4.gif -------------------------------------------------------------------------------- /example5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/example5.gif -------------------------------------------------------------------------------- /example6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/example6.gif -------------------------------------------------------------------------------- /gravityCurve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/gravityCurve.gif -------------------------------------------------------------------------------- /layers.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/layers.gif -------------------------------------------------------------------------------- /lines.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/lines.gif -------------------------------------------------------------------------------- /pushCurve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/pushCurve.gif -------------------------------------------------------------------------------- /snapCurve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/snapCurve.gif -------------------------------------------------------------------------------- /title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/Stellar/6c192427621f8b52f3b155d0088e1eabd156abe0/title.png --------------------------------------------------------------------------------