├── .DS_Store ├── .gitignore ├── .travis.yml ├── ARAnimation.podspec ├── ARAnimationDemo ├── .DS_Store ├── ARAnimationDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── ARAnimationDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── ARAnimationDemoTests │ ├── ARAnimationDemoTests.m │ └── Info.plist └── ARAnimationDemoUITests │ ├── ARAnimationDemoUITests.m │ └── Info.plist ├── LICENSE ├── README.md ├── Source ├── ARAnimatableProperty.h ├── ARAnimatableProperty.m ├── ARAnimation.h ├── ARAnimationFakeArray.h ├── ARAnimationFakeArray.m ├── ARBasicAnimation.h ├── ARBasicAnimation.m ├── AREasingCurveFunction.h ├── AREasingCurveFunction.m ├── ARInterpolation.h ├── ARSpringAnimation.h ├── ARSpringAnimation.m ├── ArInterpolation.m ├── CALayer+ARAnimation.h ├── CALayer+ARAnimation.m ├── UIView+ARAnimation.h └── UIView+ARAnimation.m ├── ex1.gif ├── rotaion.gif └── title.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/ARAnimation/342628475c848e73d04df5543d487b77a8979b83/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | #指定运行环境 2 | language: node_js 3 | #指定nodejs版本,可以指定多个 4 | node_js: 5 | - 0.12.5 6 | 7 | #运行的脚本命令 8 | script: 9 | - npm run ci 10 | 11 | #指定分支,只有指定的分支提交时才会运行脚本 12 | branches: 13 | only: 14 | - master -------------------------------------------------------------------------------- /ARAnimation.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "ARAnimation" 3 | s.version = "0.5" 4 | s.summary = "Easily Core Animation and more!" 5 | s.homepage = "https://github.com/AugustRush/ARAnimation" 6 | s.license = "MIT" 7 | s.author = { "AugustRush" => "819373341@qq.com" } 8 | s.platform = :ios, "6.0" 9 | s.source = { :git => "https://github.com/AugustRush/ARAnimation.git", :tag => "0.5" } 10 | s.source_files = "Source", "Source/**/*.{h,m}" 11 | s.exclude_files = "Source/Exclude" 12 | s.public_header_files = "Source/*.h" 13 | s.framework = "QuartzCore" 14 | s.frameworks = "UIKit", "Foundation" 15 | s.requires_arc = true 16 | end 17 | -------------------------------------------------------------------------------- /ARAnimationDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/ARAnimation/342628475c848e73d04df5543d487b77a8979b83/ARAnimationDemo/.DS_Store -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 97287D971BF590CD0045EF98 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287D961BF590CD0045EF98 /* main.m */; }; 11 | 97287D9A1BF590CD0045EF98 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287D991BF590CD0045EF98 /* AppDelegate.m */; }; 12 | 97287D9D1BF590CD0045EF98 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287D9C1BF590CD0045EF98 /* ViewController.m */; }; 13 | 97287DA01BF590CD0045EF98 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97287D9E1BF590CD0045EF98 /* Main.storyboard */; }; 14 | 97287DA21BF590CD0045EF98 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97287DA11BF590CD0045EF98 /* Assets.xcassets */; }; 15 | 97287DA51BF590CD0045EF98 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97287DA31BF590CD0045EF98 /* LaunchScreen.storyboard */; }; 16 | 97287DB01BF590CD0045EF98 /* ARAnimationDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DAF1BF590CD0045EF98 /* ARAnimationDemoTests.m */; }; 17 | 97287DBB1BF590CD0045EF98 /* ARAnimationDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DBA1BF590CD0045EF98 /* ARAnimationDemoUITests.m */; }; 18 | 97287DFD1BF5DAA70045EF98 /* ARAnimatableProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DED1BF5DAA70045EF98 /* ARAnimatableProperty.m */; }; 19 | 97287DFE1BF5DAA70045EF98 /* ARAnimationFakeArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DF01BF5DAA70045EF98 /* ARAnimationFakeArray.m */; }; 20 | 97287DFF1BF5DAA70045EF98 /* ARBasicAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DF21BF5DAA70045EF98 /* ARBasicAnimation.m */; }; 21 | 97287E001BF5DAA70045EF98 /* AREasingCurveFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DF41BF5DAA70045EF98 /* AREasingCurveFunction.m */; }; 22 | 97287E011BF5DAA70045EF98 /* ArInterpolation.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DF61BF5DAA70045EF98 /* ArInterpolation.m */; }; 23 | 97287E021BF5DAA70045EF98 /* ARSpringAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DF81BF5DAA70045EF98 /* ARSpringAnimation.m */; }; 24 | 97287E031BF5DAA70045EF98 /* CALayer+ARAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DFA1BF5DAA70045EF98 /* CALayer+ARAnimation.m */; }; 25 | 97287E041BF5DAA70045EF98 /* UIView+ARAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 97287DFC1BF5DAA70045EF98 /* UIView+ARAnimation.m */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | 97287DAC1BF590CD0045EF98 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 97287D8A1BF590CD0045EF98 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 97287D911BF590CD0045EF98; 34 | remoteInfo = ARAnimationDemo; 35 | }; 36 | 97287DB71BF590CD0045EF98 /* PBXContainerItemProxy */ = { 37 | isa = PBXContainerItemProxy; 38 | containerPortal = 97287D8A1BF590CD0045EF98 /* Project object */; 39 | proxyType = 1; 40 | remoteGlobalIDString = 97287D911BF590CD0045EF98; 41 | remoteInfo = ARAnimationDemo; 42 | }; 43 | /* End PBXContainerItemProxy section */ 44 | 45 | /* Begin PBXFileReference section */ 46 | 97287D921BF590CD0045EF98 /* ARAnimationDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ARAnimationDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 97287D961BF590CD0045EF98 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 97287D981BF590CD0045EF98 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 97287D991BF590CD0045EF98 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 97287D9B1BF590CD0045EF98 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 51 | 97287D9C1BF590CD0045EF98 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 52 | 97287D9F1BF590CD0045EF98 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | 97287DA11BF590CD0045EF98 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 97287DA41BF590CD0045EF98 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | 97287DA61BF590CD0045EF98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 97287DAB1BF590CD0045EF98 /* ARAnimationDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ARAnimationDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 97287DAF1BF590CD0045EF98 /* ARAnimationDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARAnimationDemoTests.m; sourceTree = ""; }; 58 | 97287DB11BF590CD0045EF98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 97287DB61BF590CD0045EF98 /* ARAnimationDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ARAnimationDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 97287DBA1BF590CD0045EF98 /* ARAnimationDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARAnimationDemoUITests.m; sourceTree = ""; }; 61 | 97287DBC1BF590CD0045EF98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | 97287DEC1BF5DAA70045EF98 /* ARAnimatableProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARAnimatableProperty.h; path = ../../Source/ARAnimatableProperty.h; sourceTree = ""; }; 63 | 97287DED1BF5DAA70045EF98 /* ARAnimatableProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ARAnimatableProperty.m; path = ../../Source/ARAnimatableProperty.m; sourceTree = ""; }; 64 | 97287DEE1BF5DAA70045EF98 /* ARAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARAnimation.h; path = ../../Source/ARAnimation.h; sourceTree = ""; }; 65 | 97287DEF1BF5DAA70045EF98 /* ARAnimationFakeArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARAnimationFakeArray.h; path = ../../Source/ARAnimationFakeArray.h; sourceTree = ""; }; 66 | 97287DF01BF5DAA70045EF98 /* ARAnimationFakeArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ARAnimationFakeArray.m; path = ../../Source/ARAnimationFakeArray.m; sourceTree = ""; }; 67 | 97287DF11BF5DAA70045EF98 /* ARBasicAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARBasicAnimation.h; path = ../../Source/ARBasicAnimation.h; sourceTree = ""; }; 68 | 97287DF21BF5DAA70045EF98 /* ARBasicAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ARBasicAnimation.m; path = ../../Source/ARBasicAnimation.m; sourceTree = ""; }; 69 | 97287DF31BF5DAA70045EF98 /* AREasingCurveFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AREasingCurveFunction.h; path = ../../Source/AREasingCurveFunction.h; sourceTree = ""; }; 70 | 97287DF41BF5DAA70045EF98 /* AREasingCurveFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AREasingCurveFunction.m; path = ../../Source/AREasingCurveFunction.m; sourceTree = ""; }; 71 | 97287DF51BF5DAA70045EF98 /* ARInterpolation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARInterpolation.h; path = ../../Source/ARInterpolation.h; sourceTree = ""; }; 72 | 97287DF61BF5DAA70045EF98 /* ArInterpolation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ArInterpolation.m; path = ../../Source/ArInterpolation.m; sourceTree = ""; }; 73 | 97287DF71BF5DAA70045EF98 /* ARSpringAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARSpringAnimation.h; path = ../../Source/ARSpringAnimation.h; sourceTree = ""; }; 74 | 97287DF81BF5DAA70045EF98 /* ARSpringAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ARSpringAnimation.m; path = ../../Source/ARSpringAnimation.m; sourceTree = ""; }; 75 | 97287DF91BF5DAA70045EF98 /* CALayer+ARAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CALayer+ARAnimation.h"; path = "../../Source/CALayer+ARAnimation.h"; sourceTree = ""; }; 76 | 97287DFA1BF5DAA70045EF98 /* CALayer+ARAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CALayer+ARAnimation.m"; path = "../../Source/CALayer+ARAnimation.m"; sourceTree = ""; }; 77 | 97287DFB1BF5DAA70045EF98 /* UIView+ARAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+ARAnimation.h"; path = "../../Source/UIView+ARAnimation.h"; sourceTree = ""; }; 78 | 97287DFC1BF5DAA70045EF98 /* UIView+ARAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIView+ARAnimation.m"; path = "../../Source/UIView+ARAnimation.m"; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 97287D8F1BF590CD0045EF98 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | 97287DA81BF590CD0045EF98 /* Frameworks */ = { 90 | isa = PBXFrameworksBuildPhase; 91 | buildActionMask = 2147483647; 92 | files = ( 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | 97287DB31BF590CD0045EF98 /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | /* End PBXFrameworksBuildPhase section */ 104 | 105 | /* Begin PBXGroup section */ 106 | 97287D891BF590CD0045EF98 = { 107 | isa = PBXGroup; 108 | children = ( 109 | 97287D941BF590CD0045EF98 /* ARAnimationDemo */, 110 | 97287DAE1BF590CD0045EF98 /* ARAnimationDemoTests */, 111 | 97287DB91BF590CD0045EF98 /* ARAnimationDemoUITests */, 112 | 97287D931BF590CD0045EF98 /* Products */, 113 | ); 114 | sourceTree = ""; 115 | }; 116 | 97287D931BF590CD0045EF98 /* Products */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 97287D921BF590CD0045EF98 /* ARAnimationDemo.app */, 120 | 97287DAB1BF590CD0045EF98 /* ARAnimationDemoTests.xctest */, 121 | 97287DB61BF590CD0045EF98 /* ARAnimationDemoUITests.xctest */, 122 | ); 123 | name = Products; 124 | sourceTree = ""; 125 | }; 126 | 97287D941BF590CD0045EF98 /* ARAnimationDemo */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 97287DCA1BF591710045EF98 /* Vendor */, 130 | 97287D981BF590CD0045EF98 /* AppDelegate.h */, 131 | 97287D991BF590CD0045EF98 /* AppDelegate.m */, 132 | 97287D9B1BF590CD0045EF98 /* ViewController.h */, 133 | 97287D9C1BF590CD0045EF98 /* ViewController.m */, 134 | 97287D9E1BF590CD0045EF98 /* Main.storyboard */, 135 | 97287DA11BF590CD0045EF98 /* Assets.xcassets */, 136 | 97287DA31BF590CD0045EF98 /* LaunchScreen.storyboard */, 137 | 97287DA61BF590CD0045EF98 /* Info.plist */, 138 | 97287D951BF590CD0045EF98 /* Supporting Files */, 139 | ); 140 | path = ARAnimationDemo; 141 | sourceTree = ""; 142 | }; 143 | 97287D951BF590CD0045EF98 /* Supporting Files */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 97287D961BF590CD0045EF98 /* main.m */, 147 | ); 148 | name = "Supporting Files"; 149 | sourceTree = ""; 150 | }; 151 | 97287DAE1BF590CD0045EF98 /* ARAnimationDemoTests */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 97287DAF1BF590CD0045EF98 /* ARAnimationDemoTests.m */, 155 | 97287DB11BF590CD0045EF98 /* Info.plist */, 156 | ); 157 | path = ARAnimationDemoTests; 158 | sourceTree = ""; 159 | }; 160 | 97287DB91BF590CD0045EF98 /* ARAnimationDemoUITests */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 97287DBA1BF590CD0045EF98 /* ARAnimationDemoUITests.m */, 164 | 97287DBC1BF590CD0045EF98 /* Info.plist */, 165 | ); 166 | path = ARAnimationDemoUITests; 167 | sourceTree = ""; 168 | }; 169 | 97287DCA1BF591710045EF98 /* Vendor */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 97287DEE1BF5DAA70045EF98 /* ARAnimation.h */, 173 | 97287DE81BF5A99C0045EF98 /* Category */, 174 | 97287DE71BF5A97A0045EF98 /* Private */, 175 | 97287DE61BF5A9500045EF98 /* Animations */, 176 | ); 177 | name = Vendor; 178 | sourceTree = ""; 179 | }; 180 | 97287DE61BF5A9500045EF98 /* Animations */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | 97287DF11BF5DAA70045EF98 /* ARBasicAnimation.h */, 184 | 97287DF21BF5DAA70045EF98 /* ARBasicAnimation.m */, 185 | 97287DF71BF5DAA70045EF98 /* ARSpringAnimation.h */, 186 | 97287DF81BF5DAA70045EF98 /* ARSpringAnimation.m */, 187 | ); 188 | name = Animations; 189 | sourceTree = ""; 190 | }; 191 | 97287DE71BF5A97A0045EF98 /* Private */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 97287DEC1BF5DAA70045EF98 /* ARAnimatableProperty.h */, 195 | 97287DED1BF5DAA70045EF98 /* ARAnimatableProperty.m */, 196 | 97287DEF1BF5DAA70045EF98 /* ARAnimationFakeArray.h */, 197 | 97287DF01BF5DAA70045EF98 /* ARAnimationFakeArray.m */, 198 | 97287DF31BF5DAA70045EF98 /* AREasingCurveFunction.h */, 199 | 97287DF41BF5DAA70045EF98 /* AREasingCurveFunction.m */, 200 | 97287DF51BF5DAA70045EF98 /* ARInterpolation.h */, 201 | 97287DF61BF5DAA70045EF98 /* ArInterpolation.m */, 202 | ); 203 | name = Private; 204 | sourceTree = ""; 205 | }; 206 | 97287DE81BF5A99C0045EF98 /* Category */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | 97287DF91BF5DAA70045EF98 /* CALayer+ARAnimation.h */, 210 | 97287DFA1BF5DAA70045EF98 /* CALayer+ARAnimation.m */, 211 | 97287DFB1BF5DAA70045EF98 /* UIView+ARAnimation.h */, 212 | 97287DFC1BF5DAA70045EF98 /* UIView+ARAnimation.m */, 213 | ); 214 | name = Category; 215 | sourceTree = ""; 216 | }; 217 | /* End PBXGroup section */ 218 | 219 | /* Begin PBXNativeTarget section */ 220 | 97287D911BF590CD0045EF98 /* ARAnimationDemo */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 97287DBF1BF590CD0045EF98 /* Build configuration list for PBXNativeTarget "ARAnimationDemo" */; 223 | buildPhases = ( 224 | 97287D8E1BF590CD0045EF98 /* Sources */, 225 | 97287D8F1BF590CD0045EF98 /* Frameworks */, 226 | 97287D901BF590CD0045EF98 /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | ); 232 | name = ARAnimationDemo; 233 | productName = ARAnimationDemo; 234 | productReference = 97287D921BF590CD0045EF98 /* ARAnimationDemo.app */; 235 | productType = "com.apple.product-type.application"; 236 | }; 237 | 97287DAA1BF590CD0045EF98 /* ARAnimationDemoTests */ = { 238 | isa = PBXNativeTarget; 239 | buildConfigurationList = 97287DC21BF590CD0045EF98 /* Build configuration list for PBXNativeTarget "ARAnimationDemoTests" */; 240 | buildPhases = ( 241 | 97287DA71BF590CD0045EF98 /* Sources */, 242 | 97287DA81BF590CD0045EF98 /* Frameworks */, 243 | 97287DA91BF590CD0045EF98 /* Resources */, 244 | ); 245 | buildRules = ( 246 | ); 247 | dependencies = ( 248 | 97287DAD1BF590CD0045EF98 /* PBXTargetDependency */, 249 | ); 250 | name = ARAnimationDemoTests; 251 | productName = ARAnimationDemoTests; 252 | productReference = 97287DAB1BF590CD0045EF98 /* ARAnimationDemoTests.xctest */; 253 | productType = "com.apple.product-type.bundle.unit-test"; 254 | }; 255 | 97287DB51BF590CD0045EF98 /* ARAnimationDemoUITests */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 97287DC51BF590CD0045EF98 /* Build configuration list for PBXNativeTarget "ARAnimationDemoUITests" */; 258 | buildPhases = ( 259 | 97287DB21BF590CD0045EF98 /* Sources */, 260 | 97287DB31BF590CD0045EF98 /* Frameworks */, 261 | 97287DB41BF590CD0045EF98 /* Resources */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | 97287DB81BF590CD0045EF98 /* PBXTargetDependency */, 267 | ); 268 | name = ARAnimationDemoUITests; 269 | productName = ARAnimationDemoUITests; 270 | productReference = 97287DB61BF590CD0045EF98 /* ARAnimationDemoUITests.xctest */; 271 | productType = "com.apple.product-type.bundle.ui-testing"; 272 | }; 273 | /* End PBXNativeTarget section */ 274 | 275 | /* Begin PBXProject section */ 276 | 97287D8A1BF590CD0045EF98 /* Project object */ = { 277 | isa = PBXProject; 278 | attributes = { 279 | LastUpgradeCheck = 0710; 280 | ORGANIZATIONNAME = AugustRush; 281 | TargetAttributes = { 282 | 97287D911BF590CD0045EF98 = { 283 | CreatedOnToolsVersion = 7.1; 284 | }; 285 | 97287DAA1BF590CD0045EF98 = { 286 | CreatedOnToolsVersion = 7.1; 287 | TestTargetID = 97287D911BF590CD0045EF98; 288 | }; 289 | 97287DB51BF590CD0045EF98 = { 290 | CreatedOnToolsVersion = 7.1; 291 | TestTargetID = 97287D911BF590CD0045EF98; 292 | }; 293 | }; 294 | }; 295 | buildConfigurationList = 97287D8D1BF590CD0045EF98 /* Build configuration list for PBXProject "ARAnimationDemo" */; 296 | compatibilityVersion = "Xcode 3.2"; 297 | developmentRegion = English; 298 | hasScannedForEncodings = 0; 299 | knownRegions = ( 300 | en, 301 | Base, 302 | ); 303 | mainGroup = 97287D891BF590CD0045EF98; 304 | productRefGroup = 97287D931BF590CD0045EF98 /* Products */; 305 | projectDirPath = ""; 306 | projectRoot = ""; 307 | targets = ( 308 | 97287D911BF590CD0045EF98 /* ARAnimationDemo */, 309 | 97287DAA1BF590CD0045EF98 /* ARAnimationDemoTests */, 310 | 97287DB51BF590CD0045EF98 /* ARAnimationDemoUITests */, 311 | ); 312 | }; 313 | /* End PBXProject section */ 314 | 315 | /* Begin PBXResourcesBuildPhase section */ 316 | 97287D901BF590CD0045EF98 /* Resources */ = { 317 | isa = PBXResourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | 97287DA51BF590CD0045EF98 /* LaunchScreen.storyboard in Resources */, 321 | 97287DA21BF590CD0045EF98 /* Assets.xcassets in Resources */, 322 | 97287DA01BF590CD0045EF98 /* Main.storyboard in Resources */, 323 | ); 324 | runOnlyForDeploymentPostprocessing = 0; 325 | }; 326 | 97287DA91BF590CD0045EF98 /* Resources */ = { 327 | isa = PBXResourcesBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | 97287DB41BF590CD0045EF98 /* Resources */ = { 334 | isa = PBXResourcesBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | }; 340 | /* End PBXResourcesBuildPhase section */ 341 | 342 | /* Begin PBXSourcesBuildPhase section */ 343 | 97287D8E1BF590CD0045EF98 /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | 97287E001BF5DAA70045EF98 /* AREasingCurveFunction.m in Sources */, 348 | 97287E021BF5DAA70045EF98 /* ARSpringAnimation.m in Sources */, 349 | 97287D9D1BF590CD0045EF98 /* ViewController.m in Sources */, 350 | 97287D9A1BF590CD0045EF98 /* AppDelegate.m in Sources */, 351 | 97287D971BF590CD0045EF98 /* main.m in Sources */, 352 | 97287E011BF5DAA70045EF98 /* ArInterpolation.m in Sources */, 353 | 97287DFF1BF5DAA70045EF98 /* ARBasicAnimation.m in Sources */, 354 | 97287DFD1BF5DAA70045EF98 /* ARAnimatableProperty.m in Sources */, 355 | 97287DFE1BF5DAA70045EF98 /* ARAnimationFakeArray.m in Sources */, 356 | 97287E041BF5DAA70045EF98 /* UIView+ARAnimation.m in Sources */, 357 | 97287E031BF5DAA70045EF98 /* CALayer+ARAnimation.m in Sources */, 358 | ); 359 | runOnlyForDeploymentPostprocessing = 0; 360 | }; 361 | 97287DA71BF590CD0045EF98 /* Sources */ = { 362 | isa = PBXSourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | 97287DB01BF590CD0045EF98 /* ARAnimationDemoTests.m in Sources */, 366 | ); 367 | runOnlyForDeploymentPostprocessing = 0; 368 | }; 369 | 97287DB21BF590CD0045EF98 /* Sources */ = { 370 | isa = PBXSourcesBuildPhase; 371 | buildActionMask = 2147483647; 372 | files = ( 373 | 97287DBB1BF590CD0045EF98 /* ARAnimationDemoUITests.m in Sources */, 374 | ); 375 | runOnlyForDeploymentPostprocessing = 0; 376 | }; 377 | /* End PBXSourcesBuildPhase section */ 378 | 379 | /* Begin PBXTargetDependency section */ 380 | 97287DAD1BF590CD0045EF98 /* PBXTargetDependency */ = { 381 | isa = PBXTargetDependency; 382 | target = 97287D911BF590CD0045EF98 /* ARAnimationDemo */; 383 | targetProxy = 97287DAC1BF590CD0045EF98 /* PBXContainerItemProxy */; 384 | }; 385 | 97287DB81BF590CD0045EF98 /* PBXTargetDependency */ = { 386 | isa = PBXTargetDependency; 387 | target = 97287D911BF590CD0045EF98 /* ARAnimationDemo */; 388 | targetProxy = 97287DB71BF590CD0045EF98 /* PBXContainerItemProxy */; 389 | }; 390 | /* End PBXTargetDependency section */ 391 | 392 | /* Begin PBXVariantGroup section */ 393 | 97287D9E1BF590CD0045EF98 /* Main.storyboard */ = { 394 | isa = PBXVariantGroup; 395 | children = ( 396 | 97287D9F1BF590CD0045EF98 /* Base */, 397 | ); 398 | name = Main.storyboard; 399 | sourceTree = ""; 400 | }; 401 | 97287DA31BF590CD0045EF98 /* LaunchScreen.storyboard */ = { 402 | isa = PBXVariantGroup; 403 | children = ( 404 | 97287DA41BF590CD0045EF98 /* Base */, 405 | ); 406 | name = LaunchScreen.storyboard; 407 | sourceTree = ""; 408 | }; 409 | /* End PBXVariantGroup section */ 410 | 411 | /* Begin XCBuildConfiguration section */ 412 | 97287DBD1BF590CD0045EF98 /* Debug */ = { 413 | isa = XCBuildConfiguration; 414 | buildSettings = { 415 | ALWAYS_SEARCH_USER_PATHS = NO; 416 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 417 | CLANG_CXX_LIBRARY = "libc++"; 418 | CLANG_ENABLE_MODULES = YES; 419 | CLANG_ENABLE_OBJC_ARC = YES; 420 | CLANG_WARN_BOOL_CONVERSION = YES; 421 | CLANG_WARN_CONSTANT_CONVERSION = YES; 422 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 423 | CLANG_WARN_EMPTY_BODY = YES; 424 | CLANG_WARN_ENUM_CONVERSION = YES; 425 | CLANG_WARN_INT_CONVERSION = YES; 426 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 427 | CLANG_WARN_UNREACHABLE_CODE = YES; 428 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 429 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 430 | COPY_PHASE_STRIP = NO; 431 | DEBUG_INFORMATION_FORMAT = dwarf; 432 | ENABLE_STRICT_OBJC_MSGSEND = YES; 433 | ENABLE_TESTABILITY = YES; 434 | GCC_C_LANGUAGE_STANDARD = gnu99; 435 | GCC_DYNAMIC_NO_PIC = NO; 436 | GCC_NO_COMMON_BLOCKS = YES; 437 | GCC_OPTIMIZATION_LEVEL = 0; 438 | GCC_PREPROCESSOR_DEFINITIONS = ( 439 | "DEBUG=1", 440 | "$(inherited)", 441 | ); 442 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 443 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 444 | GCC_WARN_UNDECLARED_SELECTOR = YES; 445 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 446 | GCC_WARN_UNUSED_FUNCTION = YES; 447 | GCC_WARN_UNUSED_VARIABLE = YES; 448 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 449 | MTL_ENABLE_DEBUG_INFO = YES; 450 | ONLY_ACTIVE_ARCH = YES; 451 | SDKROOT = iphoneos; 452 | TARGETED_DEVICE_FAMILY = "1,2"; 453 | }; 454 | name = Debug; 455 | }; 456 | 97287DBE1BF590CD0045EF98 /* Release */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | ALWAYS_SEARCH_USER_PATHS = NO; 460 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 461 | CLANG_CXX_LIBRARY = "libc++"; 462 | CLANG_ENABLE_MODULES = YES; 463 | CLANG_ENABLE_OBJC_ARC = YES; 464 | CLANG_WARN_BOOL_CONVERSION = YES; 465 | CLANG_WARN_CONSTANT_CONVERSION = YES; 466 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 467 | CLANG_WARN_EMPTY_BODY = YES; 468 | CLANG_WARN_ENUM_CONVERSION = YES; 469 | CLANG_WARN_INT_CONVERSION = YES; 470 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 471 | CLANG_WARN_UNREACHABLE_CODE = YES; 472 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 473 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 474 | COPY_PHASE_STRIP = NO; 475 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 476 | ENABLE_NS_ASSERTIONS = NO; 477 | ENABLE_STRICT_OBJC_MSGSEND = YES; 478 | GCC_C_LANGUAGE_STANDARD = gnu99; 479 | GCC_NO_COMMON_BLOCKS = YES; 480 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 481 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 482 | GCC_WARN_UNDECLARED_SELECTOR = YES; 483 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 484 | GCC_WARN_UNUSED_FUNCTION = YES; 485 | GCC_WARN_UNUSED_VARIABLE = YES; 486 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 487 | MTL_ENABLE_DEBUG_INFO = NO; 488 | SDKROOT = iphoneos; 489 | TARGETED_DEVICE_FAMILY = "1,2"; 490 | VALIDATE_PRODUCT = YES; 491 | }; 492 | name = Release; 493 | }; 494 | 97287DC01BF590CD0045EF98 /* Debug */ = { 495 | isa = XCBuildConfiguration; 496 | buildSettings = { 497 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 498 | INFOPLIST_FILE = ARAnimationDemo/Info.plist; 499 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 500 | PRODUCT_BUNDLE_IDENTIFIER = AR.ARAnimationDemo; 501 | PRODUCT_NAME = "$(TARGET_NAME)"; 502 | }; 503 | name = Debug; 504 | }; 505 | 97287DC11BF590CD0045EF98 /* Release */ = { 506 | isa = XCBuildConfiguration; 507 | buildSettings = { 508 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 509 | INFOPLIST_FILE = ARAnimationDemo/Info.plist; 510 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 511 | PRODUCT_BUNDLE_IDENTIFIER = AR.ARAnimationDemo; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | }; 514 | name = Release; 515 | }; 516 | 97287DC31BF590CD0045EF98 /* Debug */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | BUNDLE_LOADER = "$(TEST_HOST)"; 520 | INFOPLIST_FILE = ARAnimationDemoTests/Info.plist; 521 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 522 | PRODUCT_BUNDLE_IDENTIFIER = AR.ARAnimationDemoTests; 523 | PRODUCT_NAME = "$(TARGET_NAME)"; 524 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ARAnimationDemo.app/ARAnimationDemo"; 525 | }; 526 | name = Debug; 527 | }; 528 | 97287DC41BF590CD0045EF98 /* Release */ = { 529 | isa = XCBuildConfiguration; 530 | buildSettings = { 531 | BUNDLE_LOADER = "$(TEST_HOST)"; 532 | INFOPLIST_FILE = ARAnimationDemoTests/Info.plist; 533 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 534 | PRODUCT_BUNDLE_IDENTIFIER = AR.ARAnimationDemoTests; 535 | PRODUCT_NAME = "$(TARGET_NAME)"; 536 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ARAnimationDemo.app/ARAnimationDemo"; 537 | }; 538 | name = Release; 539 | }; 540 | 97287DC61BF590CD0045EF98 /* Debug */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | INFOPLIST_FILE = ARAnimationDemoUITests/Info.plist; 544 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 545 | PRODUCT_BUNDLE_IDENTIFIER = AR.ARAnimationDemoUITests; 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | TEST_TARGET_NAME = ARAnimationDemo; 548 | USES_XCTRUNNER = YES; 549 | }; 550 | name = Debug; 551 | }; 552 | 97287DC71BF590CD0045EF98 /* Release */ = { 553 | isa = XCBuildConfiguration; 554 | buildSettings = { 555 | INFOPLIST_FILE = ARAnimationDemoUITests/Info.plist; 556 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 557 | PRODUCT_BUNDLE_IDENTIFIER = AR.ARAnimationDemoUITests; 558 | PRODUCT_NAME = "$(TARGET_NAME)"; 559 | TEST_TARGET_NAME = ARAnimationDemo; 560 | USES_XCTRUNNER = YES; 561 | }; 562 | name = Release; 563 | }; 564 | /* End XCBuildConfiguration section */ 565 | 566 | /* Begin XCConfigurationList section */ 567 | 97287D8D1BF590CD0045EF98 /* Build configuration list for PBXProject "ARAnimationDemo" */ = { 568 | isa = XCConfigurationList; 569 | buildConfigurations = ( 570 | 97287DBD1BF590CD0045EF98 /* Debug */, 571 | 97287DBE1BF590CD0045EF98 /* Release */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | 97287DBF1BF590CD0045EF98 /* Build configuration list for PBXNativeTarget "ARAnimationDemo" */ = { 577 | isa = XCConfigurationList; 578 | buildConfigurations = ( 579 | 97287DC01BF590CD0045EF98 /* Debug */, 580 | 97287DC11BF590CD0045EF98 /* Release */, 581 | ); 582 | defaultConfigurationIsVisible = 0; 583 | defaultConfigurationName = Release; 584 | }; 585 | 97287DC21BF590CD0045EF98 /* Build configuration list for PBXNativeTarget "ARAnimationDemoTests" */ = { 586 | isa = XCConfigurationList; 587 | buildConfigurations = ( 588 | 97287DC31BF590CD0045EF98 /* Debug */, 589 | 97287DC41BF590CD0045EF98 /* Release */, 590 | ); 591 | defaultConfigurationIsVisible = 0; 592 | defaultConfigurationName = Release; 593 | }; 594 | 97287DC51BF590CD0045EF98 /* Build configuration list for PBXNativeTarget "ARAnimationDemoUITests" */ = { 595 | isa = XCConfigurationList; 596 | buildConfigurations = ( 597 | 97287DC61BF590CD0045EF98 /* Debug */, 598 | 97287DC71BF590CD0045EF98 /* Release */, 599 | ); 600 | defaultConfigurationIsVisible = 0; 601 | defaultConfigurationName = Release; 602 | }; 603 | /* End XCConfigurationList section */ 604 | }; 605 | rootObject = 97287D8A1BF590CD0045EF98 /* Project object */; 606 | } 607 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapaARlities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "ARAnimation.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (nonatomic, weak) IBOutlet UIView *redView; 15 | @property (nonatomic, weak) IBOutlet UIView *yellowView; 16 | @property (nonatomic, strong) CAShapeLayer *shapeLayer; 17 | @property (weak, nonatomic) IBOutlet UIView *ball; 18 | 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | #pragma mark - - 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | // Do any additional setup after loading the view, typically from a nib. 28 | self.shapeLayer = [CAShapeLayer layer]; 29 | self.shapeLayer.frame = self.view.bounds; 30 | self.shapeLayer.fillColor = [UIColor clearColor].CGColor; 31 | self.shapeLayer.strokeColor = [UIColor greenColor].CGColor; 32 | self.shapeLayer.lineWidth = 2; 33 | [self.view.layer addSublayer:self.shapeLayer]; 34 | } 35 | 36 | - (void)didReceiveMemoryWarning { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | #pragma mark - == 42 | 43 | - (IBAction)buttonClicked:(id)sender { 44 | // [self multipleViewAnimations]; 45 | 46 | // [self rotationAnimation]; 47 | [self ortationAndMoveX]; 48 | } 49 | 50 | #pragma mark - -- 51 | 52 | - (void)ortationAndMoveX { 53 | CGFloat x = _ball.layer.position.x; 54 | CGFloat y = _ball.layer.position.y; 55 | [UIView AR_animationWithDuration:1 animations:^{ 56 | _ball.layer.rotation = 4; 57 | _ball.layer.position = CGPointMake(x+100, y); 58 | } completion:^{ 59 | CGFloat x1 = _ball.layer.position.x; 60 | [UIView AR_animationWithDuration:1 delay:0 easing:kAREasingCurveBounceOut animations:^{ 61 | _ball.layer.rotation = -4; 62 | _ball.layer.position = CGPointMake(x1-100, y); 63 | } completion:nil]; 64 | }]; 65 | } 66 | 67 | - (void)rotationAnimation { 68 | 69 | [UIView AR_animationWithDuration:2.0 70 | animations:^{ 71 | self.redView.layer.rotation = M_PI*10; 72 | self.redView.layer.cornerRadius = 50; 73 | }]; 74 | } 75 | 76 | - (void)multipleViewAnimations { 77 | void(^animation5)(void) = ^{ 78 | self.shapeLayer.path = [UIBezierPath bezierPathWithRect:CGRectMake(100, 100, 100, 100)].CGPath; 79 | ARBasicAnimation *strokeEnd = [ARBasicAnimation animationWithKeyPath:kARShapeLayerStrokeEnd]; 80 | strokeEnd.fromValue = @0; 81 | strokeEnd.toValue = @1; 82 | strokeEnd.duration =2; 83 | strokeEnd.easing = kAREasingCurveBounceInOut; 84 | [self.shapeLayer addAnimation:strokeEnd forKey:nil]; 85 | self.shapeLayer.strokeEnd = 1; 86 | }; 87 | 88 | void(^animation4)(void) = ^{ 89 | [self.view setNeedsLayout]; 90 | [UIView AR_animationWithDuration:0.5 delay:0.0 easing:kAREasingCurveBounceOut animations:^{ 91 | [self.view layoutIfNeeded]; 92 | } completion:animation5]; 93 | }; 94 | 95 | void(^animation3)(void) = ^{ 96 | [UIView AR_springAnimationWithDuration:1 animations:^{ 97 | self.redView.layer.scale = 2; 98 | self.yellowView.layer.scale = 1; 99 | self.redView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 250); 100 | self.yellowView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 250); 101 | } completion:animation4]; 102 | }; 103 | 104 | void(^animation2)(void) = ^{ 105 | [UIView AR_springAnimationWithDuration:1.5 animations:^{ 106 | self.redView.layer.cornerRadius = CGRectGetMidX(self.redView.bounds); 107 | self.yellowView.layer.cornerRadius = CGRectGetMidX(self.yellowView.bounds); 108 | } completion:animation3]; 109 | }; 110 | 111 | void(^animation1)(void) = ^{ 112 | [UIView AR_animationWithDuration:0.5 animations:^{ 113 | self.redView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 150); 114 | self.yellowView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 150); 115 | self.redView.layer.scaleX = 1.3; 116 | self.yellowView.layer.scaleY = 1.3; 117 | } completion:animation2]; 118 | }; 119 | 120 | 121 | [UIView AR_animationWithDuration:2 animations:^{ 122 | self.redView.backgroundColor = [self randomColor]; 123 | self.yellowView.backgroundColor = [self randomColor]; 124 | self.yellowView.alpha = 1; 125 | 126 | self.redView.layer.rotation = M_PI*4; 127 | self.yellowView.layer.rotation = -M_PI*4; 128 | } completion:animation1]; 129 | } 130 | 131 | - (UIColor *) randomColor { 132 | CGFloat hue = ( arc4random() % 256 / 256.0 ); //0.0 to 1.0 133 | CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0,away from white 134 | CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; //0.5 to 1.0,away from black 135 | return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; 136 | } 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemoTests/ARAnimationDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimationDemoTests.m 3 | // ARAnimationDemoTests 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ARAnimationDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ARAnimationDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemoUITests/ARAnimationDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimationDemoUITests.m 3 | // ARAnimationDemoUITests 4 | // 5 | // Created by AugustRush on 15/11/13. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ARAnimationDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ARAnimationDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // 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. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ARAnimationDemo/ARAnimationDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 August 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![](https://github.com/AugustRush/ARAnimation/blob/develop/title.png) 2 | 3 | *___ARAnimation is an Core Animation library to make you animations easily.___* 4 | 5 | 6 | ## Features 7 | 8 | * __Layer animations__ 9 | * __Layer Spring Animations__ 10 | * __Custom TimingFunction(easing funtion)__ 11 | * __Official style block Animations__ 12 | 13 | ## Install 14 | 15 | #### Cocoapods 16 | * **pod 'ARAnimation',:git => "https://github.com/AugustRush/ARAnimation.git"** 17 | 18 | #### Manually 19 | * **just drag demo source ducument to your project** 20 | 21 | # Usage 22 | 23 | ## Example1 24 | 25 | ![](https://github.com/AugustRush/ARAnimation/blob/master/ex1.gif) 26 | -------------------------------------- 27 | ``` 28 | [UIView AR_animationWithDuration:2.0 29 | animations:^{ 30 | self.redView.layer.rotation = M_PI*10; 31 | self.redView.layer.cornerRadius = 50; 32 | }]; 33 | ``` 34 | 35 | ## Example2 (Multistep animations block Nested) 36 | 37 | ![](https://github.com/AugustRush/ARAnimation/blob/master/rotaion.gif) 38 | 39 | --------------------------------------- 40 | 41 | ``` 42 | void(^animation4)(void) = ^{ 43 | [self.view setNeedsLayout]; 44 | [UIView AR_animationWithDuration:0.5 delay:0.0 easing:kAREasingCurveBounceOut animations:^{ 45 | [self.view layoutIfNeeded]; 46 | } completion:^{ 47 | NSLog(@"all animations completion"); 48 | }]; 49 | }; 50 | 51 | void(^animation3)(void) = ^{ 52 | [UIView AR_springAnimationWithDuration:1 animations:^{ 53 | self.redView.layer.scale = 2; 54 | self.yellowView.layer.scale = 1; 55 | self.redView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 250); 56 | self.yellowView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 250); 57 | } completion:animation4]; 58 | }; 59 | 60 | void(^animation2)(void) = ^{ 61 | [UIView AR_springAnimationWithDuration:1.5 animations:^{ 62 | self.redView.layer.cornerRadius = CGRectGetMidX(self.redView.bounds); 63 | self.yellowView.layer.cornerRadius = CGRectGetMidX(self.yellowView.bounds); 64 | } completion:animation3]; 65 | }; 66 | 67 | void(^animation1)(void) = ^{ 68 | [UIView AR_animationWithDuration:0.5 animations:^{ 69 | self.redView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 150); 70 | self.yellowView.layer.position = CGPointMake(CGRectGetMidX(self.view.bounds), 150); 71 | self.redView.layer.scaleX = 1.3; 72 | self.yellowView.layer.scaleY = 1.3; 73 | } completion:animation2]; 74 | }; 75 | 76 | 77 | [UIView AR_animationWithDuration:2 animations:^{ 78 | self.redView.backgroundColor = [self randomColor]; 79 | self.yellowView.backgroundColor = [self randomColor]; 80 | self.yellowView.alpha = 1; 81 | 82 | self.redView.layer.rotation = M_PI*4; 83 | self.yellowView.layer.rotation = -M_PI*4; 84 | } completion:animation1]; 85 | ``` 86 | 87 | ## Official block style 88 | 89 | ####Basic 90 | ``` 91 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 92 | animations:(void (^)(void))animations; 93 | 94 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 95 | animations:(void (^)(void))animations 96 | completion:(void (^)(void))completion; 97 | 98 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 99 | animations:(void (^)(void))animations 100 | completion:(void (^)(void))completion; 101 | 102 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 103 | delay:(CFTimeInterval)delay 104 | animations:(void (^)(void))animations 105 | completion:(void (^)(void))completion; 106 | 107 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 108 | delay:(CFTimeInterval)delay 109 | easing:(AREasingCurve)easing 110 | animations:(void (^)(void))animations 111 | completion:(void (^)(void))completion; 112 | 113 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 114 | delay:(CFTimeInterval)delay 115 | repeatCount:(NSUInteger)repeatCount 116 | autoreverses:(BOOL)autoreverses 117 | easing:(AREasingCurve)easing 118 | animations:(void (^)(void))animations 119 | completion:(void (^)(void))completion; 120 | ``` 121 | ---------------------------------------- 122 | 123 | #### Spring 124 | ``` 125 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 126 | animations:(void (^)(void))animations; 127 | 128 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 129 | animations:(void (^)(void))animations 130 | completion:(void (^)(void))completion; 131 | 132 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 133 | delay:(CFTimeInterval)delay 134 | animations:(void (^)(void))animations 135 | completion:(void (^)(void))completion; 136 | 137 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 138 | delay:(CFTimeInterval)delay 139 | mass:(CGFloat)mass 140 | damping:(CGFloat)damping 141 | stiffness:(CGFloat)stiffness 142 | initialVelocity:(CGFloat)initialVelocity 143 | animations:(void (^)(void))animations 144 | completion:(void (^)(void))completion; 145 | 146 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 147 | delay:(CFTimeInterval)delay 148 | repeatCount:(NSUInteger)repeatCount 149 | autoreverses:(BOOL)autoreverses 150 | mass:(CGFloat)mass 151 | damping:(CGFloat)damping 152 | stiffness:(CGFloat)stiffness 153 | initialVelocity:(CGFloat)initialVelocity 154 | animations:(void (^)(void))animations 155 | completion:(void (^)(void))completion; 156 | ``` 157 | 158 | ## Support Layer animatable propertys 159 | 160 | * **kARLayerPosition** 161 | * **kARLayerPositionX** 162 | * **kARLayerPositionY** 163 | * **kARLayerCornerRadius** 164 | * **kARLayerZPositoin** 165 | * **kARLayerBorderWidth** 166 | * **kARLayerScaleX** 167 | * **kARLayerScaleY** 168 | * **kARLayerScale** 169 | * **kARLayerBounds** 170 | * **kARLayerBackgroundColor** 171 | * **kARLayerOpacity** 172 | * **kARLayerRotationX** 173 | * **kARLayerRotationY** 174 | * **kARLayerRotation** 175 | * **kARLayerAnchorPoint** 176 | * **kARShapeLayerStrokeEnd** 177 | * **kARShapeLayerStrokeStart** 178 | 179 | ## Reference 180 | 181 | * www.gizma.com/easing/#quad2 182 | * https://es.wikipedia.org/wiki/Oscilador_armónico 183 | * http://objccn.io/issue-12-4/ 184 | * https://github.com/robb/RBBAnimation 185 | 186 | ## Next 187 | 188 | * **More animatable layer's propertys** 189 | * **Custom animaton ??** 190 | * **Chainable animations ??** 191 | 192 | ## Supplement 193 | 194 | * **Please email me if you have any idea ‘liupingwei30@gmail.com’** 195 | 196 | ## Licence 197 | 198 | The MIT License (MIT) 199 | 200 | Copyright (c) 2015 August 201 | 202 | Permission is hereby granted, free of charge, to any person obtaining a copy 203 | of this software and associated documentation files (the "Software"), to deal 204 | in the Software without restriction, including without limitation the rights 205 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 206 | copies of the Software, and to permit persons to whom the Software is 207 | furnished to do so, subject to the following conditions: 208 | 209 | The above copyright notice and this permission notice shall be included in all 210 | copies or substantial portions of the Software. 211 | 212 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 213 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 214 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 215 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 216 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 217 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 218 | SOFTWARE. 219 | -------------------------------------------------------------------------------- /Source/ARAnimatableProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimatableProperty.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //CALayer 12 | FOUNDATION_EXPORT NSString * const kARLayerPosition; 13 | FOUNDATION_EXPORT NSString * const kARLayerPositionX; 14 | FOUNDATION_EXPORT NSString * const kARLayerPositionY; 15 | FOUNDATION_EXPORT NSString * const kARLayerCornerRadius; 16 | FOUNDATION_EXPORT NSString * const kARLayerZPositoin; 17 | FOUNDATION_EXPORT NSString * const kARLayerBorderWidth; 18 | FOUNDATION_EXPORT NSString * const kARLayerScaleX; 19 | FOUNDATION_EXPORT NSString * const kARLayerScaleY; 20 | FOUNDATION_EXPORT NSString * const kARLayerScale; 21 | FOUNDATION_EXPORT NSString * const kARLayerBounds; 22 | FOUNDATION_EXPORT NSString * const kARLayerBackgroundColor; 23 | FOUNDATION_EXPORT NSString * const kARLayerOpacity; 24 | FOUNDATION_EXPORT NSString * const kARLayerRotationX; 25 | FOUNDATION_EXPORT NSString * const kARLayerRotationY; 26 | FOUNDATION_EXPORT NSString * const kARLayerRotation; 27 | FOUNDATION_EXPORT NSString * const kARLayerAnchorPoint; 28 | //CAShapeLayer 29 | FOUNDATION_EXPORT NSString * const kARShapeLayerStrokeEnd; 30 | FOUNDATION_EXPORT NSString * const kARShapeLayerStrokeStart; 31 | 32 | NSArray *ARAllAnimatablePropertys(); 33 | 34 | NSString *ARLayerActionEventStoreKey(NSString *event); 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Source/ARAnimatableProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimatableProperty.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARAnimatableProperty.h" 10 | 11 | NSString * const kARLayerPosition = @"position"; 12 | NSString * const kARLayerPositionX = @"position.x"; 13 | NSString * const kARLayerPositionY = @"position.y"; 14 | NSString * const kARLayerCornerRadius = @"cornerRadius"; 15 | NSString * const kARLayerZPositoin = @"zPosition"; 16 | NSString * const kARLayerScaleX = @"transform.scale.x"; 17 | NSString * const kARLayerScaleY = @"transform.scale.y"; 18 | NSString * const kARLayerScale = @"transform.scale"; 19 | NSString * const kARLayerBorderWidth = @"borderWidth"; 20 | NSString * const kARLayerBounds = @"bounds"; 21 | NSString * const kARLayerBackgroundColor = @"backgroundColor"; 22 | NSString * const kARLayerOpacity = @"opacity"; 23 | NSString * const kARLayerRotationX = @"transform.rotation.x"; 24 | NSString * const kARLayerRotationY = @"transform.rotation.y"; 25 | NSString * const kARLayerRotation = @"transform.rotation"; 26 | NSString * const kARLayerAnchorPoint = @"anchorPoint"; 27 | NSString * const kARShapeLayerStrokeEnd = @"strokeEnd"; 28 | NSString * const kARShapeLayerStrokeStart = @"strokeStart"; 29 | 30 | 31 | 32 | NSArray *ARAllAnimatablePropertys() { 33 | return @[@"position", 34 | @"position.x", 35 | @"position.y", 36 | @"cornerRadius", 37 | @"zPosition", 38 | @"transform.scale.x", 39 | @"transform.scale.y", 40 | @"transform.scale", 41 | @"borderWidth", 42 | @"bounds", 43 | @"backgroundColor", 44 | @"opacity", 45 | @"transform.rotation.x", 46 | @"transform.rotation.y", 47 | @"transform.rotation", 48 | @"anchorPoint", 49 | @"strokeEnd", 50 | @"strokeStart"]; 51 | } 52 | 53 | NSString *ARLayerActionEventStoreKey(NSString *event) { 54 | static NSDictionary *dict = nil; 55 | static dispatch_once_t onceToken; 56 | dispatch_once(&onceToken, ^{ 57 | dict = @{@"position":@"position", 58 | @"position.x":@"positionX", 59 | @"position.y":@"positionY", 60 | @"cornerRadius":@"cornerRadius", 61 | @"zPosition":@"zPosition", 62 | @"transform.scale.x":@"transform.scale.x", 63 | @"transform.scale.y":@"transform.scale.y", 64 | @"transform.scale":@"transform.scale", 65 | @"borderWidth":@"borderWidth", 66 | @"bounds":@"bounds", 67 | @"backgroundColor":@"backgroundColor", 68 | @"opacity":@"opacity", 69 | @"transform.rotation.x":@"transformRotationX", 70 | @"transform.rotation.y":@"transformRotationY", 71 | @"transform.rotation":@"transformRotation", 72 | @"anchorPoint":@"anchorPoint", 73 | @"strokeEnd":@"strokeEnd", 74 | @"strokeStart":@"strokeStart"}; 75 | }); 76 | 77 | return dict[event]; 78 | } 79 | -------------------------------------------------------------------------------- /Source/ARAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimation.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ARAnimation. 12 | FOUNDATION_EXPORT double ARAnimationVerionNumber; 13 | 14 | //! Project version string for ARAnimation. 15 | FOUNDATION_EXPORT NSString * ARAnimationVersionString[]; 16 | 17 | #import "ARBasicAnimation.h" 18 | #import "ARSpringAnimation.h" 19 | #import "CALayer+ARAnimation.h" 20 | #import "UIView+ARAnimation.h" 21 | 22 | -------------------------------------------------------------------------------- /Source/ARAnimationFakeArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimationLazyArray.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/20. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARInterpolation.h" 10 | 11 | /** 12 | * @brief use for ARAnimation lazy calulate 13 | */ 14 | @interface ARAnimationFakeArray : NSArray 15 | 16 | + (instancetype)arrayWithCount:(NSUInteger)count 17 | interpolation:(ARInterpolation)interpolation 18 | from:(id)from 19 | to:(id)to 20 | easing:(AREasingCurve)easing; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Source/ARAnimationFakeArray.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARAnimationLazyArray.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/20. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARAnimationFakeArray.h" 10 | 11 | @interface ARAnimationFakeArray () 12 | 13 | @property (nonatomic, assign) NSUInteger fakeCount; 14 | @property (nonatomic, copy) ARInterpolation interpolation; 15 | @property (nonatomic, weak) id from; 16 | @property (nonatomic, weak) id to; 17 | @property (nonatomic, copy) AREasingCurve easing; 18 | 19 | @end 20 | 21 | @implementation ARAnimationFakeArray 22 | 23 | + (instancetype)arrayWithCount:(NSUInteger)count interpolation:(ARInterpolation)interpolation from:(id)from to:(id)to easing:(AREasingCurve)easing { 24 | ARAnimationFakeArray *array = [[super alloc] init]; 25 | array->_fakeCount = count; 26 | array->_interpolation = [interpolation copy]; 27 | array->_easing = [easing copy]; 28 | array->_from = from; 29 | array->_to = to; 30 | return array; 31 | } 32 | 33 | - (id)objectAtIndex:(NSUInteger)index { 34 | CGFloat percentage = index * 1.0 / (_fakeCount - 1); 35 | return _interpolation(_from,_to,percentage,_easing); 36 | } 37 | 38 | - (NSUInteger)count { 39 | return _fakeCount; 40 | } 41 | 42 | - (id)copyWithZone:(NSZone *)zone { 43 | return [[self class] arrayWithCount:_fakeCount interpolation:_interpolation from:_from to:_to easing:_easing]; 44 | } 45 | 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Source/ARBasicAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARBasicAnimation.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "AREasingCurveFunction.h" 10 | #import "ARInterpolation.h" 11 | #import "ARAnimatableProperty.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | @interface ARBasicAnimation : CAKeyframeAnimation 15 | 16 | @property (nonatomic, strong) id fromValue; 17 | @property (nonatomic, strong) id toValue; 18 | @property (nonatomic, copy) AREasingCurve easing; 19 | 20 | + (instancetype)animation NS_UNAVAILABLE; 21 | - (instancetype)init NS_UNAVAILABLE; 22 | 23 | @end 24 | 25 | @interface ARBasicAnimation (Unavalible) 26 | 27 | @property (nonatomic) NSString *calculationMode __attribute__((unavailable("calculationMode cannot be set on ARBasicAnimation"))); 28 | 29 | - (void)setValues:(NSArray *)values __attribute__((unavailable("values cannot be set on ARBasicAnimation"))); 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | -------------------------------------------------------------------------------- /Source/ARBasicAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARBasicAnimation.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARBasicAnimation.h" 10 | #import "ARAnimatableProperty.h" 11 | #import "ARAnimationFakeArray.h" 12 | 13 | @interface ARBasicAnimation () 14 | 15 | @property (nonatomic, copy) ARInterpolation interpolation; 16 | 17 | @end 18 | 19 | @implementation ARBasicAnimation 20 | 21 | + (instancetype)animationWithKeyPath:(NSString *)path { 22 | ARBasicAnimation *animation = [super animationWithKeyPath:path]; 23 | animation.easing = kAREasingCurveLinear; 24 | animation.duration = 0.25; 25 | animation.interpolation = InterpolationForKeyPath(path); 26 | return animation; 27 | } 28 | 29 | - (NSString *)calculationMode { 30 | return kCAAnimationLinear; 31 | } 32 | 33 | - (NSArray *)values { 34 | NSUInteger frames = self.duration * 60; 35 | 36 | //just create a fake array 37 | return [ARAnimationFakeArray arrayWithCount:frames interpolation:_interpolation from:_fromValue to:_toValue easing:_easing]; 38 | } 39 | 40 | - (id)copyWithZone:(NSZone *)zone { 41 | ARBasicAnimation *copy = [super copyWithZone:zone]; 42 | copy->_fromValue = _fromValue; 43 | copy->_toValue = _toValue; 44 | copy->_easing = _easing; 45 | copy->_interpolation = _interpolation; 46 | return copy; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Source/AREasingCurveFunction.h: -------------------------------------------------------------------------------- 1 | // 2 | // AREasingCurveFunction.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef CGFloat (^AREasingCurve)(CGFloat timePercentage); 12 | 13 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveLinear; 14 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveQuadratic; 15 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveEaseInCubic; 16 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveEaseOutCubic; 17 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveQuartic; 18 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveSine; 19 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveBackEaseIn; 20 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveBackEaseOut; 21 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveBackEaseInOut; 22 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveBounceOut; 23 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveBounceIn; 24 | FOUNDATION_EXPORT AREasingCurve const kAREasingCurveBounceInOut; -------------------------------------------------------------------------------- /Source/AREasingCurveFunction.m: -------------------------------------------------------------------------------- 1 | // 2 | // AREasingCurveFunction.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Cotyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "AREasingCurveFunction.h" 10 | 11 | AREasingCurve const kAREasingCurveLinear = ^CGFloat(CGFloat t){ 12 | return t; 13 | }; 14 | 15 | AREasingCurve const kAREasingCurveQuadratic = ^CGFloat(CGFloat t){ 16 | return t * t; 17 | }; 18 | 19 | AREasingCurve const kAREasingCurveEaseInCubic = ^CGFloat(CGFloat t){ 20 | return t * t * t; 21 | }; 22 | 23 | AREasingCurve const kAREasingCurveEaseOutCubic = ^CGFloat(CGFloat t){ 24 | return pow(t - 1, 3) + 1;; 25 | }; 26 | 27 | AREasingCurve const kAREasingCurveQuartic = ^CGFloat(CGFloat t){ 28 | return t * t * t * t; 29 | }; 30 | 31 | AREasingCurve const kAREasingCurveSine = ^CGFloat(CGFloat t){ 32 | return sin((t - 1) * M_PI_2) + 1; 33 | }; 34 | 35 | AREasingCurve const kAREasingCurveBackEaseIn = ^CGFloat(CGFloat t){ 36 | return t * t * t - t * sin(t * M_PI); 37 | }; 38 | 39 | AREasingCurve const kAREasingCurveBackEaseOut = ^CGFloat(CGFloat t){ 40 | CGFloat f = (1 - t); 41 | return 1 - (f * f * f - f * sin(f * M_PI)); 42 | }; 43 | 44 | AREasingCurve const kAREasingCurveBackEaseInOut = ^CGFloat(CGFloat t){ 45 | if(t < 0.5) 46 | { 47 | CGFloat f = 2 * t; 48 | return 0.5 * (f * f * f - f * sin(f * M_PI)); 49 | } 50 | else 51 | { 52 | CGFloat f = (1 - (2*t - 1)); 53 | return 0.5 * (1 - (f * f * f - f * sin(f * M_PI))) + 0.5; 54 | } 55 | }; 56 | 57 | AREasingCurve const kAREasingCurveBounceOut = ^CGFloat(CGFloat t){ 58 | if(t < 4/11.0){ 59 | return (121 * t * t)/16.0; 60 | } else if(t < 8/11.0){ 61 | return (363/40.0 * t * t) - (99/10.0 * t) + 17/5.0; 62 | }else if(t < 9/10.0){ 63 | return (4356/361.0 * t * t) - (35442/1805.0 * t) + 16061/1805.0; 64 | }else{ 65 | return (54/5.0 * t * t) - (513/25.0 * t) + 268/25.0; 66 | } 67 | }; 68 | 69 | AREasingCurve const kAREasingCurveBounceIn = ^CGFloat(CGFloat t){ 70 | return 1 - kAREasingCurveBounceOut(1 - t); 71 | }; 72 | 73 | AREasingCurve const kAREasingCurveBounceInOut = ^CGFloat(CGFloat t){ 74 | if(t < 0.5) 75 | { 76 | return 0.5 * kAREasingCurveBounceIn(t*2); 77 | } 78 | else 79 | { 80 | return 0.5 * kAREasingCurveBounceOut(t * 2 - 1) + 0.5; 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /Source/ARInterpolation.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARValueFunction.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "AREasingCurveFunction.h" 10 | #import "ARAnimatableProperty.h" 11 | 12 | typedef id (^ARInterpolation)(id from, id to, CGFloat time, AREasingCurve easing); 13 | 14 | /** 15 | * @brief get the special interpolation for keyPath 16 | * 17 | * @param path animatable keyPath of ARAnimation 18 | * 19 | * @return the Interpolation 20 | */ 21 | ARInterpolation InterpolationForKeyPath(NSString *path); -------------------------------------------------------------------------------- /Source/ARSpringAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARSpringAnimation.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/20. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARBasicAnimation.h" 10 | 11 | @interface ARSpringAnimation : ARBasicAnimation 12 | 13 | @property (nonatomic, assign) CGFloat damping;// > 0 default 10 14 | @property (nonatomic, assign) CGFloat mass;// > 0 default 1 15 | @property (nonatomic, assign) CGFloat stiffness;// > 0 deafault 100 16 | @property (nonatomic, assign) CGFloat initialVelocity; //default 0 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Source/ARSpringAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARSpringAnimation.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/20. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARSpringAnimation.h" 10 | 11 | @implementation ARSpringAnimation 12 | 13 | + (instancetype)animationWithKeyPath:(NSString *)path { 14 | ARSpringAnimation *animation = [super animationWithKeyPath:path]; 15 | animation.damping = 10; 16 | animation.initialVelocity = 0; 17 | animation.stiffness = 100; 18 | animation.mass = 1; 19 | animation.easing = [animation easing]; 20 | 21 | return animation; 22 | } 23 | 24 | - (NSString *)calculationMode { 25 | return kCAAnimationLinear; 26 | } 27 | 28 | - (AREasingCurve)easing { 29 | 30 | CGFloat b = self.damping; 31 | CGFloat m = self.mass; 32 | CGFloat k = self.stiffness; 33 | CGFloat v0 = self.initialVelocity; 34 | 35 | NSParameterAssert(m > 0); 36 | NSParameterAssert(k > 0); 37 | NSParameterAssert(b > 0); 38 | 39 | CGFloat beta = b / (2 * m); 40 | CGFloat omega0 = sqrtf(k / m); 41 | CGFloat omega1 = sqrtf((omega0 * omega0) - (beta * beta)); 42 | CGFloat omega2 = sqrtf((beta * beta) - (omega0 * omega0)); 43 | 44 | CGFloat x0 = -1; 45 | 46 | if (beta > omega0) 47 | beta = omega0; 48 | 49 | CGFloat (^oscillation)(CGFloat); 50 | if (beta < omega0) { 51 | // Underdamped 52 | oscillation = ^(CGFloat t) { 53 | CGFloat envelope = expf(-beta * t); 54 | 55 | return -x0 + envelope * (x0 * cosf(omega1 * t) + ((beta * x0 + v0) / omega1) * sinf(omega1 * t)); 56 | }; 57 | } else if (beta == omega0) { 58 | // Critically damped 59 | oscillation = ^(CGFloat t) { 60 | CGFloat envelope = expf(-beta * t); 61 | 62 | return -x0 + envelope * (x0 + (beta * x0 + v0) * t); 63 | }; 64 | } else { 65 | // Overdamped 66 | oscillation = ^(CGFloat t) { 67 | CGFloat envelope = expf(-beta * t); 68 | 69 | return -x0 + envelope * (x0 * coshf(omega2 * t) + ((beta * x0 + v0) / omega2) * sinhf(omega2 * t)); 70 | }; 71 | } 72 | 73 | return oscillation; 74 | } 75 | 76 | - (id)copyWithZone:(NSZone *)zone { 77 | ARSpringAnimation *copy = [super copyWithZone:zone]; 78 | copy->_damping = _damping; 79 | copy->_stiffness = _stiffness; 80 | copy->_mass = _mass; 81 | copy->_initialVelocity = _initialVelocity; 82 | copy.easing = self.easing; 83 | return copy; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Source/ArInterpolation.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARValueFunction.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/19. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "ARInterpolation.h" 10 | #import 11 | 12 | //convenient method for float caculation 13 | CGFloat ARFloatInterpolation(CGFloat from, CGFloat to, CGFloat time, AREasingCurve easing) { 14 | CGFloat differ = to - from; 15 | return from + differ * easing(time); 16 | } 17 | 18 | 19 | ARInterpolation const ARNumberInterpolation = ^NSNumber *(NSNumber *from, NSNumber *to, CGFloat time, AREasingCurve easing) { 20 | CGFloat f = [from floatValue]; 21 | CGFloat t = [to floatValue]; 22 | CGFloat des = ARFloatInterpolation(f, t, time, easing); 23 | return [NSNumber numberWithDouble:des]; 24 | }; 25 | 26 | ARInterpolation const ARPointInterpolation = ^NSValue *(NSValue *from, NSValue *to, CGFloat time, AREasingCurve easing) { 27 | CGPoint f = [from CGPointValue]; 28 | CGPoint t = [to CGPointValue]; 29 | CGFloat desX = ARFloatInterpolation(f.x, t.x, time, easing); 30 | CGFloat desY = ARFloatInterpolation(f.y, t.y, time, easing); 31 | CGPoint des = CGPointMake(desX, desY); 32 | return [NSValue valueWithCGPoint:des]; 33 | }; 34 | 35 | ARInterpolation const ARBoundsInterpolation = ^NSValue *(NSValue *from, NSValue *to, CGFloat time, AREasingCurve easing) { 36 | CGRect f = [from CGRectValue]; 37 | CGRect t = [to CGRectValue]; 38 | CGFloat desX = ARFloatInterpolation(f.origin.x, t.origin.x, time, easing); 39 | CGFloat desY = ARFloatInterpolation(f.origin.y, t.origin.y, time, easing); 40 | CGFloat desW = ARFloatInterpolation(f.size.width, t.size.width, time, easing); 41 | CGFloat desH = ARFloatInterpolation(f.size.height, t.size.height, time, easing); 42 | 43 | CGRect frame = CGRectMake(desX, desY, desW, desH); 44 | return [NSValue valueWithCGRect:frame]; 45 | }; 46 | 47 | ARInterpolation const ARColorInterpolation = ^id (UIColor *from, UIColor *to, CGFloat time, AREasingCurve easing) { 48 | CGFloat fromHue = 0.0f; 49 | CGFloat fromSaturation = 0.0f; 50 | CGFloat fromBrightness = 0.0f; 51 | CGFloat fromAlpha = 0.0f; 52 | 53 | [from getHue:&fromHue saturation:&fromSaturation brightness:&fromBrightness alpha:&fromAlpha]; 54 | 55 | CGFloat toHue = 0.0f; 56 | CGFloat toSaturation = 0.0f; 57 | CGFloat toBrightness = 0.0f; 58 | CGFloat toAlpha = 0.0f; 59 | 60 | [to getHue:&toHue saturation:&toSaturation brightness:&toBrightness alpha:&toAlpha]; 61 | 62 | CGFloat desHue = ARFloatInterpolation(fromHue, toHue, time, easing); 63 | CGFloat desSaturation = ARFloatInterpolation(fromSaturation, toSaturation, time, easing); 64 | CGFloat desBrightness = ARFloatInterpolation(fromBrightness, toBrightness, time, easing); 65 | CGFloat desAlpha = ARFloatInterpolation(toAlpha, toAlpha, time, easing); 66 | 67 | UIColor *color = [UIColor colorWithHue:desHue saturation:desSaturation brightness:desBrightness alpha:desAlpha]; 68 | return (__bridge id)color.CGColor; 69 | }; 70 | 71 | 72 | ARInterpolation InterpolationForKeyPath(NSString *path) { 73 | static NSDictionary *dict = nil; 74 | static dispatch_once_t onceToken; 75 | dispatch_once(&onceToken, ^{ 76 | dict = @{kARLayerCornerRadius:ARNumberInterpolation, 77 | kARLayerPositionY:ARNumberInterpolation, 78 | kARLayerPositionX:ARNumberInterpolation, 79 | kARLayerZPositoin:ARNumberInterpolation, 80 | kARLayerScaleY:ARNumberInterpolation, 81 | kARLayerScaleX:ARNumberInterpolation, 82 | kARLayerScale:ARNumberInterpolation, 83 | kARLayerBorderWidth:ARNumberInterpolation, 84 | kARLayerPosition:ARPointInterpolation, 85 | kARLayerBounds:ARBoundsInterpolation, 86 | kARLayerBackgroundColor:ARColorInterpolation, 87 | kARLayerOpacity:ARNumberInterpolation, 88 | kARLayerRotationX:ARNumberInterpolation, 89 | kARLayerRotationY:ARNumberInterpolation, 90 | kARLayerRotation:ARNumberInterpolation, 91 | kARLayerAnchorPoint:ARPointInterpolation, 92 | kARShapeLayerStrokeEnd:ARNumberInterpolation, 93 | kARShapeLayerStrokeStart:ARNumberInterpolation}; 94 | }); 95 | return dict[path]; 96 | } -------------------------------------------------------------------------------- /Source/CALayer+ARAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+ARAnimation.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/23. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface CALayer (ARAnimation) 13 | 14 | @property (nonatomic, assign) CGFloat scaleX; 15 | @property (nonatomic, assign) CGFloat scaleY; 16 | @property (nonatomic, assign) CGFloat scale; 17 | 18 | @property (nonatomic, assign) CGFloat rotationX; 19 | @property (nonatomic, assign) CGFloat rotationY; 20 | @property (nonatomic, assign) CGFloat rotation; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Source/CALayer+ARAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+ARAnimation.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/23. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "CALayer+ARAnimation.h" 10 | #import 11 | 12 | #import "ARAnimatableProperty.h" 13 | 14 | @implementation CALayer (ARAnimation) 15 | 16 | @dynamic scaleX; 17 | @dynamic scaleY; 18 | @dynamic scale; 19 | @dynamic rotationX; 20 | @dynamic rotationY; 21 | @dynamic rotation; 22 | 23 | - (void)setScaleX:(CGFloat)scaleX { 24 | [self setValue:@(scaleX) forKeyPath:kARLayerScaleX]; 25 | } 26 | 27 | - (void)setScaleY:(CGFloat)scaleY { 28 | [self setValue:@(scaleY) forKeyPath:kARLayerScaleY]; 29 | } 30 | 31 | - (void)setScale:(CGFloat)scale { 32 | [self setValue:@(scale) forKeyPath:kARLayerScale]; 33 | } 34 | 35 | - (void)setRotationX:(CGFloat)rotationX { 36 | [self setValue:@(rotationX) forKey:ARLayerActionEventStoreKey(kARLayerRotationX)]; 37 | [self setValue:@(rotationX) forKeyPath:kARLayerRotationX]; 38 | } 39 | 40 | - (void)setRotationY:(CGFloat)rotationY { 41 | [self setValue:@(rotationY) forKey:ARLayerActionEventStoreKey(kARLayerRotationY)]; 42 | [self setValue:@(rotationY) forKeyPath:kARLayerRotationY]; 43 | } 44 | 45 | - (void)setRotation:(CGFloat)rotation { 46 | [self setValue:@(rotation) forKey:ARLayerActionEventStoreKey(kARLayerRotation)]; 47 | [self setValue:@(rotation) forKeyPath:kARLayerRotation]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Source/UIView+ARAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ARAnimation.h 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/21. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AREasingCurveFunction.h" 11 | 12 | @interface UIView (ARAnimation) 13 | 14 | // basic 15 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 16 | animations:(void (^)(void))animations; 17 | 18 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 19 | animations:(void (^)(void))animations 20 | completion:(void (^)(void))completion; 21 | 22 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 23 | delay:(CFTimeInterval)delay 24 | animations:(void (^)(void))animations 25 | completion:(void (^)(void))completion; 26 | 27 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 28 | delay:(CFTimeInterval)delay 29 | easing:(AREasingCurve)easing 30 | animations:(void (^)(void))animations 31 | completion:(void (^)(void))completion; 32 | 33 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 34 | delay:(CFTimeInterval)delay 35 | repeatCount:(NSUInteger)repeatCount 36 | autoreverses:(BOOL)autoreverses 37 | easing:(AREasingCurve)easing 38 | animations:(void (^)(void))animations 39 | completion:(void (^)(void))completion; 40 | 41 | // spring 42 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 43 | animations:(void (^)(void))animations; 44 | 45 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 46 | animations:(void (^)(void))animations 47 | completion:(void (^)(void))completion; 48 | 49 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 50 | delay:(CFTimeInterval)delay 51 | animations:(void (^)(void))animations 52 | completion:(void (^)(void))completion; 53 | 54 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 55 | delay:(CFTimeInterval)delay 56 | mass:(CGFloat)mass 57 | damping:(CGFloat)damping 58 | stiffness:(CGFloat)stiffness 59 | initialVelocity:(CGFloat)initialVelocity 60 | animations:(void (^)(void))animations 61 | completion:(void (^)(void))completion; 62 | 63 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 64 | delay:(CFTimeInterval)delay 65 | repeatCount:(NSUInteger)repeatCount 66 | autoreverses:(BOOL)autoreverses 67 | mass:(CGFloat)mass 68 | damping:(CGFloat)damping 69 | stiffness:(CGFloat)stiffness 70 | initialVelocity:(CGFloat)initialVelocity 71 | animations:(void (^)(void))animations 72 | completion:(void (^)(void))completion; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Source/UIView+ARAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ARAnimation.m 3 | // ARAnimationDemo 4 | // 5 | // Created by AugustRush on 15/10/21. 6 | // Copyright © 2015年 AugustRush. All rights reserved. 7 | // 8 | 9 | #import "UIView+ARAnimation.h" 10 | #import 11 | #import "ARBasicAnimation.h" 12 | #import "ARSpringAnimation.h" 13 | 14 | static void *AR_currentAnimationContext = NULL; 15 | static void *AR_animationContext = &AR_animationContext; 16 | 17 | NSString *const kARBlockAnimationContextKey = @"kARBlockAnimationContextKey"; 18 | 19 | /** 20 | * @brief info 21 | */ 22 | @interface ARAnimationInfo : NSObject 23 | 24 | @property(nonatomic, weak) CALayer *layer; 25 | @property(nonatomic, copy) NSString *event; 26 | @property(nonatomic, strong) id fromValue; 27 | 28 | @end 29 | 30 | @implementation ARAnimationInfo 31 | 32 | @end 33 | 34 | /** 35 | * @brief context 36 | */ 37 | @interface ARBlockAnimationContext : NSObject 38 | 39 | @property(nonatomic, assign) CFTimeInterval delay; 40 | @property(nonatomic, strong, readonly) 41 | NSMutableArray *animationInfos; 42 | 43 | @end 44 | 45 | @implementation ARBlockAnimationContext 46 | 47 | - (instancetype)init { 48 | self = [super init]; 49 | if (self) { 50 | _animationInfos = [NSMutableArray array]; 51 | } 52 | return self; 53 | } 54 | 55 | @end 56 | 57 | @implementation UIView (ARAnimation) 58 | 59 | #pragma mark - swizzle methods 60 | 61 | + (void)initialize { 62 | static dispatch_once_t onceToken; 63 | dispatch_once(&onceToken, ^{ 64 | [self swizzleMethods]; 65 | }); 66 | } 67 | 68 | + (void)swizzleMethods { 69 | SEL originalSelector = @selector(actionForLayer:forKey:); 70 | SEL extendedSelector = @selector(AR_actionForLayer:forKey:); 71 | 72 | Method originalMethod = class_getInstanceMethod(self, originalSelector); 73 | Method extendedMethod = class_getInstanceMethod(self, extendedSelector); 74 | 75 | if (class_addMethod(self, originalSelector, 76 | method_getImplementation(extendedMethod), 77 | method_getTypeEncoding(extendedMethod))) { 78 | class_replaceMethod(self, extendedSelector, 79 | method_getImplementation(originalMethod), 80 | method_getTypeEncoding(originalMethod)); 81 | } else { 82 | method_exchangeImplementations(originalMethod, extendedMethod); 83 | } 84 | } 85 | 86 | - (id)AR_actionForLayer:(CALayer *)layer forKey:(NSString *)event { 87 | if (AR_currentAnimationContext == AR_animationContext) { 88 | // NSLog(@"event is %@",event); 89 | if ([ARAllAnimatablePropertys() containsObject:event]) { 90 | ARBlockAnimationContext *context = 91 | [CATransaction valueForKey:kARBlockAnimationContextKey]; 92 | ARAnimationInfo *info = [[ARAnimationInfo alloc] init]; 93 | info.layer = layer; 94 | info.event = event; 95 | if ([event isEqualToString:kARLayerBackgroundColor]) { 96 | CGColorRef from = (__bridge CGColorRef)([layer valueForKeyPath:event]); 97 | info.fromValue = [UIColor colorWithCGColor:from]; 98 | } else { 99 | info.fromValue = [layer valueForKeyPath:event]; 100 | } 101 | 102 | [context.animationInfos addObject:info]; 103 | } 104 | 105 | return (id)[NSNull null]; 106 | } 107 | 108 | return [self AR_actionForLayer:layer forKey:event]; 109 | } 110 | 111 | #pragma mark - public methods 112 | 113 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 114 | animations:(void (^)(void))animations { 115 | [self AR_animationWithDuration:duration animations:animations completion:nil]; 116 | } 117 | 118 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 119 | animations:(void (^)(void))animations 120 | completion:(void (^)(void))completion { 121 | [self AR_animationWithDuration:duration 122 | delay:0 123 | animations:animations 124 | completion:completion]; 125 | } 126 | 127 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 128 | delay:(CFTimeInterval)delay 129 | animations:(void (^)(void))animations 130 | completion:(void (^)(void))completion { 131 | [self AR_animationWithDuration:duration 132 | delay:delay 133 | easing:kAREasingCurveLinear 134 | animations:animations 135 | completion:completion]; 136 | } 137 | 138 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 139 | delay:(CFTimeInterval)delay 140 | easing:(AREasingCurve)easing 141 | animations:(void (^)(void))animations 142 | completion:(void (^)(void))completion { 143 | [self AR_animationWithDuration:duration 144 | delay:delay 145 | repeatCount:0 146 | autoreverses:NO 147 | easing:easing 148 | animations:animations 149 | completion:completion]; 150 | } 151 | 152 | + (void)AR_animationWithDuration:(NSTimeInterval)duration 153 | delay:(CFTimeInterval)delay 154 | repeatCount:(NSUInteger)repeatCount 155 | autoreverses:(BOOL)autoreverses 156 | easing:(AREasingCurve)easing 157 | animations:(void (^)(void))animations 158 | completion:(void (^)(void))completion { 159 | [CATransaction lock]; 160 | [CATransaction begin]; 161 | [CATransaction setDisableActions:NO]; 162 | [CATransaction setCompletionBlock:completion]; 163 | 164 | AR_currentAnimationContext = AR_animationContext; 165 | ARBlockAnimationContext *context = [[ARBlockAnimationContext alloc] init]; 166 | context.delay = delay; 167 | [CATransaction setValue:context forKey:kARBlockAnimationContextKey]; 168 | animations(); 169 | AR_currentAnimationContext = NULL; 170 | [self addBasicAnimationsWithContext:context 171 | easing:easing 172 | duration:duration 173 | repeatCount:repeatCount 174 | autoreverses:autoreverses]; 175 | 176 | [CATransaction commit]; 177 | [CATransaction unlock]; 178 | } 179 | 180 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 181 | animations:(void (^)(void))animations { 182 | [self AR_springAnimationWithDuration:duration 183 | animations:animations 184 | completion:nil]; 185 | } 186 | 187 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 188 | animations:(void (^)(void))animations 189 | completion:(void (^)(void))completion { 190 | [self AR_springAnimationWithDuration:duration 191 | delay:0.0 192 | animations:animations 193 | completion:completion]; 194 | } 195 | 196 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 197 | delay:(CFTimeInterval)delay 198 | animations:(void (^)(void))animations 199 | completion:(void (^)(void))completion { 200 | [self AR_springAnimationWithDuration:duration 201 | delay:delay 202 | mass:1 203 | damping:10 204 | stiffness:100 205 | initialVelocity:0 206 | animations:animations 207 | completion:completion]; 208 | } 209 | 210 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 211 | delay:(CFTimeInterval)delay 212 | mass:(CGFloat)mass 213 | damping:(CGFloat)damping 214 | stiffness:(CGFloat)stiffness 215 | initialVelocity:(CGFloat)initialVelocity 216 | animations:(void (^)(void))animations 217 | completion:(void (^)(void))completion { 218 | [self AR_springAnimationWithDuration:duration 219 | delay:delay 220 | repeatCount:0 221 | autoreverses:NO 222 | mass:mass 223 | damping:damping 224 | stiffness:stiffness 225 | initialVelocity:initialVelocity 226 | animations:animations 227 | completion:completion]; 228 | } 229 | 230 | + (void)AR_springAnimationWithDuration:(NSTimeInterval)duration 231 | delay:(CFTimeInterval)delay 232 | repeatCount:(NSUInteger)repeatCount 233 | autoreverses:(BOOL)autoreverses 234 | mass:(CGFloat)mass 235 | damping:(CGFloat)damping 236 | stiffness:(CGFloat)stiffness 237 | initialVelocity:(CGFloat)initialVelocity 238 | animations:(void (^)(void))animations 239 | completion:(void (^)(void))completion { 240 | [CATransaction lock]; 241 | [CATransaction begin]; 242 | [CATransaction setDisableActions:NO]; 243 | [CATransaction setCompletionBlock:completion]; 244 | 245 | AR_currentAnimationContext = AR_animationContext; 246 | ARBlockAnimationContext *context = [[ARBlockAnimationContext alloc] init]; 247 | context.delay = delay; 248 | [CATransaction setValue:context forKey:kARBlockAnimationContextKey]; 249 | animations(); 250 | AR_currentAnimationContext = NULL; 251 | [self addSpringAnimationsWithContext:context 252 | duration:duration 253 | mass:mass 254 | damping:damping 255 | stiffness:stiffness 256 | initialVelocity:initialVelocity 257 | repeatCount:repeatCount 258 | autoreverses:autoreverses]; 259 | 260 | [CATransaction commit]; 261 | [CATransaction unlock]; 262 | } 263 | 264 | #pragma mark - private methods 265 | 266 | + (void)addBasicAnimationsWithContext:(ARBlockAnimationContext *)context 267 | easing:(AREasingCurve)easing 268 | duration:(CFTimeInterval)duration 269 | repeatCount:(NSUInteger)repeatCount 270 | autoreverses:(BOOL)autoreverses { 271 | [context.animationInfos 272 | enumerateObjectsUsingBlock:^(ARAnimationInfo *_Nonnull info, 273 | NSUInteger idx, BOOL *_Nonnull stop) { 274 | ARBasicAnimation *basic = 275 | [ARBasicAnimation animationWithKeyPath:info.event]; 276 | basic.fromValue = info.fromValue; 277 | NSString *key = ARLayerActionEventStoreKey(info.event); 278 | if ([info.event isEqualToString:kARLayerBackgroundColor]) { 279 | CGColorRef color = 280 | (__bridge CGColorRef)([info.layer valueForKeyPath:key]); 281 | basic.toValue = [UIColor colorWithCGColor:color]; 282 | } else { 283 | basic.toValue = [info.layer valueForKeyPath:key]; 284 | } 285 | basic.easing = [easing copy]; 286 | basic.duration = duration; 287 | basic.repeatCount = repeatCount; 288 | basic.autoreverses = autoreverses; 289 | basic.fillMode = kCAFillModeBoth; 290 | basic.beginTime = CACurrentMediaTime() + context.delay; 291 | 292 | [info.layer addAnimation:basic forKey:nil]; 293 | }]; 294 | } 295 | 296 | + (void)addSpringAnimationsWithContext:(ARBlockAnimationContext *)context 297 | duration:(CFTimeInterval)duration 298 | mass:(CGFloat)mass 299 | damping:(CGFloat)damping 300 | stiffness:(CGFloat)stiffness 301 | initialVelocity:(CGFloat)initialVelocity 302 | repeatCount:(NSUInteger)repeatCount 303 | autoreverses:(BOOL)autoreverses { 304 | 305 | [context.animationInfos 306 | enumerateObjectsUsingBlock:^(ARAnimationInfo *_Nonnull info, 307 | NSUInteger idx, BOOL *_Nonnull stop) { 308 | ARSpringAnimation *spring = 309 | [ARSpringAnimation animationWithKeyPath:info.event]; 310 | spring.fromValue = info.fromValue; 311 | NSString *key = ARLayerActionEventStoreKey(info.event); 312 | if ([info.event isEqualToString:kARLayerBackgroundColor]) { 313 | CGColorRef color = 314 | (__bridge CGColorRef)([info.layer valueForKeyPath:key]); 315 | spring.toValue = [UIColor colorWithCGColor:color]; 316 | } else { 317 | spring.toValue = [info.layer valueForKeyPath:key]; 318 | } 319 | spring.mass = mass; 320 | spring.initialVelocity = initialVelocity; 321 | spring.damping = damping; 322 | spring.stiffness = stiffness; 323 | spring.duration = duration; 324 | spring.repeatCount = repeatCount; 325 | spring.autoreverses = autoreverses; 326 | spring.fillMode = kCAFillModeBoth; 327 | spring.beginTime = CACurrentMediaTime() + context.delay; 328 | 329 | [info.layer addAnimation:spring forKey:nil]; 330 | }]; 331 | } 332 | 333 | @end 334 | -------------------------------------------------------------------------------- /ex1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/ARAnimation/342628475c848e73d04df5543d487b77a8979b83/ex1.gif -------------------------------------------------------------------------------- /rotaion.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/ARAnimation/342628475c848e73d04df5543d487b77a8979b83/rotaion.gif -------------------------------------------------------------------------------- /title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustRush/ARAnimation/342628475c848e73d04df5543d487b77a8979b83/title.png --------------------------------------------------------------------------------