├── .DS_Store ├── .gitattributes ├── .gitignore ├── README.md ├── YTAnimationDemo.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── YTAnimationDemo ├── .DS_Store ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Like-Blue.imageset │ │ ├── Contents.json │ │ └── Like-Blue@2x.png │ ├── Like.imageset │ │ ├── Contents.json │ │ └── Like@2x.png │ ├── Sparkle.imageset │ │ ├── Contents.json │ │ └── Sparkle.png │ ├── chooser-button-input-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-button-input-highlighted@2x.png │ ├── chooser-button-input.imageset │ │ ├── Contents.json │ │ └── chooser-button-input@2x.png │ ├── chooser-button-tab-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-button-tab-highlighted@2x.png │ ├── chooser-button-tab.imageset │ │ ├── Contents.json │ │ └── chooser-button-tab@2x.png │ ├── chooser-moment-button-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-moment-button-highlighted@2x.png │ ├── chooser-moment-button.imageset │ │ ├── Contents.json │ │ └── chooser-moment-button@2x.png │ ├── chooser-moment-icon-camera-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-camera-highlighted@2x.png │ ├── chooser-moment-icon-camera.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-camera@2x.png │ ├── chooser-moment-icon-music-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-music-highlighted@2x.png │ ├── chooser-moment-icon-music.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-music@2x.png │ ├── chooser-moment-icon-place-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-place-highlighted@2x.png │ ├── chooser-moment-icon-place.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-place@2x.png │ ├── chooser-moment-icon-sleep-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-sleep-highlighted@2x.png │ ├── chooser-moment-icon-sleep.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-sleep@2x.png │ ├── chooser-moment-icon-thought-highlighted.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-thought-highlighted@2x.png │ └── chooser-moment-icon-thought.imageset │ │ ├── Contents.json │ │ └── chooser-moment-icon-thought@2x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Base │ ├── BaseConst.swift │ └── YTBaseViewController.swift ├── Info.plist ├── SnapKit │ ├── .gitignore │ ├── .swift-version │ ├── .travis.yml │ ├── Constraint.swift │ ├── ConstraintAttributes.swift │ ├── ConstraintConfig.swift │ ├── ConstraintConstantTarget.swift │ ├── ConstraintDSL.swift │ ├── ConstraintDescription.swift │ ├── ConstraintInsetTarget.swift │ ├── ConstraintInsets.swift │ ├── ConstraintItem.swift │ ├── ConstraintLayoutGuide.swift │ ├── ConstraintLayoutGuideDSL.swift │ ├── ConstraintLayoutSupport.swift │ ├── ConstraintLayoutSupportDSL.swift │ ├── ConstraintMaker.swift │ ├── ConstraintMakerEditable.swift │ ├── ConstraintMakerExtendable.swift │ ├── ConstraintMakerFinalizable.swift │ ├── ConstraintMakerPriortizable.swift │ ├── ConstraintMakerRelatable.swift │ ├── ConstraintMultiplierTarget.swift │ ├── ConstraintOffsetTarget.swift │ ├── ConstraintPriorityTarget.swift │ ├── ConstraintRelatableTarget.swift │ ├── ConstraintRelation.swift │ ├── ConstraintView+Extensions.swift │ ├── ConstraintView.swift │ ├── ConstraintViewDSL.swift │ ├── Debugging.swift │ ├── LayoutConstraint.swift │ ├── SnapKit.h │ ├── UILayoutGuide+Extensions.swift │ └── UILayoutSupport+Extensions.swift ├── ViewController.swift ├── YTAnimationDemo-Bridging-Header.h ├── 关键帧动画 │ └── YTKeyFrameAnimationViewController.swift ├── 基础动画 │ └── YTBaseAnimationViewController.swift ├── 组动画 │ └── YTGroupAnimationViewController.swift ├── 过渡动画 │ └── YTTransitionAnimationViewController.swift └── 项目案例 │ ├── .DS_Store │ ├── YTCombinationAnimationViewController.swift │ ├── 弹球 │ ├── .DS_Store │ ├── DCPathButton │ │ ├── DCPathButton.h │ │ ├── DCPathButton.m │ │ ├── DCPathCenterButton.h │ │ ├── DCPathCenterButton.m │ │ ├── DCPathItemButton.h │ │ └── DCPathItemButton.m │ └── Sounds │ │ ├── bloom.caf │ │ ├── fold.caf │ │ └── selected.caf │ ├── 点赞 │ ├── MCFireworksButton.h │ ├── MCFireworksButton.m │ ├── MCFireworksView.h │ └── MCFireworksView.m │ ├── 进度 │ └── YTProgressView.swift │ └── 钉钉 │ ├── DWBubbleMenuButton.h │ └── DWBubbleMenuButton.m └── images ├── tanqiu.gif ├── 抖动.gif ├── 旋转.gif ├── 点赞.gif ├── 组动画2.gif ├── 过渡动画.gif └── 进度条.gif /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | # Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /YTAnimationDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /YTAnimationDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /YTAnimationDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/.DS_Store -------------------------------------------------------------------------------- /YTAnimationDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/23. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | 19 | window = UIWindow.init(frame: kScreenBounds) 20 | window?.makeKeyAndVisible() 21 | 22 | let nav = UINavigationController.init(rootViewController: ViewController()) 23 | window?.rootViewController = nav 24 | 25 | return true 26 | } 27 | 28 | func applicationWillResignActive(_ application: UIApplication) { 29 | // 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. 30 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 31 | } 32 | 33 | func applicationDidEnterBackground(_ application: UIApplication) { 34 | // 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. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | func applicationWillEnterForeground(_ application: UIApplication) { 39 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | func applicationDidBecomeActive(_ application: UIApplication) { 43 | // 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. 44 | } 45 | 46 | func applicationWillTerminate(_ application: UIApplication) { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Like-Blue.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Like-Blue@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Like-Blue.imageset/Like-Blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/Like-Blue.imageset/Like-Blue@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Like.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "Like@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Like.imageset/Like@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/Like.imageset/Like@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Sparkle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Sparkle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/Sparkle.imageset/Sparkle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/Sparkle.imageset/Sparkle.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-input-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-button-input-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-input-highlighted.imageset/chooser-button-input-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-button-input-highlighted.imageset/chooser-button-input-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-input.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-button-input@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-input.imageset/chooser-button-input@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-button-input.imageset/chooser-button-input@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-tab-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-button-tab-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-tab-highlighted.imageset/chooser-button-tab-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-button-tab-highlighted.imageset/chooser-button-tab-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-tab.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-button-tab@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-button-tab.imageset/chooser-button-tab@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-button-tab.imageset/chooser-button-tab@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-button-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-button-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-button-highlighted.imageset/chooser-moment-button-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-button-highlighted.imageset/chooser-moment-button-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-button.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-button@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-button.imageset/chooser-moment-button@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-button.imageset/chooser-moment-button@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-camera-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-camera-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-camera-highlighted.imageset/chooser-moment-icon-camera-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-camera-highlighted.imageset/chooser-moment-icon-camera-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-camera.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-camera@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-camera.imageset/chooser-moment-icon-camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-camera.imageset/chooser-moment-icon-camera@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-music-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-music-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-music-highlighted.imageset/chooser-moment-icon-music-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-music-highlighted.imageset/chooser-moment-icon-music-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-music.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-music@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-music.imageset/chooser-moment-icon-music@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-music.imageset/chooser-moment-icon-music@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-place-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-place-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-place-highlighted.imageset/chooser-moment-icon-place-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-place-highlighted.imageset/chooser-moment-icon-place-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-place.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-place@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-place.imageset/chooser-moment-icon-place@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-place.imageset/chooser-moment-icon-place@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-sleep-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-sleep-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-sleep-highlighted.imageset/chooser-moment-icon-sleep-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-sleep-highlighted.imageset/chooser-moment-icon-sleep-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-sleep.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-sleep@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-sleep.imageset/chooser-moment-icon-sleep@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-sleep.imageset/chooser-moment-icon-sleep@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-thought-highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-thought-highlighted@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-thought-highlighted.imageset/chooser-moment-icon-thought-highlighted@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-thought-highlighted.imageset/chooser-moment-icon-thought-highlighted@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-thought.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "chooser-moment-icon-thought@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /YTAnimationDemo/Assets.xcassets/chooser-moment-icon-thought.imageset/chooser-moment-icon-thought@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/Assets.xcassets/chooser-moment-icon-thought.imageset/chooser-moment-icon-thought@2x.png -------------------------------------------------------------------------------- /YTAnimationDemo/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 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /YTAnimationDemo/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 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /YTAnimationDemo/Base/BaseConst.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseConst.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/24. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let kScreenW = UIScreen.main.bounds.size.width 12 | let kScreenH = UIScreen.main.bounds.size.height 13 | let kScreenBounds = UIScreen.main.bounds 14 | let iPhoneXBottemHei:CGFloat = UIDevice.current.isX() == true ? 34.0 : 0 15 | let kNavigationBarHei:CGFloat = 64.0 + (UIDevice.current.isX() == true ? 24.0 : 0) 16 | let kBottomBarHei:CGFloat = 49.0 + iPhoneXBottemHei 17 | 18 | extension UIDevice { 19 | public func isX() -> Bool { 20 | if UIScreen.main.bounds.height == 812 { 21 | return true 22 | } 23 | 24 | return false 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /YTAnimationDemo/Base/YTBaseViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTBaseViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/23. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YTBaseViewController: UIViewController { 12 | 13 | var view_Body: UIView! 14 | var btn_Play: UIButton! 15 | 16 | let margin_Top: CGFloat = 100.0 //位置上移 17 | let margin_ViewWidthHeight: CGFloat = 100.0 //view宽高 18 | let margin_ViewMidPosition: CGFloat = 50.0 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | initMainView() 24 | } 25 | 26 | override func didReceiveMemoryWarning() { 27 | super.didReceiveMemoryWarning() 28 | // Dispose of any resources that can be recreated. 29 | } 30 | 31 | } 32 | 33 | 34 | extension YTBaseViewController{ 35 | 36 | func playBtnClick(btn: UIButton) { 37 | 38 | } 39 | 40 | } 41 | 42 | 43 | // MARK: UI 44 | extension YTBaseViewController{ 45 | 46 | func initMainView() { 47 | 48 | view.backgroundColor = UIColor.white 49 | 50 | view_Body = UIView() 51 | view_Body.backgroundColor = UIColor.red 52 | view.addSubview(view_Body) 53 | view_Body.snp.makeConstraints { (make) in 54 | make.centerX.equalTo(view) 55 | make.centerY.equalTo(view).offset(-margin_Top) 56 | make.width.height.equalTo(margin_ViewWidthHeight) 57 | } 58 | 59 | btn_Play = UIButton.init(type: .custom) 60 | btn_Play.setTitle("开始", for: .normal) 61 | btn_Play.setTitleColor(UIColor.white, for: .normal) 62 | btn_Play.backgroundColor = UIColor.orange 63 | btn_Play.addTarget(self, action: #selector(playBtnClick(btn:)), for: .touchUpInside) 64 | view.addSubview(btn_Play) 65 | btn_Play.snp.makeConstraints { (make) in 66 | make.centerX.equalTo(view) 67 | make.bottom.equalTo(-iPhoneXBottemHei - 80) 68 | make.width.equalTo(150) 69 | make.height.equalTo(44) 70 | } 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /YTAnimationDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/.gitignore: -------------------------------------------------------------------------------- 1 | project.xcworkspace 2 | xcuserdata 3 | Examples/ 4 | .DS_Store 5 | Gemfile 6 | Gemfile.lock 7 | *.sketch 8 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8 3 | 4 | env: 5 | - ACTION=test PLATFORM=Mac DESTINATION='platform=OS X' 6 | - ACTION=test PLATFORM=iOS DESTINATION='platform=iOS Simulator,name=iPhone 6S' 7 | - ACTION=test PLATFORM=tvOS DESTINATION='platform=tvOS Simulator,name=Apple TV 1080p' 8 | 9 | script: 10 | - set -o pipefail && xcodebuild -scheme SnapKit -destination "$DESTINATION" $ACTION | xcpretty 11 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/Constraint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | public class Constraint { 31 | 32 | internal let sourceLocation: (String, UInt) 33 | internal let label: String? 34 | 35 | private let from: ConstraintItem 36 | private let to: ConstraintItem 37 | private let relation: ConstraintRelation 38 | private let multiplier: ConstraintMultiplierTarget 39 | private var constant: ConstraintConstantTarget { 40 | didSet { 41 | self.updateConstantAndPriorityIfNeeded() 42 | } 43 | } 44 | private var priority: ConstraintPriorityTarget { 45 | didSet { 46 | self.updateConstantAndPriorityIfNeeded() 47 | } 48 | } 49 | private var layoutConstraints: [LayoutConstraint] 50 | 51 | // MARK: Initialization 52 | 53 | internal init(from: ConstraintItem, 54 | to: ConstraintItem, 55 | relation: ConstraintRelation, 56 | sourceLocation: (String, UInt), 57 | label: String?, 58 | multiplier: ConstraintMultiplierTarget, 59 | constant: ConstraintConstantTarget, 60 | priority: ConstraintPriorityTarget) { 61 | self.from = from 62 | self.to = to 63 | self.relation = relation 64 | self.sourceLocation = sourceLocation 65 | self.label = label 66 | self.multiplier = multiplier 67 | self.constant = constant 68 | self.priority = priority 69 | self.layoutConstraints = [] 70 | 71 | // get attributes 72 | let layoutFromAttributes = self.from.attributes.layoutAttributes 73 | let layoutToAttributes = self.to.attributes.layoutAttributes 74 | 75 | // get layout from 76 | let layoutFrom: ConstraintView = self.from.view! 77 | 78 | // get relation 79 | let layoutRelation = self.relation.layoutRelation 80 | 81 | for layoutFromAttribute in layoutFromAttributes { 82 | // get layout to attribute 83 | let layoutToAttribute: NSLayoutAttribute 84 | #if os(iOS) || os(tvOS) 85 | if layoutToAttributes.count > 0 { 86 | if self.from.attributes == .edges && self.to.attributes == .margins { 87 | switch layoutFromAttribute { 88 | case .left: 89 | layoutToAttribute = .leftMargin 90 | case .right: 91 | layoutToAttribute = .rightMargin 92 | case .top: 93 | layoutToAttribute = .topMargin 94 | case .bottom: 95 | layoutToAttribute = .bottomMargin 96 | default: 97 | fatalError() 98 | } 99 | } else if self.from.attributes == .margins && self.to.attributes == .edges { 100 | switch layoutFromAttribute { 101 | case .leftMargin: 102 | layoutToAttribute = .left 103 | case .rightMargin: 104 | layoutToAttribute = .right 105 | case .topMargin: 106 | layoutToAttribute = .top 107 | case .bottomMargin: 108 | layoutToAttribute = .bottom 109 | default: 110 | fatalError() 111 | } 112 | } else if self.from.attributes == self.to.attributes { 113 | layoutToAttribute = layoutFromAttribute 114 | } else { 115 | layoutToAttribute = layoutToAttributes[0] 116 | } 117 | } else { 118 | layoutToAttribute = layoutFromAttribute 119 | } 120 | #else 121 | if self.from.attributes == self.to.attributes { 122 | layoutToAttribute = layoutFromAttribute 123 | } else if layoutToAttributes.count > 0 { 124 | layoutToAttribute = layoutToAttributes[0] 125 | } else { 126 | layoutToAttribute = layoutFromAttribute 127 | } 128 | #endif 129 | 130 | // get layout constant 131 | let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute) 132 | 133 | // get layout to 134 | var layoutTo: AnyObject? = self.to.target 135 | 136 | // use superview if possible 137 | if layoutTo == nil && layoutToAttribute != .width && layoutToAttribute != .height { 138 | layoutTo = layoutFrom.superview 139 | } 140 | 141 | // create layout constraint 142 | let layoutConstraint = LayoutConstraint( 143 | item: layoutFrom, 144 | attribute: layoutFromAttribute, 145 | relatedBy: layoutRelation, 146 | toItem: layoutTo, 147 | attribute: layoutToAttribute, 148 | multiplier: self.multiplier.constraintMultiplierTargetValue, 149 | constant: layoutConstant 150 | ) 151 | 152 | // set label 153 | layoutConstraint.label = self.label 154 | 155 | // set priority 156 | layoutConstraint.priority = self.priority.constraintPriorityTargetValue 157 | 158 | // set constraint 159 | layoutConstraint.constraint = self 160 | 161 | // append 162 | self.layoutConstraints.append(layoutConstraint) 163 | } 164 | } 165 | 166 | // MARK: Public 167 | 168 | @available(*, deprecated:3.0, message:"Use activate().") 169 | public func install() { 170 | self.activate() 171 | } 172 | 173 | @available(*, deprecated:3.0, message:"Use deactivate().") 174 | public func uninstall() { 175 | self.deactivate() 176 | } 177 | 178 | public func activate() { 179 | self.activateIfNeeded() 180 | } 181 | 182 | public func deactivate() { 183 | self.deactivateIfNeeded() 184 | } 185 | 186 | @discardableResult 187 | public func update(offset: ConstraintOffsetTarget) -> Constraint { 188 | self.constant = offset.constraintOffsetTargetValue 189 | return self 190 | } 191 | 192 | @discardableResult 193 | public func update(inset: ConstraintInsetTarget) -> Constraint { 194 | self.constant = inset.constraintInsetTargetValue 195 | return self 196 | } 197 | 198 | @discardableResult 199 | public func update(priority: ConstraintPriorityTarget) -> Constraint { 200 | self.priority = priority.constraintPriorityTargetValue 201 | return self 202 | } 203 | 204 | @available(*, deprecated:3.0, message:"Use update(offset: ConstraintOffsetTarget) instead.") 205 | public func updateOffset(amount: ConstraintOffsetTarget) -> Void { self.update(offset: amount) } 206 | 207 | @available(*, deprecated:3.0, message:"Use update(inset: ConstraintInsetTarget) instead.") 208 | public func updateInsets(amount: ConstraintInsetTarget) -> Void { self.update(inset: amount) } 209 | 210 | @available(*, deprecated:3.0, message:"Use update(priority: ConstraintPriorityTarget) instead.") 211 | public func updatePriority(amount: ConstraintPriorityTarget) -> Void { self.update(priority: amount) } 212 | 213 | @available(*, obsoleted:3.0, message:"Use update(priority: ConstraintPriorityTarget) instead.") 214 | public func updatePriorityRequired() -> Void {} 215 | 216 | @available(*, obsoleted:3.0, message:"Use update(priority: ConstraintPriorityTarget) instead.") 217 | public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") } 218 | 219 | @available(*, obsoleted:3.0, message:"Use update(priority: ConstraintPriorityTarget) instead.") 220 | public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") } 221 | 222 | @available(*, obsoleted:3.0, message:"Use update(priority: ConstraintPriorityTarget) instead.") 223 | public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") } 224 | 225 | // MARK: Internal 226 | 227 | internal func updateConstantAndPriorityIfNeeded() { 228 | for layoutConstraint in self.layoutConstraints { 229 | let attribute = (layoutConstraint.secondAttribute == .notAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute 230 | layoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: attribute) 231 | layoutConstraint.priority = self.priority.constraintPriorityTargetValue 232 | } 233 | } 234 | 235 | internal func activateIfNeeded(updatingExisting: Bool = false) { 236 | guard let view = self.from.view else { 237 | print("WARNING: SnapKit failed to get from view from constraint. Activate will be a no-op.") 238 | return 239 | } 240 | let layoutConstraints = self.layoutConstraints 241 | let existingLayoutConstraints = view.snp.constraints.map({ $0.layoutConstraints }).reduce([]) { $0 + $1 } 242 | 243 | if updatingExisting { 244 | for layoutConstraint in layoutConstraints { 245 | let existingLayoutConstraint = existingLayoutConstraints.first { $0 == layoutConstraint } 246 | guard let updateLayoutConstraint = existingLayoutConstraint else { 247 | fatalError("Updated constraint could not find existing matching constraint to update: \(layoutConstraint)") 248 | } 249 | 250 | let updateLayoutAttribute = (updateLayoutConstraint.secondAttribute == .notAnAttribute) ? updateLayoutConstraint.firstAttribute : updateLayoutConstraint.secondAttribute 251 | updateLayoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: updateLayoutAttribute) 252 | } 253 | } else { 254 | NSLayoutConstraint.activate(layoutConstraints) 255 | view.snp.add(constraints: [self]) 256 | } 257 | } 258 | 259 | internal func deactivateIfNeeded() { 260 | guard let view = self.from.view else { 261 | print("WARNING: SnapKit failed to get from view from constraint. Deactivate will be a no-op.") 262 | return 263 | } 264 | let layoutConstraints = self.layoutConstraints 265 | NSLayoutConstraint.deactivate(layoutConstraints) 266 | view.snp.remove(constraints: [self]) 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintAttributes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | internal struct ConstraintAttributes: OptionSet { 32 | 33 | internal init(rawValue: UInt) { 34 | self.rawValue = rawValue 35 | } 36 | internal init(_ rawValue: UInt) { 37 | self.init(rawValue: rawValue) 38 | } 39 | internal init(nilLiteral: ()) { 40 | self.rawValue = 0 41 | } 42 | 43 | internal private(set) var rawValue: UInt 44 | internal static var allZeros: ConstraintAttributes { return self.init(0) } 45 | internal static func convertFromNilLiteral() -> ConstraintAttributes { return self.init(0) } 46 | internal var boolValue: Bool { return self.rawValue != 0 } 47 | 48 | internal func toRaw() -> UInt { return self.rawValue } 49 | internal static func fromRaw(_ raw: UInt) -> ConstraintAttributes? { return self.init(raw) } 50 | internal static func fromMask(_ raw: UInt) -> ConstraintAttributes { return self.init(raw) } 51 | 52 | // normal 53 | 54 | internal static var none: ConstraintAttributes { return self.init(0) } 55 | internal static var left: ConstraintAttributes { return self.init(1) } 56 | internal static var top: ConstraintAttributes { return self.init(2) } 57 | internal static var right: ConstraintAttributes { return self.init(4) } 58 | internal static var bottom: ConstraintAttributes { return self.init(8) } 59 | internal static var leading: ConstraintAttributes { return self.init(16) } 60 | internal static var trailing: ConstraintAttributes { return self.init(32) } 61 | internal static var width: ConstraintAttributes { return self.init(64) } 62 | internal static var height: ConstraintAttributes { return self.init(128) } 63 | internal static var centerX: ConstraintAttributes { return self.init(256) } 64 | internal static var centerY: ConstraintAttributes { return self.init(512) } 65 | internal static var lastBaseline: ConstraintAttributes { return self.init(1024) } 66 | 67 | @available(iOS 8.0, OSX 10.11, *) 68 | internal static var firstBaseline: ConstraintAttributes { return self.init(2048) } 69 | 70 | @available(iOS 8.0, *) 71 | internal static var leftMargin: ConstraintAttributes { return self.init(4096) } 72 | 73 | @available(iOS 8.0, *) 74 | internal static var rightMargin: ConstraintAttributes { return self.init(8192) } 75 | 76 | @available(iOS 8.0, *) 77 | internal static var topMargin: ConstraintAttributes { return self.init(16384) } 78 | 79 | @available(iOS 8.0, *) 80 | internal static var bottomMargin: ConstraintAttributes { return self.init(32768) } 81 | 82 | @available(iOS 8.0, *) 83 | internal static var leadingMargin: ConstraintAttributes { return self.init(65536) } 84 | 85 | @available(iOS 8.0, *) 86 | internal static var trailingMargin: ConstraintAttributes { return self.init(131072) } 87 | 88 | @available(iOS 8.0, *) 89 | internal static var centerXWithinMargins: ConstraintAttributes { return self.init(262144) } 90 | 91 | @available(iOS 8.0, *) 92 | internal static var centerYWithinMargins: ConstraintAttributes { return self.init(524288) } 93 | 94 | // aggregates 95 | 96 | internal static var edges: ConstraintAttributes { return self.init(15) } 97 | internal static var size: ConstraintAttributes { return self.init(192) } 98 | internal static var center: ConstraintAttributes { return self.init(768) } 99 | 100 | @available(iOS 8.0, *) 101 | internal static var margins: ConstraintAttributes { return self.init(61440) } 102 | 103 | @available(iOS 8.0, *) 104 | internal static var centerWithinMargins: ConstraintAttributes { return self.init(786432) } 105 | 106 | internal var layoutAttributes:[NSLayoutAttribute] { 107 | var attrs = [NSLayoutAttribute]() 108 | if (self.contains(ConstraintAttributes.left)) { 109 | attrs.append(.left) 110 | } 111 | if (self.contains(ConstraintAttributes.top)) { 112 | attrs.append(.top) 113 | } 114 | if (self.contains(ConstraintAttributes.right)) { 115 | attrs.append(.right) 116 | } 117 | if (self.contains(ConstraintAttributes.bottom)) { 118 | attrs.append(.bottom) 119 | } 120 | if (self.contains(ConstraintAttributes.leading)) { 121 | attrs.append(.leading) 122 | } 123 | if (self.contains(ConstraintAttributes.trailing)) { 124 | attrs.append(.trailing) 125 | } 126 | if (self.contains(ConstraintAttributes.width)) { 127 | attrs.append(.width) 128 | } 129 | if (self.contains(ConstraintAttributes.height)) { 130 | attrs.append(.height) 131 | } 132 | if (self.contains(ConstraintAttributes.centerX)) { 133 | attrs.append(.centerX) 134 | } 135 | if (self.contains(ConstraintAttributes.centerY)) { 136 | attrs.append(.centerY) 137 | } 138 | if (self.contains(ConstraintAttributes.lastBaseline)) { 139 | attrs.append(.lastBaseline) 140 | } 141 | 142 | #if os(iOS) || os(tvOS) 143 | if (self.contains(ConstraintAttributes.firstBaseline)) { 144 | attrs.append(.firstBaseline) 145 | } 146 | if (self.contains(ConstraintAttributes.leftMargin)) { 147 | attrs.append(.leftMargin) 148 | } 149 | if (self.contains(ConstraintAttributes.rightMargin)) { 150 | attrs.append(.rightMargin) 151 | } 152 | if (self.contains(ConstraintAttributes.topMargin)) { 153 | attrs.append(.topMargin) 154 | } 155 | if (self.contains(ConstraintAttributes.bottomMargin)) { 156 | attrs.append(.bottomMargin) 157 | } 158 | if (self.contains(ConstraintAttributes.leadingMargin)) { 159 | attrs.append(.leadingMargin) 160 | } 161 | if (self.contains(ConstraintAttributes.trailingMargin)) { 162 | attrs.append(.trailingMargin) 163 | } 164 | if (self.contains(ConstraintAttributes.centerXWithinMargins)) { 165 | attrs.append(.centerXWithinMargins) 166 | } 167 | if (self.contains(ConstraintAttributes.centerYWithinMargins)) { 168 | attrs.append(.centerYWithinMargins) 169 | } 170 | #endif 171 | 172 | return attrs 173 | } 174 | } 175 | 176 | internal func + (left: ConstraintAttributes, right: ConstraintAttributes) -> ConstraintAttributes { 177 | return left.union(right) 178 | } 179 | 180 | internal func +=(left: inout ConstraintAttributes, right: ConstraintAttributes) { 181 | left.formUnion(right) 182 | } 183 | 184 | internal func -=(left: inout ConstraintAttributes, right: ConstraintAttributes) { 185 | left.subtract(right) 186 | } 187 | 188 | internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool { 189 | return left.rawValue == right.rawValue 190 | } 191 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection 27 | #else 28 | import AppKit 29 | public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection 30 | #endif 31 | 32 | 33 | public struct ConstraintConfig { 34 | 35 | public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight 36 | 37 | } 38 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintConstantTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintConstantTarget { 32 | } 33 | 34 | extension CGPoint: ConstraintConstantTarget { 35 | } 36 | 37 | extension CGSize: ConstraintConstantTarget { 38 | } 39 | 40 | extension ConstraintInsets: ConstraintConstantTarget { 41 | } 42 | 43 | extension ConstraintConstantTarget { 44 | 45 | internal func constraintConstantTargetValueFor(layoutAttribute: NSLayoutAttribute) -> CGFloat { 46 | if let value = self as? CGFloat { 47 | return value 48 | } 49 | 50 | if let value = self as? Float { 51 | return CGFloat(value) 52 | } 53 | 54 | if let value = self as? Double { 55 | return CGFloat(value) 56 | } 57 | 58 | if let value = self as? Int { 59 | return CGFloat(value) 60 | } 61 | 62 | if let value = self as? UInt { 63 | return CGFloat(value) 64 | } 65 | 66 | if let value = self as? CGSize { 67 | if layoutAttribute == .width { 68 | return value.width 69 | } else if layoutAttribute == .height { 70 | return value.height 71 | } else { 72 | return 0.0 73 | } 74 | } 75 | 76 | if let value = self as? CGPoint { 77 | #if os(iOS) || os(tvOS) 78 | switch layoutAttribute { 79 | case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins: 80 | return value.x 81 | case .top, .bottom, .centerY, .topMargin, .bottomMargin, .centerYWithinMargins, .lastBaseline, .firstBaseline: 82 | return value.y 83 | case .width, .height, .notAnAttribute: 84 | return 0.0 85 | } 86 | #else 87 | switch layoutAttribute { 88 | case .left, .right, .leading, .trailing, .centerX: 89 | return value.x 90 | case .top, .bottom, .centerY, .lastBaseline, .firstBaseline: 91 | return value.y 92 | case .width, .height, .notAnAttribute: 93 | return 0.0 94 | } 95 | #endif 96 | } 97 | 98 | if let value = self as? ConstraintInsets { 99 | #if os(iOS) || os(tvOS) 100 | switch layoutAttribute { 101 | case .left, .leftMargin, .centerX, .centerXWithinMargins: 102 | return value.left 103 | case .top, .topMargin, .centerY, .centerYWithinMargins, .lastBaseline, .firstBaseline: 104 | return value.top 105 | case .right, .rightMargin: 106 | return -value.right 107 | case .bottom, .bottomMargin: 108 | return -value.bottom 109 | case .leading, .leadingMargin: 110 | return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right 111 | case .trailing, .trailingMargin: 112 | return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left 113 | case .width: 114 | return -(value.left + value.right) 115 | case .height: 116 | return -(value.top + value.bottom) 117 | case .notAnAttribute: 118 | return 0.0 119 | } 120 | #else 121 | switch layoutAttribute { 122 | case .left, .centerX: 123 | return value.left 124 | case .top, .centerY, .lastBaseline, .firstBaseline: 125 | return value.top 126 | case .right: 127 | return -value.right 128 | case .bottom: 129 | return -value.bottom 130 | case .leading: 131 | return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : value.right 132 | case .trailing: 133 | return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? -value.right : -value.left 134 | case .width: 135 | return -(value.left + value.right) 136 | case .height: 137 | return -(value.top + value.bottom) 138 | case .notAnAttribute: 139 | return 0.0 140 | } 141 | #endif 142 | } 143 | 144 | return 0.0 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintDSL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintDSL { 32 | 33 | var target: AnyObject? { get } 34 | 35 | func setLabel(_ value: String?) 36 | func label() -> String? 37 | 38 | } 39 | extension ConstraintDSL { 40 | 41 | public func setLabel(_ value: String?) { 42 | objc_setAssociatedObject(self.target, &labelKey, value, .OBJC_ASSOCIATION_COPY_NONATOMIC) 43 | } 44 | public func label() -> String? { 45 | return objc_getAssociatedObject(self.target, &labelKey) as? String 46 | } 47 | 48 | } 49 | private var labelKey: UInt8 = 0 50 | 51 | 52 | public protocol ConstraintAttributesDSL: ConstraintDSL { 53 | } 54 | extension ConstraintAttributesDSL { 55 | 56 | // MARK: Basics 57 | 58 | public var left: ConstraintItem { 59 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left) 60 | } 61 | 62 | public var top: ConstraintItem { 63 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top) 64 | } 65 | 66 | public var right: ConstraintItem { 67 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right) 68 | } 69 | 70 | public var bottom: ConstraintItem { 71 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom) 72 | } 73 | 74 | public var leading: ConstraintItem { 75 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading) 76 | } 77 | 78 | public var trailing: ConstraintItem { 79 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing) 80 | } 81 | 82 | public var width: ConstraintItem { 83 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width) 84 | } 85 | 86 | public var height: ConstraintItem { 87 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height) 88 | } 89 | 90 | public var centerX: ConstraintItem { 91 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX) 92 | } 93 | 94 | public var centerY: ConstraintItem { 95 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY) 96 | } 97 | 98 | public var edges: ConstraintItem { 99 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges) 100 | } 101 | 102 | public var size: ConstraintItem { 103 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size) 104 | } 105 | 106 | public var center: ConstraintItem { 107 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center) 108 | } 109 | 110 | // MARK: Baselines 111 | 112 | @available(*, deprecated:3.0, message:"Use .lastBaseline instead") 113 | public var baseline: ConstraintItem { 114 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline) 115 | } 116 | 117 | @available(iOS 8.0, OSX 10.11, *) 118 | public var lastBaseline: ConstraintItem { 119 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline) 120 | } 121 | 122 | @available(iOS 8.0, OSX 10.11, *) 123 | public var firstBaseline: ConstraintItem { 124 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline) 125 | } 126 | 127 | // MARK: Margins 128 | 129 | @available(iOS 8.0, *) 130 | public var leftMargin: ConstraintItem { 131 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin) 132 | } 133 | 134 | @available(iOS 8.0, *) 135 | public var topMargin: ConstraintItem { 136 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin) 137 | } 138 | 139 | @available(iOS 8.0, *) 140 | public var rightMargin: ConstraintItem { 141 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin) 142 | } 143 | 144 | @available(iOS 8.0, *) 145 | public var bottomMargin: ConstraintItem { 146 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin) 147 | } 148 | 149 | @available(iOS 8.0, *) 150 | public var leadingMargin: ConstraintItem { 151 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin) 152 | } 153 | 154 | @available(iOS 8.0, *) 155 | public var trailingMargin: ConstraintItem { 156 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin) 157 | } 158 | 159 | @available(iOS 8.0, *) 160 | public var centerXWithinMargins: ConstraintItem { 161 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins) 162 | } 163 | 164 | @available(iOS 8.0, *) 165 | public var centerYWithinMargins: ConstraintItem { 166 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins) 167 | } 168 | 169 | @available(iOS 8.0, *) 170 | public var margins: ConstraintItem { 171 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins) 172 | } 173 | 174 | @available(iOS 8.0, *) 175 | public var centerWithinMargins: ConstraintItem { 176 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins) 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintDescription.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintDescription { 32 | 33 | internal let view: ConstraintView 34 | internal var attributes: ConstraintAttributes 35 | internal var relation: ConstraintRelation? = nil 36 | internal var sourceLocation: (String, UInt)? = nil 37 | internal var label: String? = nil 38 | internal var related: ConstraintItem? = nil 39 | internal var multiplier: ConstraintMultiplierTarget = 1.0 40 | internal var constant: ConstraintConstantTarget = 0.0 41 | internal var priority: ConstraintPriorityTarget = 1000.0 42 | internal lazy var constraint: Constraint? = { 43 | guard let relation = self.relation, 44 | let related = self.related, 45 | let sourceLocation = self.sourceLocation else { 46 | return nil 47 | } 48 | let from = ConstraintItem(target: self.view, attributes: self.attributes) 49 | 50 | return Constraint( 51 | from: from, 52 | to: related, 53 | relation: relation, 54 | sourceLocation: sourceLocation, 55 | label: self.label, 56 | multiplier: self.multiplier, 57 | constant: self.constant, 58 | priority: self.priority 59 | ) 60 | }() 61 | 62 | // MARK: Initialization 63 | 64 | internal init(view: ConstraintView, attributes: ConstraintAttributes) { 65 | self.view = view 66 | self.attributes = attributes 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintInsetTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintInsetTarget: ConstraintConstantTarget { 32 | } 33 | 34 | extension Int: ConstraintInsetTarget { 35 | } 36 | 37 | extension UInt: ConstraintInsetTarget { 38 | } 39 | 40 | extension Float: ConstraintInsetTarget { 41 | } 42 | 43 | extension Double: ConstraintInsetTarget { 44 | } 45 | 46 | extension CGFloat: ConstraintInsetTarget { 47 | } 48 | 49 | extension ConstraintInsets: ConstraintInsetTarget { 50 | } 51 | 52 | extension ConstraintInsetTarget { 53 | 54 | internal var constraintInsetTargetValue: ConstraintInsets { 55 | if let amount = self as? ConstraintInsets { 56 | return amount 57 | } else if let amount = self as? Float { 58 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) 59 | } else if let amount = self as? Double { 60 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) 61 | } else if let amount = self as? CGFloat { 62 | return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount) 63 | } else if let amount = self as? Int { 64 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) 65 | } else if let amount = self as? UInt { 66 | return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount)) 67 | } else { 68 | return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0) 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintInsets.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if os(iOS) || os(tvOS) 32 | public typealias ConstraintInsets = UIEdgeInsets 33 | #else 34 | public typealias ConstraintInsets = EdgeInsets 35 | #endif 36 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintItem: Equatable { 32 | 33 | internal weak var target: AnyObject? 34 | internal let attributes: ConstraintAttributes 35 | 36 | internal init(target: AnyObject?, attributes: ConstraintAttributes) { 37 | self.target = target 38 | self.attributes = attributes 39 | } 40 | 41 | internal var view: ConstraintView? { 42 | return self.target as? ConstraintView 43 | } 44 | 45 | } 46 | 47 | public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool { 48 | // pointer equality 49 | guard lhs !== rhs else { 50 | return true 51 | } 52 | 53 | // must both have valid targets and identical attributes 54 | guard let target1 = lhs.target, 55 | let target2 = rhs.target, 56 | target1 === target2 && lhs.attributes == rhs.attributes else { 57 | return false 58 | } 59 | 60 | return true 61 | } 62 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintLayoutGuide.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if os(iOS) || os(tvOS) 32 | @available(iOS 9.0, *) 33 | public typealias ConstraintLayoutGuide = UILayoutGuide 34 | #else 35 | public class ConstraintLayoutGuide {} 36 | #endif 37 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintLayoutGuideDSL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | @available(iOS 9.0, *) 32 | public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL { 33 | 34 | public var target: AnyObject? { 35 | return self.guide 36 | } 37 | 38 | internal let guide: ConstraintLayoutGuide 39 | 40 | internal init(guide: ConstraintLayoutGuide) { 41 | self.guide = guide 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintLayoutSupport.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if os(iOS) || os(tvOS) 32 | @available(iOS 8.0, *) 33 | public typealias ConstraintLayoutSupport = UILayoutSupport 34 | #else 35 | public class ConstraintLayoutSupport {} 36 | #endif 37 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintLayoutSupportDSL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | @available(iOS 8.0, *) 32 | public struct ConstraintLayoutSupportDSL: ConstraintDSL { 33 | 34 | public var target: AnyObject? { 35 | return self.support 36 | } 37 | 38 | internal let support: ConstraintLayoutSupport 39 | 40 | internal init(support: ConstraintLayoutSupport) { 41 | self.support = support 42 | 43 | } 44 | 45 | public var top: ConstraintItem { 46 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top) 47 | } 48 | 49 | public var bottom: ConstraintItem { 50 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom) 51 | } 52 | 53 | public var height: ConstraintItem { 54 | return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMaker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | public class ConstraintMaker { 31 | 32 | public var left: ConstraintMakerExtendable { 33 | return self.makeExtendableWithAttributes(.left) 34 | } 35 | 36 | public var top: ConstraintMakerExtendable { 37 | return self.makeExtendableWithAttributes(.top) 38 | } 39 | 40 | public var bottom: ConstraintMakerExtendable { 41 | return self.makeExtendableWithAttributes(.bottom) 42 | } 43 | 44 | public var right: ConstraintMakerExtendable { 45 | return self.makeExtendableWithAttributes(.right) 46 | } 47 | 48 | public var leading: ConstraintMakerExtendable { 49 | return self.makeExtendableWithAttributes(.leading) 50 | } 51 | 52 | public var trailing: ConstraintMakerExtendable { 53 | return self.makeExtendableWithAttributes(.trailing) 54 | } 55 | 56 | public var width: ConstraintMakerExtendable { 57 | return self.makeExtendableWithAttributes(.width) 58 | } 59 | 60 | public var height: ConstraintMakerExtendable { 61 | return self.makeExtendableWithAttributes(.height) 62 | } 63 | 64 | public var centerX: ConstraintMakerExtendable { 65 | return self.makeExtendableWithAttributes(.centerX) 66 | } 67 | 68 | public var centerY: ConstraintMakerExtendable { 69 | return self.makeExtendableWithAttributes(.centerY) 70 | } 71 | 72 | @available(*, deprecated:3.0, message:"Use lastBaseline instead") 73 | public var baseline: ConstraintMakerExtendable { 74 | return self.makeExtendableWithAttributes(.lastBaseline) 75 | } 76 | 77 | public var lastBaseline: ConstraintMakerExtendable { 78 | return self.makeExtendableWithAttributes(.lastBaseline) 79 | } 80 | 81 | @available(iOS 8.0, OSX 10.11, *) 82 | public var firstBaseline: ConstraintMakerExtendable { 83 | return self.makeExtendableWithAttributes(.firstBaseline) 84 | } 85 | 86 | @available(iOS 8.0, *) 87 | public var leftMargin: ConstraintMakerExtendable { 88 | return self.makeExtendableWithAttributes(.leftMargin) 89 | } 90 | 91 | @available(iOS 8.0, *) 92 | public var rightMargin: ConstraintMakerExtendable { 93 | return self.makeExtendableWithAttributes(.rightMargin) 94 | } 95 | 96 | @available(iOS 8.0, *) 97 | public var bottomMargin: ConstraintMakerExtendable { 98 | return self.makeExtendableWithAttributes(.bottomMargin) 99 | } 100 | 101 | @available(iOS 8.0, *) 102 | public var leadingMargin: ConstraintMakerExtendable { 103 | return self.makeExtendableWithAttributes(.leadingMargin) 104 | } 105 | 106 | @available(iOS 8.0, *) 107 | public var trailingMargin: ConstraintMakerExtendable { 108 | return self.makeExtendableWithAttributes(.trailingMargin) 109 | } 110 | 111 | @available(iOS 8.0, *) 112 | public var centerXWithinMargins: ConstraintMakerExtendable { 113 | return self.makeExtendableWithAttributes(.centerXWithinMargins) 114 | } 115 | 116 | @available(iOS 8.0, *) 117 | public var centerYWithinMargins: ConstraintMakerExtendable { 118 | return self.makeExtendableWithAttributes(.centerYWithinMargins) 119 | } 120 | 121 | public var edges: ConstraintMakerExtendable { 122 | return self.makeExtendableWithAttributes(.edges) 123 | } 124 | public var size: ConstraintMakerExtendable { 125 | return self.makeExtendableWithAttributes(.size) 126 | } 127 | public var center: ConstraintMakerExtendable { 128 | return self.makeExtendableWithAttributes(.center) 129 | } 130 | 131 | @available(iOS 8.0, *) 132 | public var margins: ConstraintMakerExtendable { 133 | return self.makeExtendableWithAttributes(.margins) 134 | } 135 | 136 | @available(iOS 8.0, *) 137 | public var centerWithinMargins: ConstraintMakerExtendable { 138 | return self.makeExtendableWithAttributes(.centerWithinMargins) 139 | } 140 | 141 | private let view: ConstraintView 142 | private var descriptions = [ConstraintDescription]() 143 | 144 | internal init(view: ConstraintView) { 145 | self.view = view 146 | self.view.translatesAutoresizingMaskIntoConstraints = false 147 | } 148 | 149 | internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable { 150 | let description = ConstraintDescription(view: self.view, attributes: attributes) 151 | self.descriptions.append(description) 152 | return ConstraintMakerExtendable(description) 153 | } 154 | 155 | internal static func prepareConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { 156 | let maker = ConstraintMaker(view: view) 157 | closure(maker) 158 | let constraints = maker.descriptions 159 | .map { $0.constraint } 160 | .filter { $0 != nil } 161 | .map { $0! } 162 | return constraints 163 | } 164 | 165 | internal static func makeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) { 166 | let maker = ConstraintMaker(view: view) 167 | closure(maker) 168 | let constraints = maker.descriptions 169 | .map { $0.constraint } 170 | .filter { $0 != nil } 171 | .map { $0! } 172 | for constraint in constraints { 173 | constraint.activateIfNeeded(updatingExisting: false) 174 | } 175 | } 176 | 177 | internal static func remakeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) { 178 | self.removeConstraints(view: view) 179 | self.makeConstraints(view: view, closure: closure) 180 | } 181 | 182 | internal static func updateConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) { 183 | guard view.snp.constraints.count > 0 else { 184 | self.makeConstraints(view: view, closure: closure) 185 | return 186 | } 187 | 188 | let maker = ConstraintMaker(view: view) 189 | closure(maker) 190 | let constraints = maker.descriptions 191 | .map { $0.constraint } 192 | .filter { $0 != nil } 193 | .map { $0! } 194 | for constraint in constraints { 195 | constraint.activateIfNeeded(updatingExisting: true) 196 | } 197 | } 198 | 199 | internal static func removeConstraints(view: ConstraintView) { 200 | let constraints = view.snp.constraints 201 | for constraint in constraints { 202 | constraint.deactivateIfNeeded() 203 | } 204 | } 205 | 206 | } 207 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMakerEditable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerEditable: ConstraintMakerPriortizable { 32 | 33 | @discardableResult 34 | public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable { 35 | self.description.multiplier = amount 36 | return self 37 | } 38 | 39 | @discardableResult 40 | public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable { 41 | return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue) 42 | } 43 | 44 | @discardableResult 45 | public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable { 46 | self.description.constant = amount.constraintOffsetTargetValue 47 | return self 48 | } 49 | 50 | @discardableResult 51 | public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable { 52 | self.description.constant = amount.constraintInsetTargetValue 53 | return self 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMakerExtendable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerExtendable: ConstraintMakerRelatable { 32 | 33 | public var left: ConstraintMakerExtendable { 34 | self.description.attributes += .left 35 | return self 36 | } 37 | 38 | public var top: ConstraintMakerExtendable { 39 | self.description.attributes += .top 40 | return self 41 | } 42 | 43 | public var bottom: ConstraintMakerExtendable { 44 | self.description.attributes += .bottom 45 | return self 46 | } 47 | 48 | public var right: ConstraintMakerExtendable { 49 | self.description.attributes += .right 50 | return self 51 | } 52 | 53 | public var leading: ConstraintMakerExtendable { 54 | self.description.attributes += .leading 55 | return self 56 | } 57 | 58 | public var trailing: ConstraintMakerExtendable { 59 | self.description.attributes += .trailing 60 | return self 61 | } 62 | 63 | public var width: ConstraintMakerExtendable { 64 | self.description.attributes += .width 65 | return self 66 | } 67 | 68 | public var height: ConstraintMakerExtendable { 69 | self.description.attributes += .height 70 | return self 71 | } 72 | 73 | public var centerX: ConstraintMakerExtendable { 74 | self.description.attributes += .centerX 75 | return self 76 | } 77 | 78 | public var centerY: ConstraintMakerExtendable { 79 | self.description.attributes += .centerY 80 | return self 81 | } 82 | 83 | @available(*, deprecated:3.0, message:"Use lastBaseline instead") 84 | public var baseline: ConstraintMakerExtendable { 85 | self.description.attributes += .lastBaseline 86 | return self 87 | } 88 | 89 | public var lastBaseline: ConstraintMakerExtendable { 90 | self.description.attributes += .lastBaseline 91 | return self 92 | } 93 | 94 | @available(iOS 8.0, OSX 10.11, *) 95 | public var firstBaseline: ConstraintMakerExtendable { 96 | self.description.attributes += .firstBaseline 97 | return self 98 | } 99 | 100 | @available(iOS 8.0, *) 101 | public var leftMargin: ConstraintMakerExtendable { 102 | self.description.attributes += .leftMargin 103 | return self 104 | } 105 | 106 | @available(iOS 8.0, *) 107 | public var rightMargin: ConstraintMakerExtendable { 108 | self.description.attributes += .rightMargin 109 | return self 110 | } 111 | 112 | @available(iOS 8.0, *) 113 | public var bottomMargin: ConstraintMakerExtendable { 114 | self.description.attributes += .bottomMargin 115 | return self 116 | } 117 | 118 | @available(iOS 8.0, *) 119 | public var leadingMargin: ConstraintMakerExtendable { 120 | self.description.attributes += .leadingMargin 121 | return self 122 | } 123 | 124 | @available(iOS 8.0, *) 125 | public var trailingMargin: ConstraintMakerExtendable { 126 | self.description.attributes += .trailingMargin 127 | return self 128 | } 129 | 130 | @available(iOS 8.0, *) 131 | public var centerXWithinMargins: ConstraintMakerExtendable { 132 | self.description.attributes += .centerXWithinMargins 133 | return self 134 | } 135 | 136 | @available(iOS 8.0, *) 137 | public var centerYWithinMargins: ConstraintMakerExtendable { 138 | self.description.attributes += .centerYWithinMargins 139 | return self 140 | } 141 | 142 | public var edges: ConstraintMakerExtendable { 143 | self.description.attributes += .edges 144 | return self 145 | } 146 | public var size: ConstraintMakerExtendable { 147 | self.description.attributes += .size 148 | return self 149 | } 150 | 151 | @available(iOS 8.0, *) 152 | public var margins: ConstraintMakerExtendable { 153 | self.description.attributes += .margins 154 | return self 155 | } 156 | 157 | @available(iOS 8.0, *) 158 | public var centerWithinMargins: ConstraintMakerExtendable { 159 | self.description.attributes += .centerWithinMargins 160 | return self 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMakerFinalizable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerFinalizable { 32 | 33 | internal let description: ConstraintDescription 34 | 35 | internal init(_ description: ConstraintDescription) { 36 | self.description = description 37 | } 38 | 39 | @discardableResult 40 | public func labeled(_ label: String) -> ConstraintMakerFinalizable { 41 | self.description.label = label 42 | return self 43 | } 44 | 45 | public var constraint: Constraint { 46 | return self.description.constraint! 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMakerPriortizable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerPriortizable: ConstraintMakerFinalizable { 32 | 33 | @discardableResult 34 | public func priority(_ amount: ConstraintPriorityTarget) -> ConstraintMakerFinalizable { 35 | self.description.priority = amount 36 | return self 37 | } 38 | 39 | @available(*, deprecated:3.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.") 40 | @discardableResult 41 | public func priorityRequired() -> ConstraintMakerFinalizable { 42 | return self.priority(1000) 43 | } 44 | 45 | @available(*, deprecated:3.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.") 46 | @discardableResult 47 | public func priorityHigh() -> ConstraintMakerFinalizable { 48 | return self.priority(750) 49 | } 50 | 51 | @available(*, deprecated:3.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.") 52 | @discardableResult 53 | public func priorityMedium() -> ConstraintMakerFinalizable { 54 | #if os(iOS) || os(tvOS) 55 | return self.priority(500) 56 | #else 57 | return self.priority(501) 58 | #endif 59 | } 60 | 61 | @available(*, deprecated:3.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.") 62 | @discardableResult 63 | public func priorityLow() -> ConstraintMakerFinalizable { 64 | return self.priority(250) 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMakerRelatable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class ConstraintMakerRelatable { 32 | 33 | internal let description: ConstraintDescription 34 | 35 | internal init(_ description: ConstraintDescription) { 36 | self.description = description 37 | } 38 | 39 | internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable { 40 | let related: ConstraintItem 41 | let constant: ConstraintConstantTarget 42 | 43 | if let other = other as? ConstraintItem { 44 | guard other.attributes == ConstraintAttributes.none || 45 | other.attributes.layoutAttributes.count <= 1 || 46 | other.attributes.layoutAttributes == self.description.attributes.layoutAttributes || 47 | other.attributes == .edges && self.description.attributes == .margins || 48 | other.attributes == .margins && self.description.attributes == .edges else { 49 | fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))"); 50 | } 51 | 52 | related = other 53 | constant = 0.0 54 | } else if let other = other as? ConstraintView { 55 | related = ConstraintItem(target: other, attributes: ConstraintAttributes.none) 56 | constant = 0.0 57 | } else if let other = other as? ConstraintConstantTarget { 58 | related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none) 59 | constant = other 60 | } else { 61 | fatalError("Invalid constraint. (\(file), \(line))") 62 | } 63 | 64 | let editable = ConstraintMakerEditable(self.description) 65 | editable.description.sourceLocation = (file, line) 66 | editable.description.relation = relation 67 | editable.description.related = related 68 | editable.description.constant = constant 69 | return editable 70 | } 71 | 72 | @discardableResult 73 | public func equalTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { 74 | return self.relatedTo(other, relation: .equal, file: file, line: line) 75 | } 76 | 77 | @discardableResult 78 | public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { 79 | guard let other = self.description.view.superview else { 80 | fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.") 81 | } 82 | return self.relatedTo(other, relation: .equal, file: file, line: line) 83 | } 84 | 85 | @discardableResult 86 | public func lessThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable { 87 | return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line) 88 | } 89 | 90 | @discardableResult 91 | public func greaterThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable { 92 | return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line) 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintMultiplierTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintMultiplierTarget { 32 | 33 | var constraintMultiplierTargetValue: CGFloat { get } 34 | 35 | } 36 | 37 | extension Int: ConstraintMultiplierTarget { 38 | 39 | public var constraintMultiplierTargetValue: CGFloat { 40 | return CGFloat(self) 41 | } 42 | 43 | } 44 | 45 | extension UInt: ConstraintMultiplierTarget { 46 | 47 | public var constraintMultiplierTargetValue: CGFloat { 48 | return CGFloat(self) 49 | } 50 | 51 | } 52 | 53 | extension Float: ConstraintMultiplierTarget { 54 | 55 | public var constraintMultiplierTargetValue: CGFloat { 56 | return CGFloat(self) 57 | } 58 | 59 | } 60 | 61 | extension Double: ConstraintMultiplierTarget { 62 | 63 | public var constraintMultiplierTargetValue: CGFloat { 64 | return CGFloat(self) 65 | } 66 | 67 | } 68 | 69 | extension CGFloat: ConstraintMultiplierTarget { 70 | 71 | public var constraintMultiplierTargetValue: CGFloat { 72 | return self 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintOffsetTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintOffsetTarget: ConstraintConstantTarget { 32 | } 33 | 34 | extension Int: ConstraintOffsetTarget { 35 | } 36 | 37 | extension UInt: ConstraintOffsetTarget { 38 | } 39 | 40 | extension Float: ConstraintOffsetTarget { 41 | } 42 | 43 | extension Double: ConstraintOffsetTarget { 44 | } 45 | 46 | extension CGFloat: ConstraintOffsetTarget { 47 | } 48 | 49 | extension ConstraintOffsetTarget { 50 | 51 | internal var constraintOffsetTargetValue: CGFloat { 52 | let offset: CGFloat 53 | if let amount = self as? Float { 54 | offset = CGFloat(amount) 55 | } else if let amount = self as? Double { 56 | offset = CGFloat(amount) 57 | } else if let amount = self as? CGFloat { 58 | offset = CGFloat(amount) 59 | } else if let amount = self as? Int { 60 | offset = CGFloat(amount) 61 | } else if let amount = self as? UInt { 62 | offset = CGFloat(amount) 63 | } else { 64 | offset = 0.0 65 | } 66 | return offset 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintPriorityTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintPriorityTarget { 32 | 33 | var constraintPriorityTargetValue: Float { get } 34 | 35 | } 36 | 37 | extension Int: ConstraintPriorityTarget { 38 | 39 | public var constraintPriorityTargetValue: Float { 40 | return Float(self) 41 | } 42 | 43 | } 44 | 45 | extension UInt: ConstraintPriorityTarget { 46 | 47 | public var constraintPriorityTargetValue: Float { 48 | return Float(self) 49 | } 50 | 51 | } 52 | 53 | extension Float: ConstraintPriorityTarget { 54 | 55 | public var constraintPriorityTargetValue: Float { 56 | return self 57 | } 58 | 59 | } 60 | 61 | extension Double: ConstraintPriorityTarget { 62 | 63 | public var constraintPriorityTargetValue: Float { 64 | return Float(self) 65 | } 66 | 67 | } 68 | 69 | extension CGFloat: ConstraintPriorityTarget { 70 | 71 | public var constraintPriorityTargetValue: Float { 72 | return Float(self) 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintRelatableTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public protocol ConstraintRelatableTarget { 32 | } 33 | 34 | extension Int: ConstraintRelatableTarget { 35 | } 36 | 37 | extension UInt: ConstraintRelatableTarget { 38 | } 39 | 40 | extension Float: ConstraintRelatableTarget { 41 | } 42 | 43 | extension Double: ConstraintRelatableTarget { 44 | } 45 | 46 | extension CGFloat: ConstraintRelatableTarget { 47 | } 48 | 49 | extension CGSize: ConstraintRelatableTarget { 50 | } 51 | 52 | extension CGPoint: ConstraintRelatableTarget { 53 | } 54 | 55 | extension ConstraintInsets: ConstraintRelatableTarget { 56 | } 57 | 58 | extension ConstraintItem: ConstraintRelatableTarget { 59 | } 60 | 61 | extension ConstraintView: ConstraintRelatableTarget { 62 | } 63 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintRelation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | internal enum ConstraintRelation: Int { 32 | case equal = 1 33 | case lessThanOrEqual 34 | case greaterThanOrEqual 35 | 36 | internal var layoutRelation: NSLayoutRelation { 37 | get { 38 | switch(self) { 39 | case .equal: 40 | return .equal 41 | case .lessThanOrEqual: 42 | return .lessThanOrEqual 43 | case .greaterThanOrEqual: 44 | return .greaterThanOrEqual 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintView+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public extension ConstraintView { 32 | 33 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 34 | public var snp_left: ConstraintItem { return self.snp.left } 35 | 36 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 37 | public var snp_top: ConstraintItem { return self.snp.top } 38 | 39 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 40 | public var snp_right: ConstraintItem { return self.snp.right } 41 | 42 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 43 | public var snp_bottom: ConstraintItem { return self.snp.bottom } 44 | 45 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 46 | public var snp_leading: ConstraintItem { return self.snp.leading } 47 | 48 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 49 | public var snp_trailing: ConstraintItem { return self.snp.trailing } 50 | 51 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 52 | public var snp_width: ConstraintItem { return self.snp.width } 53 | 54 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 55 | public var snp_height: ConstraintItem { return self.snp.height } 56 | 57 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 58 | public var snp_centerX: ConstraintItem { return self.snp.centerX } 59 | 60 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 61 | public var snp_centerY: ConstraintItem { return self.snp.centerY } 62 | 63 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 64 | public var snp_baseline: ConstraintItem { return self.snp.baseline } 65 | 66 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 67 | @available(iOS 8.0, OSX 10.11, *) 68 | public var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline } 69 | 70 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 71 | @available(iOS 8.0, OSX 10.11, *) 72 | public var snp_firstBaseline: ConstraintItem { return self.snp.firstBaseline } 73 | 74 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 75 | @available(iOS 8.0, *) 76 | public var snp_leftMargin: ConstraintItem { return self.snp.leftMargin } 77 | 78 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 79 | @available(iOS 8.0, *) 80 | public var snp_topMargin: ConstraintItem { return self.snp.topMargin } 81 | 82 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 83 | @available(iOS 8.0, *) 84 | public var snp_rightMargin: ConstraintItem { return self.snp.rightMargin } 85 | 86 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 87 | @available(iOS 8.0, *) 88 | public var snp_bottomMargin: ConstraintItem { return self.snp.bottomMargin } 89 | 90 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 91 | @available(iOS 8.0, *) 92 | public var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin } 93 | 94 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 95 | @available(iOS 8.0, *) 96 | public var snp_trailingMargin: ConstraintItem { return self.snp.trailingMargin } 97 | 98 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 99 | @available(iOS 8.0, *) 100 | public var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins } 101 | 102 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 103 | @available(iOS 8.0, *) 104 | public var snp_centerYWithinMargins: ConstraintItem { return self.snp.centerYWithinMargins } 105 | 106 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 107 | public var snp_edges: ConstraintItem { return self.snp.edges } 108 | 109 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 110 | public var snp_size: ConstraintItem { return self.snp.size } 111 | 112 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 113 | public var snp_center: ConstraintItem { return self.snp.center } 114 | 115 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 116 | @available(iOS 8.0, *) 117 | public var snp_margins: ConstraintItem { return self.snp.margins } 118 | 119 | @available(iOS, deprecated:3.0, message:"Use newer snp.* syntax.") 120 | @available(iOS 8.0, *) 121 | public var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins } 122 | 123 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 124 | public func snp_prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { 125 | return self.snp.prepareConstraints(closure) 126 | } 127 | 128 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 129 | public func snp_makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 130 | self.snp.makeConstraints(closure) 131 | } 132 | 133 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 134 | public func snp_remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 135 | self.snp.remakeConstraints(closure) 136 | } 137 | 138 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 139 | public func snp_updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 140 | self.snp.updateConstraints(closure) 141 | } 142 | 143 | @available(*, deprecated:3.0, message:"Use newer snp.* syntax.") 144 | public func snp_removeConstraints() { 145 | self.snp.removeConstraints() 146 | } 147 | 148 | public var snp: ConstraintViewDSL { 149 | return ConstraintViewDSL(view: self) 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | #if os(iOS) || os(tvOS) 32 | public typealias ConstraintView = UIView 33 | #else 34 | public typealias ConstraintView = NSView 35 | #endif 36 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/ConstraintViewDSL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public struct ConstraintViewDSL: ConstraintAttributesDSL { 32 | 33 | @discardableResult 34 | public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] { 35 | return ConstraintMaker.prepareConstraints(view: self.view, closure: closure) 36 | } 37 | 38 | public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 39 | ConstraintMaker.makeConstraints(view: self.view, closure: closure) 40 | } 41 | 42 | public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 43 | ConstraintMaker.remakeConstraints(view: self.view, closure: closure) 44 | } 45 | 46 | public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { 47 | ConstraintMaker.updateConstraints(view: self.view, closure: closure) 48 | } 49 | 50 | public func removeConstraints() { 51 | ConstraintMaker.removeConstraints(view: self.view) 52 | } 53 | 54 | 55 | 56 | public var contentHuggingHorizontalPriority: Float { 57 | get { 58 | return self.view.contentHuggingPriority(for: .horizontal) 59 | } 60 | set { 61 | self.view.setContentHuggingPriority(newValue, for: .horizontal) 62 | } 63 | } 64 | 65 | public var contentHuggingVerticalPriority: Float { 66 | get { 67 | return self.view.contentHuggingPriority(for: .vertical) 68 | } 69 | set { 70 | self.view.setContentHuggingPriority(newValue, for: .vertical) 71 | } 72 | } 73 | 74 | public var contentCompressionResistanceHorizontalPriority: Float { 75 | get { 76 | return self.view.contentCompressionResistancePriority(for: .horizontal) 77 | } 78 | set { 79 | self.view.setContentHuggingPriority(newValue, for: .horizontal) 80 | } 81 | } 82 | 83 | public var contentCompressionResistanceVerticalPriority: Float { 84 | get { 85 | return self.view.contentCompressionResistancePriority(for: .vertical) 86 | } 87 | set { 88 | self.view.setContentCompressionResistancePriority(newValue, for: .vertical) 89 | } 90 | } 91 | 92 | public var target: AnyObject? { 93 | return self.view 94 | } 95 | 96 | internal let view: ConstraintView 97 | 98 | internal init(view: ConstraintView) { 99 | self.view = view 100 | 101 | } 102 | 103 | internal var constraints: [Constraint] { 104 | return self.constraintsHashTable.allObjects 105 | } 106 | 107 | internal func add(constraints: [Constraint]) { 108 | let hashTable = self.constraintsHashTable 109 | for constraint in constraints { 110 | hashTable.add(constraint) 111 | } 112 | } 113 | 114 | internal func remove(constraints: [Constraint]) { 115 | let hashTable = self.constraintsHashTable 116 | for constraint in constraints { 117 | hashTable.remove(constraint) 118 | } 119 | } 120 | 121 | private var constraintsHashTable: NSHashTable { 122 | let constraints: NSHashTable 123 | 124 | if let existing = objc_getAssociatedObject(self.view, &constraintsKey) as? NSHashTable { 125 | constraints = existing 126 | } else { 127 | constraints = NSHashTable() 128 | objc_setAssociatedObject(self.view, &constraintsKey, constraints, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 129 | } 130 | return constraints 131 | 132 | } 133 | 134 | } 135 | private var constraintsKey: UInt8 = 0 136 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/Debugging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | public extension LayoutConstraint { 31 | 32 | override public var description: String { 33 | var description = "<" 34 | 35 | description += descriptionForObject(self) 36 | 37 | if let firstItem = conditionalOptional(from: self.firstItem) { 38 | description += " \(descriptionForObject(firstItem))" 39 | } 40 | 41 | if self.firstAttribute != .notAnAttribute { 42 | description += ".\(descriptionForAttribute(self.firstAttribute))" 43 | } 44 | 45 | description += " \(descriptionForRelation(self.relation))" 46 | 47 | if let secondItem = self.secondItem { 48 | description += " \(descriptionForObject(secondItem))" 49 | } 50 | 51 | if self.secondAttribute != .notAnAttribute { 52 | description += ".\(descriptionForAttribute(self.secondAttribute))" 53 | } 54 | 55 | if self.multiplier != 1.0 { 56 | description += " * \(self.multiplier)" 57 | } 58 | 59 | if self.secondAttribute == .notAnAttribute { 60 | description += " \(self.constant)" 61 | } else { 62 | if self.constant > 0.0 { 63 | description += " + \(self.constant)" 64 | } else if self.constant < 0.0 { 65 | description += " - \(abs(self.constant))" 66 | } 67 | } 68 | 69 | if self.priority != 1000.0 { 70 | description += " ^\(self.priority)" 71 | } 72 | 73 | description += ">" 74 | 75 | return description 76 | } 77 | 78 | } 79 | 80 | private func descriptionForRelation(_ relation: NSLayoutRelation) -> String { 81 | switch relation { 82 | case .equal: return "==" 83 | case .greaterThanOrEqual: return ">=" 84 | case .lessThanOrEqual: return "<=" 85 | } 86 | } 87 | 88 | private func descriptionForAttribute(_ attribute: NSLayoutAttribute) -> String { 89 | #if os(iOS) || os(tvOS) 90 | switch attribute { 91 | case .notAnAttribute: return "notAnAttribute" 92 | case .top: return "top" 93 | case .left: return "left" 94 | case .bottom: return "bottom" 95 | case .right: return "right" 96 | case .leading: return "leading" 97 | case .trailing: return "trailing" 98 | case .width: return "width" 99 | case .height: return "height" 100 | case .centerX: return "centerX" 101 | case .centerY: return "centerY" 102 | case .lastBaseline: return "lastBaseline" 103 | case .firstBaseline: return "firstBaseline" 104 | case .topMargin: return "topMargin" 105 | case .leftMargin: return "leftMargin" 106 | case .bottomMargin: return "bottomMargin" 107 | case .rightMargin: return "rightMargin" 108 | case .leadingMargin: return "leadingMargin" 109 | case .trailingMargin: return "trailingMargin" 110 | case .centerXWithinMargins: return "centerXWithinMargins" 111 | case .centerYWithinMargins: return "centerYWithinMargins" 112 | } 113 | #else 114 | switch attribute { 115 | case .notAnAttribute: return "notAnAttribute" 116 | case .top: return "top" 117 | case .left: return "left" 118 | case .bottom: return "bottom" 119 | case .right: return "right" 120 | case .leading: return "leading" 121 | case .trailing: return "trailing" 122 | case .width: return "width" 123 | case .height: return "height" 124 | case .centerX: return "centerX" 125 | case .centerY: return "centerY" 126 | case .lastBaseline: return "lastBaseline" 127 | case .firstBaseline: return "firstBaseline" 128 | } 129 | #endif 130 | } 131 | 132 | private func conditionalOptional(from object: Optional) -> Optional { 133 | return object 134 | } 135 | 136 | private func conditionalOptional(from object: T) -> Optional { 137 | return Optional.some(object) 138 | } 139 | 140 | private func descriptionForObject(_ object: AnyObject) -> String { 141 | let pointerDescription = String(format: "%p", UInt(bitPattern: ObjectIdentifier(object))) 142 | var desc = "" 143 | 144 | desc += type(of: object).description() 145 | 146 | if let object = object as? ConstraintView { 147 | desc += ":\(object.snp.label() ?? pointerDescription)" 148 | } else if let object = object as? LayoutConstraint { 149 | desc += ":\(object.label ?? pointerDescription)" 150 | } else { 151 | desc += ":\(pointerDescription)" 152 | } 153 | 154 | if let object = object as? LayoutConstraint, let file = object.constraint?.sourceLocation.0, let line = object.constraint?.sourceLocation.1 { 155 | desc += "@\((file as NSString).lastPathComponent)#\(line)" 156 | } 157 | 158 | desc += "" 159 | return desc 160 | } 161 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/LayoutConstraint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | 31 | public class LayoutConstraint: NSLayoutConstraint { 32 | 33 | public var label: String? { 34 | get { 35 | return self.identifier 36 | } 37 | set { 38 | self.identifier = newValue 39 | } 40 | } 41 | 42 | internal weak var constraint: Constraint? = nil 43 | 44 | } 45 | 46 | internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool { 47 | guard lhs.firstItem === rhs.firstItem && 48 | lhs.secondItem === rhs.secondItem && 49 | lhs.firstAttribute == rhs.firstAttribute && 50 | lhs.secondAttribute == rhs.secondAttribute && 51 | lhs.relation == rhs.relation && 52 | lhs.priority == rhs.priority && 53 | lhs.multiplier == rhs.multiplier else { 54 | return false 55 | } 56 | return true 57 | } 58 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/SnapKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | FOUNDATION_EXPORT double SnapKitVersionNumber; 27 | FOUNDATION_EXPORT const unsigned char SnapKitVersionString[]; -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/UILayoutGuide+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #endif 27 | 28 | 29 | @available(iOS 9.0, *) 30 | public extension ConstraintLayoutGuide { 31 | 32 | public var snp: ConstraintLayoutGuideDSL { 33 | return ConstraintLayoutGuideDSL(guide: self) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /YTAnimationDemo/SnapKit/UILayoutSupport+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #endif 27 | 28 | 29 | @available(iOS 8.0, *) 30 | public extension ConstraintLayoutSupport { 31 | 32 | public var snp: ConstraintLayoutSupportDSL { 33 | return ConstraintLayoutSupportDSL(support: self) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /YTAnimationDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/23. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | fileprivate var myTableView: UITableView! 14 | fileprivate var array_Dict = [Dictionary]() 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | title = "动画" 20 | view.backgroundColor = UIColor.white 21 | configData() 22 | initMainView() 23 | } 24 | 25 | override func didReceiveMemoryWarning() { 26 | super.didReceiveMemoryWarning() 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | 31 | } 32 | 33 | // MARK: 配置数据 34 | extension ViewController{ 35 | 36 | func configData() { 37 | 38 | var dict_SectionOne = Dictionary() 39 | dict_SectionOne["title"] = "基础动画" 40 | dict_SectionOne["rowValue"] = ["位移", "旋转", "缩放", "透明度", "背景色"] 41 | 42 | var dict_SectionTwo = Dictionary() 43 | dict_SectionTwo["title"] = "关键帧动画" 44 | dict_SectionTwo["rowValue"] = ["关键帧", "路径", "抖动"] 45 | 46 | var dict_SectionThree = Dictionary() 47 | dict_SectionThree["title"] = "组动画" 48 | dict_SectionThree["rowValue"] = ["同时", "连续"] 49 | 50 | var dict_SectionFour = Dictionary() 51 | dict_SectionFour["title"] = "过渡动画" 52 | dict_SectionFour["rowValue"] = ["fade", "moveln", "push", "reveal", "cube", "suck", "oglFile", "ripple", "curl", "unCurl", "caOpen", "caClose"] 53 | 54 | var dict_SectionFive = Dictionary() 55 | dict_SectionFive["title"] = "项目案例" 56 | dict_SectionFive["rowValue"] = ["弹球", "钉钉", "点赞", "贝塞尔曲线", "进度"] 57 | 58 | array_Dict = [dict_SectionOne, dict_SectionTwo, dict_SectionThree, dict_SectionFour, dict_SectionFive] 59 | } 60 | 61 | } 62 | 63 | // MARK: UITableViewDelegate, UITableViewDataSource 64 | extension ViewController: UITableViewDelegate, UITableViewDataSource{ 65 | 66 | func numberOfSections(in tableView: UITableView) -> Int { 67 | return array_Dict.count 68 | } 69 | 70 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 71 | if let array: Array = array_Dict[section]["rowValue"] as? Array{ 72 | return array.count 73 | } 74 | return 0 75 | } 76 | 77 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 78 | let identifier = "AnimationCellIdentifier" 79 | var cell = tableView.dequeueReusableCell(withIdentifier: identifier) 80 | if cell == nil{ 81 | cell = UITableViewCell.init(style: .default, reuseIdentifier: identifier) 82 | } 83 | if let array: Array = array_Dict[indexPath.section]["rowValue"] as? Array{ 84 | cell?.textLabel?.text = array[indexPath.row] 85 | } 86 | return cell! 87 | } 88 | 89 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 90 | 91 | var vc: YTBaseViewController? 92 | switch indexPath.section { 93 | case 0: 94 | vc = YTBaseAnimationViewController.init(enterType: indexPath.row) 95 | case 1: 96 | vc = YTKeyFrameAnimationViewController.init(enterType: indexPath.row) 97 | case 2: 98 | vc = YTGroupAnimationViewController.init(enterType: indexPath.row) 99 | case 3: 100 | vc = YTTransitionAnimationViewController.init(enterType: indexPath.row) 101 | case 4: 102 | let viewControl = YTCombinationAnimationViewController.init(enterType: indexPath.row) 103 | if let array: Array = array_Dict[indexPath.section]["rowValue"] as? Array{ 104 | viewControl.title = array[indexPath.row] 105 | } 106 | navigationController?.pushViewController(viewControl, animated: true) 107 | break 108 | default: 109 | break 110 | } 111 | 112 | if let array: Array = array_Dict[indexPath.section]["rowValue"] as? Array{ 113 | vc?.title = array[indexPath.row] 114 | } 115 | guard let viewControl = vc else {return} 116 | navigationController?.pushViewController(viewControl, animated: true) 117 | } 118 | 119 | func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 120 | return array_Dict[section]["title"] as? String 121 | } 122 | 123 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 124 | return 45 125 | } 126 | 127 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 128 | return 20 129 | } 130 | 131 | func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 132 | return 0.01 133 | } 134 | 135 | } 136 | 137 | // MARK: UI 138 | extension ViewController{ 139 | 140 | func initMainView() { 141 | 142 | myTableView = UITableView.init(frame: CGRect.zero, style: .grouped) 143 | myTableView.delegate = self 144 | myTableView.dataSource = self 145 | myTableView.backgroundColor = UIColor.init(red: 180, green: 180, blue: 180, alpha: 1) 146 | view.addSubview(myTableView) 147 | 148 | myTableView.snp.makeConstraints { (make) in 149 | make.top.equalTo(kNavigationBarHei) 150 | make.left.right.equalTo(view) 151 | make.bottom.equalTo(-iPhoneXBottemHei) 152 | } 153 | 154 | if #available(iOS 11.0, *) { 155 | myTableView.contentInsetAdjustmentBehavior = .never 156 | }else{ 157 | self.automaticallyAdjustsScrollViewInsets = false 158 | } 159 | 160 | } 161 | 162 | } 163 | 164 | -------------------------------------------------------------------------------- /YTAnimationDemo/YTAnimationDemo-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/29. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | 10 | #import "DCPathButton.h" 11 | #import "DWBubbleMenuButton.h" 12 | #import "MCFireworksButton.h" 13 | 14 | 15 | -------------------------------------------------------------------------------- /YTAnimationDemo/关键帧动画/YTKeyFrameAnimationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTKeyFrameAnimationViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/25. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum KeyFrameAnimationType: Int { 12 | case keyFrame = 0 //关键帧 13 | case path //路径 14 | case shake //抖动 15 | } 16 | 17 | class YTKeyFrameAnimationViewController: YTBaseViewController { 18 | 19 | fileprivate var type: KeyFrameAnimationType! 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | // Do any additional setup after loading the view. 25 | } 26 | 27 | convenience init(enterType: Int) { 28 | self.init() 29 | switch enterType { 30 | case 0: 31 | type = .keyFrame 32 | case 1: 33 | type = .path 34 | case 2: 35 | type = .shake 36 | default: 37 | break 38 | } 39 | } 40 | 41 | override func didReceiveMemoryWarning() { 42 | super.didReceiveMemoryWarning() 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | } 47 | 48 | 49 | extension YTKeyFrameAnimationViewController { 50 | 51 | override func playBtnClick(btn: UIButton) { 52 | switch type.rawValue { 53 | case 0: 54 | keyFrameAnimation() 55 | case 1: 56 | pathAnimation() 57 | case 2: 58 | shakeAnimation() 59 | default: 60 | break 61 | } 62 | } 63 | 64 | } 65 | 66 | // MARK: 关键帧动画 67 | extension YTKeyFrameAnimationViewController { 68 | 69 | //关键帧动画 70 | func keyFrameAnimation() { 71 | 72 | let animation = CAKeyframeAnimation.init(keyPath: "position") 73 | let value_0 = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewWidthHeight) 74 | let value_1 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 - margin_ViewWidthHeight) 75 | let value_2 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 + margin_ViewMidPosition) 76 | let value_3 = CGPoint.init(x: kScreenW * 2 / 3, y: kScreenH / 2 + margin_ViewMidPosition) 77 | let value_4 = CGPoint.init(x: kScreenW * 2 / 3, y: kScreenH / 2 - margin_ViewWidthHeight) 78 | let value_5 = CGPoint.init(x: kScreenW - margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewWidthHeight) 79 | animation.values = [value_0, value_1, value_2, value_3, value_4, value_5] 80 | animation.duration = 2.0 81 | view_Body.layer.add(animation, forKey: "keyFrameAnimation") 82 | } 83 | 84 | //路径动画 85 | func pathAnimation() { 86 | 87 | let animation = CAKeyframeAnimation.init(keyPath: "position") 88 | let path = UIBezierPath.init(arcCenter: CGPoint.init(x: kScreenW / 2, y: kScreenH / 2), radius: 60, startAngle: 0.0, endAngle: .pi * 2, clockwise: true) 89 | animation.duration = 2.0 90 | animation.path = path.cgPath 91 | view_Body.layer.add(animation, forKey: "pathAnimation") 92 | } 93 | 94 | //抖动动画 95 | func shakeAnimation() { 96 | 97 | let animation = CAKeyframeAnimation.init(keyPath: "transform.rotation") 98 | let value_0 = NSNumber.init(value: -Double.pi / 180 * 8) 99 | let value_1 = NSNumber.init(value: Double.pi / 180 * 8) 100 | animation.values = [value_0, value_1, value_0] 101 | animation.duration = 1.0 102 | animation.repeatCount = 1e100 103 | view_Body.layer.add(animation, forKey: "shakeAnimation") 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /YTAnimationDemo/基础动画/YTBaseAnimationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTBaseAnimationViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 2018/5/24. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum BaseAnimationType: Int{ 12 | case position = 0 //位移 13 | case rotate = 1 //旋转 14 | case scale //缩放 15 | case opacity //透明度 16 | case backgroundColor //背景色 17 | } 18 | 19 | class YTBaseAnimationViewController: YTBaseViewController { 20 | 21 | fileprivate var type: BaseAnimationType = .position 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | } 27 | 28 | convenience init(enterType: Int) { 29 | self.init() 30 | switch enterType { 31 | case 0: 32 | type = .position 33 | case 1: 34 | type = .rotate 35 | case 2: 36 | type = .scale 37 | case 3: 38 | type = .opacity 39 | case 4: 40 | type = .backgroundColor 41 | default: 42 | break 43 | } 44 | } 45 | 46 | override func didReceiveMemoryWarning() { 47 | super.didReceiveMemoryWarning() 48 | // Dispose of any resources that can be recreated. 49 | } 50 | 51 | } 52 | 53 | 54 | extension YTBaseAnimationViewController{ 55 | 56 | override func playBtnClick(btn: UIButton) { 57 | switch type.rawValue { 58 | case 0: 59 | positionAnimation() 60 | case 1: 61 | rotateAnimation() 62 | case 2: 63 | scaleAnimation() 64 | case 3: 65 | opacityAnimation() 66 | case 4: 67 | backgroundColorAnimation() 68 | default: 69 | break 70 | } 71 | } 72 | 73 | } 74 | 75 | // MARK: Animation 76 | extension YTBaseAnimationViewController{ 77 | 78 | // 可选的KeyPath 79 | // transform.scale = 比例轉換 80 | // transform.scale.x 81 | // transform.scale.y 82 | // transform.rotation = 旋轉 83 | // transform.rotation.x 84 | // transform.rotation.y 85 | // transform.rotation.z 86 | // transform.translation 87 | // transform.translation.x 88 | // transform.translation.y 89 | // transform.translation.z 90 | // 91 | // opacity = 透明度 92 | // margin 93 | // zPosition 94 | // backgroundColor 背景颜色 95 | // cornerRadius 圆角 96 | // borderWidth 97 | // bounds 98 | // contents 99 | // contentsRect 100 | // cornerRadius 101 | // frame 102 | // hidden 103 | // mask 104 | // masksToBounds 105 | // opacity 106 | // position 107 | // shadowColor 108 | // shadowOffset 109 | // shadowOpacity 110 | // shadowRadius 111 | 112 | //位移动画 113 | func positionAnimation() { 114 | 115 | let animation = CABasicAnimation.init(keyPath: "position") //keyPath为系统提供 116 | animation.fromValue = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2 - margin_Top) 117 | animation.toValue = CGPoint.init(x: kScreenW - margin_ViewMidPosition, y: kScreenH / 2 - margin_Top) 118 | animation.duration = 1.0 119 | view_Body.layer.add(animation, forKey: "positionAnimation") //key自定义 120 | } 121 | 122 | //旋转动画 123 | func rotateAnimation() { 124 | 125 | let animation = CABasicAnimation.init(keyPath: "transform.rotation.z") 126 | animation.toValue = NSNumber.init(value: Double.pi) 127 | animation.duration = 0.1 128 | animation.repeatCount = 1e100 //无限大重复次数 129 | view_Body.layer.add(animation, forKey: "rotateAnimation") 130 | } 131 | 132 | //缩放动画 133 | func scaleAnimation() { 134 | 135 | let animation = CABasicAnimation.init(keyPath: "transform.scale") 136 | animation.toValue = NSNumber.init(value: 2.0) 137 | animation.duration = 1.0 138 | view_Body.layer.add(animation, forKey: "scaleAnimation") 139 | } 140 | 141 | //透明度动画 142 | func opacityAnimation() { 143 | 144 | let animation = CABasicAnimation.init(keyPath: "opacity") 145 | animation.fromValue = NSNumber.init(value: 1.0) 146 | animation.toValue = NSNumber.init(value: 0.0) 147 | animation.duration = 1.0 148 | view_Body.layer.add(animation, forKey: "opacityAnimation") 149 | } 150 | 151 | //背景色动画 152 | func backgroundColorAnimation() { 153 | 154 | let animation = CABasicAnimation.init(keyPath: "backgroundColor") 155 | animation.toValue = UIColor.green.cgColor //因为layer层动画, 所以需要使用cgColor 156 | animation.duration = 1.0 157 | view_Body.layer.add(animation, forKey: "backgroundColorAnimation") 158 | } 159 | 160 | } 161 | 162 | -------------------------------------------------------------------------------- /YTAnimationDemo/组动画/YTGroupAnimationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTGroupAnimationViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 18/5/25. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum GroupAnimationType: Int { 12 | case sameTime = 0 //同时 13 | case goOn //连续 14 | } 15 | 16 | class YTGroupAnimationViewController: YTBaseViewController { 17 | 18 | fileprivate var type: GroupAnimationType! 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | // Do any additional setup after loading the view. 24 | } 25 | 26 | convenience init(enterType: Int) { 27 | self.init() 28 | switch enterType { 29 | case 0: 30 | type = .sameTime 31 | case 1: 32 | type = .goOn 33 | default: 34 | break 35 | } 36 | } 37 | 38 | override func didReceiveMemoryWarning() { 39 | super.didReceiveMemoryWarning() 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | } 44 | 45 | 46 | extension YTGroupAnimationViewController{ 47 | 48 | override func playBtnClick(btn: UIButton) { 49 | switch type.rawValue { 50 | case 0: 51 | sameTimeAnimation() 52 | case 1: 53 | goOnAnimation() 54 | default: 55 | break 56 | } 57 | } 58 | 59 | } 60 | 61 | 62 | // MARK: 组动画 63 | extension YTGroupAnimationViewController{ 64 | 65 | //同时 66 | func sameTimeAnimation() { 67 | 68 | let animation_Position = CAKeyframeAnimation.init(keyPath: "position") 69 | let value_0 = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewMidPosition) 70 | let value_1 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 - margin_ViewMidPosition) 71 | let value_2 = CGPoint.init(x: kScreenW / 3, y: kScreenH / 2 + margin_ViewMidPosition) 72 | let value_3 = CGPoint.init(x: kScreenW / 3 * 2, y: kScreenH / 2 + margin_ViewMidPosition) 73 | let value_4 = CGPoint.init(x: kScreenW / 3 * 2, y: kScreenH / 2 - margin_ViewMidPosition) 74 | let value_5 = CGPoint.init(x: kScreenW - margin_ViewMidPosition, y: kScreenH / 2 - margin_ViewMidPosition) 75 | animation_Position.values = [value_0, value_1, value_2, value_3, value_4, value_5] 76 | 77 | let animation_BGColor = CABasicAnimation.init(keyPath: "backgroundColor") 78 | animation_BGColor.toValue = UIColor.green.cgColor 79 | 80 | let animation_Rotate = CABasicAnimation.init(keyPath: "transform.rotation") 81 | animation_Rotate.toValue = NSNumber.init(value: Double.pi * 4) 82 | 83 | let animation_Group = CAAnimationGroup() 84 | animation_Group.animations = [animation_Position, animation_BGColor, animation_Rotate] 85 | animation_Group.duration = 4.0 86 | view_Body.layer.add(animation_Group, forKey: "groupAnimation") 87 | } 88 | 89 | //连续动画 最主要的是处理好各个动画时间的衔接 90 | func goOnAnimation() { 91 | 92 | //定义一个动画开始的时间 93 | let currentTime = CACurrentMediaTime() 94 | 95 | let animation_Position = CABasicAnimation.init(keyPath: "position") 96 | animation_Position.fromValue = CGPoint.init(x: margin_ViewMidPosition, y: kScreenH / 2) 97 | animation_Position.toValue = CGPoint.init(x: kScreenW / 2, y: kScreenH / 2) 98 | animation_Position.duration = 1.0 99 | animation_Position.fillMode = "forwards" //只在前台 100 | animation_Position.isRemovedOnCompletion = false //切出界面再回来动画不会停止 101 | animation_Position.beginTime = currentTime 102 | view_Body.layer.add(animation_Position, forKey: "positionAnimation") 103 | 104 | let animation_Scale = CABasicAnimation.init(keyPath: "transform.scale") 105 | animation_Scale.fromValue = NSNumber.init(value: 0.7) 106 | animation_Scale.toValue = NSNumber.init(value: 2.0) 107 | animation_Scale.duration = 1.0 108 | animation_Scale.fillMode = "forwards" 109 | animation_Scale.isRemovedOnCompletion = false 110 | animation_Scale.beginTime = currentTime + 1.0 111 | view_Body.layer.add(animation_Scale, forKey: "scaleAnimation") 112 | 113 | let animation_Rotate = CABasicAnimation.init(keyPath: "transform.rotation") 114 | animation_Rotate.toValue = NSNumber.init(value: Double.pi * 4) 115 | animation_Rotate.duration = 1.0 116 | animation_Rotate.fillMode = "forwards" 117 | animation_Rotate.isRemovedOnCompletion = false 118 | animation_Rotate.beginTime = currentTime + 2.0 119 | view_Body.layer.add(animation_Rotate, forKey: "rotateAnimation") 120 | } 121 | 122 | } 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /YTAnimationDemo/过渡动画/YTTransitionAnimationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTTransitionAnimationViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 18/5/28. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum TransitionAnimationType: Int{ 12 | case fade = 0 //淡出 默认 13 | case moveIn //覆盖原图 14 | case push // 推出 15 | case reveal //底部显示出来 16 | case cube //立方旋转 17 | case suck //吸走 18 | case oglFlip //水平翻转 沿y轴 19 | case ripple //滴水效果 20 | case curl //卷曲翻页(向上翻页) 21 | case unCurl //卷曲翻页返回(向下翻页) 22 | case caOpen //相机开启 23 | case caClose //相机关闭 24 | } 25 | 26 | class YTTransitionAnimationViewController: YTBaseViewController { 27 | 28 | fileprivate var type: TransitionAnimationType = .fade 29 | fileprivate var label_Num: UILabel! 30 | fileprivate var index: Int = 0 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | createLabel() 36 | } 37 | 38 | convenience init(enterType: Int) { 39 | self.init() 40 | switch enterType { 41 | case 0: 42 | type = .fade 43 | case 1: 44 | type = .moveIn 45 | case 2: 46 | type = .push 47 | case 3: 48 | type = .reveal 49 | case 4: 50 | type = .cube 51 | case 5: 52 | type = .suck 53 | case 6: 54 | type = .oglFlip 55 | case 7: 56 | type = .ripple 57 | case 8: 58 | type = .curl 59 | case 9: 60 | type = .unCurl 61 | case 10: 62 | type = .caOpen 63 | case 11: 64 | type = .caClose 65 | default: 66 | break 67 | } 68 | } 69 | 70 | override func didReceiveMemoryWarning() { 71 | super.didReceiveMemoryWarning() 72 | // Dispose of any resources that can be recreated. 73 | } 74 | 75 | } 76 | 77 | // MARK: 逻辑处理 78 | extension YTTransitionAnimationViewController{ 79 | 80 | func changeLabelNum() { 81 | 82 | if index > 4{ index = 0 } 83 | 84 | let array_Color = [UIColor.cyan, UIColor.magenta, UIColor.red, UIColor.purple, UIColor.orange] 85 | let array_Num = ["1", "2", "3", "4", "5"] 86 | 87 | view_Body.backgroundColor = array_Color[index] 88 | label_Num.text = array_Num[index] 89 | 90 | index += 1 91 | } 92 | 93 | override func playBtnClick(btn: UIButton) { 94 | 95 | changeLabelNum() 96 | 97 | switch type.rawValue { 98 | case 0: 99 | fadeAnimation() 100 | case 1: 101 | moveInAnimation() 102 | case 2: 103 | pushAnimation() 104 | case 3: 105 | revealAnimation() 106 | case 4: 107 | cubeAnimation() 108 | case 5: 109 | suckAnimation() 110 | case 6: 111 | oglFlipAnimation() 112 | case 7: 113 | rippleAnimation() 114 | case 8: 115 | curlAnimation() 116 | case 9: 117 | unCurlAnimation() 118 | case 10: 119 | caOpenAnimation() 120 | case 11: 121 | caCloseAnimation() 122 | default: 123 | break 124 | } 125 | } 126 | 127 | } 128 | 129 | // MARK: 过渡动画 130 | extension YTTransitionAnimationViewController{ 131 | 132 | // CATransition 转场动画 133 | 134 | func fadeAnimation() { 135 | 136 | let animation_Fade = CATransition() 137 | animation_Fade.type = "fade" 138 | animation_Fade.duration = 1.0 139 | view_Body.layer.add(animation_Fade, forKey: "fadeAnimation") 140 | } 141 | 142 | func moveInAnimation() { 143 | 144 | let animation_MoveIn = CATransition() 145 | animation_MoveIn.type = "moveIn" 146 | animation_MoveIn.duration = 1.0 147 | view_Body.layer.add(animation_MoveIn, forKey: "moveInAnimation") 148 | } 149 | 150 | func pushAnimation() { 151 | 152 | let animation_Push = CATransition() 153 | animation_Push.type = "push" 154 | animation_Push.subtype = "fromRight" /* the legal values are `fromLeft', `fromRight', `fromTop' and`fromBottom'. */ 155 | animation_Push.duration = 1.0 156 | view_Body.layer.add(animation_Push, forKey: "pushAnimation") 157 | } 158 | 159 | func revealAnimation() { 160 | 161 | let animation_Reveal = CATransition() 162 | animation_Reveal.type = "reveal" 163 | animation_Reveal.subtype = "fromRight" 164 | animation_Reveal.duration = 1.0 165 | view_Body.layer.add(animation_Reveal, forKey: "revealAnimation") 166 | } 167 | 168 | func cubeAnimation() { 169 | 170 | let animation_Cube = CATransition() 171 | animation_Cube.type = "cube" 172 | animation_Cube.subtype = "fromRight" 173 | animation_Cube.duration = 1.0 174 | view_Body.layer.add(animation_Cube, forKey: "cubeAnimation") 175 | } 176 | 177 | func suckAnimation() { 178 | 179 | let animation_Suck = CATransition() 180 | animation_Suck.type = "suckEffect" 181 | animation_Suck.subtype = "fromRight" 182 | animation_Suck.duration = 1.0 183 | view_Body.layer.add(animation_Suck, forKey: "suckAnimation") 184 | } 185 | 186 | func oglFlipAnimation() { 187 | 188 | let animation_OglFlip = CATransition() 189 | animation_OglFlip.type = "oglFlip" 190 | animation_OglFlip.subtype = "fromRight" 191 | animation_OglFlip.duration = 1.0 192 | view_Body.layer.add(animation_OglFlip, forKey: "oglFlipAnimation") 193 | } 194 | 195 | func rippleAnimation() { 196 | 197 | let animation_Ripple = CATransition() 198 | animation_Ripple.type = "rippleEffect" 199 | animation_Ripple.subtype = "fromRight" 200 | animation_Ripple.duration = 1.0 201 | view_Body.layer.add(animation_Ripple, forKey: "rippleAnimation") 202 | } 203 | 204 | func curlAnimation() { 205 | 206 | let animation_Curl = CATransition() 207 | animation_Curl.type = "pageCurl" 208 | animation_Curl.subtype = "fromRight" 209 | animation_Curl.duration = 1.0 210 | view_Body.layer.add(animation_Curl, forKey: "curlAnimation") 211 | } 212 | 213 | func unCurlAnimation() { 214 | 215 | let animation_UnCurl = CATransition() 216 | animation_UnCurl.type = "pageUnCurl" 217 | animation_UnCurl.subtype = "fromRight" 218 | animation_UnCurl.duration = 1.0 219 | view_Body.layer.add(animation_UnCurl, forKey: "unCurlAnimation") 220 | } 221 | 222 | func caOpenAnimation() { 223 | 224 | let animation_CaOpen = CATransition() 225 | animation_CaOpen.type = "cameraIrisHollowOpen" 226 | animation_CaOpen.subtype = "fromRight" 227 | animation_CaOpen.duration = 1.0 228 | view_Body.layer.add(animation_CaOpen, forKey: "caOpenAnimation") 229 | } 230 | 231 | func caCloseAnimation() { 232 | 233 | let animation_CaClose = CATransition() 234 | animation_CaClose.type = "cameraIrisHollowClose" 235 | animation_CaClose.subtype = "fromRight" 236 | animation_CaClose.duration = 1.0 237 | view_Body.layer.add(animation_CaClose, forKey: "caCloseAnimation") 238 | } 239 | 240 | } 241 | 242 | // MARK: UI 243 | extension YTTransitionAnimationViewController{ 244 | 245 | func createLabel() { 246 | 247 | label_Num = UILabel() 248 | label_Num.font = UIFont.systemFont(ofSize: 40) 249 | label_Num.textAlignment = .center 250 | view_Body.addSubview(label_Num) 251 | label_Num.snp.makeConstraints { (make) in 252 | make.centerX.centerY.equalTo(view_Body) 253 | make.width.height.equalTo(40) 254 | } 255 | 256 | changeLabelNum() 257 | } 258 | 259 | } 260 | 261 | 262 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/项目案例/.DS_Store -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/YTCombinationAnimationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTCombinationAnimationViewController.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 18/5/28. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum CombinationAnimationType: Int{ 12 | case aPath = 0 //弹球 13 | case dingding //钉钉 14 | case dianzan //点赞 15 | case bezier //贝塞尔曲线 16 | case progress //进度球 17 | } 18 | 19 | class YTCombinationAnimationViewController: UIViewController { 20 | 21 | fileprivate var type: CombinationAnimationType = .aPath 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | view.backgroundColor = UIColor.white 27 | } 28 | 29 | convenience init(enterType: Int){ 30 | 31 | self.init() 32 | 33 | switch enterType { 34 | case 0: 35 | aPathAnimation() 36 | case 1: 37 | dingDingAnimation() 38 | case 2: 39 | dianZanAnimation() 40 | case 3: 41 | bezierAnimation() 42 | case 4: 43 | progressAnimation() 44 | default: 45 | break 46 | } 47 | 48 | 49 | } 50 | 51 | override func didReceiveMemoryWarning() { 52 | super.didReceiveMemoryWarning() 53 | // Dispose of any resources that can be recreated. 54 | } 55 | 56 | } 57 | 58 | // 弹球 59 | extension YTCombinationAnimationViewController: DCPathButtonDelegate{ 60 | 61 | func aPathAnimation() { 62 | 63 | let btn_DcPath = DCPathButton.init(center: UIImage(named: "chooser-button-tab"), hilightedImage: UIImage(named: "chooser-button-tab-highlighted")) 64 | 65 | btn_DcPath?.delegate = self 66 | 67 | //各个item 68 | let btn_Item1 = DCPathItemButton.init(image: UIImage(named: "chooser-moment-icon-music"), highlightedImage: UIImage(named: "chooser-moment-icon-music-highlighted"), backgroundImage: UIImage(named: "chooser-moment-button"), backgroundHighlightedImage: UIImage(named: "chooser-moment-button-highlighted")) 69 | 70 | let btn_Item2 = DCPathItemButton.init(image: UIImage(named: "chooser-moment-icon-place"), highlightedImage: UIImage(named: "chooser-moment-icon-place-highlighted"), backgroundImage: UIImage(named: "chooser-moment-button"), backgroundHighlightedImage: UIImage(named: "chooser-moment-button-highlighted")) 71 | 72 | let btn_Item3 = DCPathItemButton.init(image: UIImage(named: "chooser-moment-icon-camera"), highlightedImage: UIImage(named: "chooser-moment-icon-camera-highlighted"), backgroundImage: UIImage(named: "chooser-moment-button"), backgroundHighlightedImage: UIImage(named: "chooser-moment-button-highlighted")) 73 | 74 | let btn_Item4 = DCPathItemButton.init(image: UIImage(named: "chooser-moment-icon-thought"), highlightedImage: UIImage(named: "chooser-moment-icon-thought-highlighted"), backgroundImage: UIImage(named: "chooser-moment-button"), backgroundHighlightedImage: UIImage(named: "chooser-moment-button-highlighted")) 75 | 76 | let btn_Item5 = DCPathItemButton.init(image: UIImage(named: "chooser-moment-icon-sleep"), highlightedImage: UIImage(named: "chooser-moment-icon-sleep-highlighted"), backgroundImage: UIImage(named: "chooser-moment-button"), backgroundHighlightedImage: UIImage(named: "chooser-moment-button-highlighted")) 77 | 78 | btn_DcPath?.addPathItems([btn_Item1, btn_Item2, btn_Item3, btn_Item4, btn_Item5]) 79 | 80 | if let btn = btn_DcPath{ 81 | view.addSubview(btn) 82 | } 83 | 84 | } 85 | 86 | func itemButtonTapped(at index: UInt) { 87 | print("你点击了第 \(index) 个按钮") 88 | } 89 | 90 | } 91 | 92 | // MARK: 钉钉 93 | extension YTCombinationAnimationViewController{ 94 | 95 | func dingDingAnimation() { 96 | 97 | let label_Home = createBtnView() 98 | 99 | let btn_UpMenu = DWBubbleMenuButton.init(frame: CGRect.init(x: kScreenW - label_Home.frame.size.width - 20, y: kScreenH - label_Home.frame.size.height - 20, width: label_Home.frame.size.width, height: label_Home.frame.size.height), expansionDirection: .DirectionUp) 100 | btn_UpMenu?.homeButtonView = label_Home 101 | btn_UpMenu?.addButtons(createBtnArray()) 102 | 103 | if let btn = btn_UpMenu{ 104 | view.addSubview(btn) 105 | } 106 | } 107 | 108 | func createBtnView() -> UILabel { 109 | 110 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) 111 | label.text = "Tap" 112 | label.textColor = UIColor.white 113 | label.textAlignment = .center 114 | label.layer.cornerRadius = label.frame.size.height / 2 115 | label.backgroundColor = UIColor.red 116 | label.clipsToBounds = true 117 | return label 118 | } 119 | 120 | func createBtnArray() -> [UIButton] { 121 | 122 | var array_Btn = [UIButton]() 123 | let array = ["A", "B", "C", "D", "E", "F", "G"] 124 | 125 | 126 | for i in 0.. 16 | 17 | - (void)itemButtonTappedAtIndex:(NSUInteger)index; 18 | 19 | @end 20 | 21 | @interface DCPathButton : UIView 22 | 23 | @property (weak, nonatomic) id delegate; 24 | 25 | @property (strong, nonatomic) NSMutableArray *itemButtonImages; 26 | @property (strong, nonatomic) NSMutableArray *itemButtonHighlightedImages; 27 | 28 | @property (strong, nonatomic) UIImage *itemButtonBackgroundImage; 29 | @property (strong, nonatomic) UIImage *itemButtonBackgroundHighlightedImage; 30 | 31 | @property (assign, nonatomic) CGFloat bloomRadius; 32 | 33 | - (id)initWithCenterImage:(UIImage *)centerImage hilightedImage:(UIImage *)centerHighlightedImage; 34 | - (void)addPathItems:(NSArray *)pathItemButtons; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/DCPathButton/DCPathCenterButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // DCPathCenterButton.h 3 | // DCPathButton 4 | // 5 | // Created by tang dixi on 30/7/14. 6 | // Copyright (c) 2014 Tangdxi. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @protocol DCPathCenterButtonDelegate 12 | 13 | - (void)centerButtonTapped; 14 | 15 | @end 16 | 17 | @interface DCPathCenterButton : UIImageView 18 | 19 | @property (weak, nonatomic) id delegate; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/DCPathButton/DCPathCenterButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // DCPathCenterButton.m 3 | // DCPathButton 4 | // 5 | // Created by tang dixi on 30/7/14. 6 | // Copyright (c) 2014 Tangdxi. All rights reserved. 7 | // 8 | 9 | #import "DCPathCenterButton.h" 10 | 11 | @implementation DCPathCenterButton 12 | 13 | - (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage 14 | { 15 | if (self = [super initWithImage:image highlightedImage:highlightedImage]) { 16 | 17 | self.userInteractionEnabled = YES; 18 | 19 | self.image = image; 20 | self.highlightedImage = highlightedImage; 21 | 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - Scale Center Button Frame to 5x 27 | 28 | - (CGRect)scaleRect:(CGRect)originRect 29 | { 30 | return CGRectMake(- originRect.size.width, 31 | - originRect.size.height, 32 | originRect.size.width * 3, 33 | originRect.size.height * 3); 34 | } 35 | 36 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 37 | { 38 | self.highlighted = YES; 39 | 40 | // Center button Begin Tapped 41 | if ([_delegate respondsToSelector:@selector(centerButtonTapped)]) { 42 | [_delegate centerButtonTapped]; 43 | } 44 | 45 | } 46 | 47 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 48 | { 49 | CGPoint currentLocation = [[touches anyObject]locationInView:self]; 50 | 51 | 52 | // Cancel button highlight when the touch location is out of 5x area 53 | // 54 | if (!CGRectContainsPoint([self scaleRect:self.bounds] , currentLocation)) { 55 | self.highlighted = NO; 56 | return ; 57 | } 58 | 59 | // If moving in the 3x area, keep the highlight state 60 | // 61 | self.highlighted = YES; 62 | } 63 | 64 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 65 | { 66 | self.highlighted = NO; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/DCPathButton/DCPathItemButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // DCPathItemButton.h 3 | // DCPathButton 4 | // 5 | // Created by tang dixi on 31/7/14. 6 | // Copyright (c) 2014 Tangdxi. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @class DCPathItemButton; 12 | 13 | @protocol DCPathItemButtonDelegate 14 | 15 | - (void)itemButtonTapped:(DCPathItemButton *)itemButton; 16 | 17 | @end 18 | 19 | @interface DCPathItemButton : UIImageView 20 | 21 | @property (assign, nonatomic) NSUInteger index; 22 | @property (weak, nonatomic) id delegate; 23 | 24 | - (id)initWithImage:(UIImage *)image 25 | highlightedImage:(UIImage *)highlightedImage 26 | backgroundImage:(UIImage *)backgroundImage 27 | backgroundHighlightedImage:(UIImage *)backgroundHighlightedImage; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/DCPathButton/DCPathItemButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // DCPathItemButton.m 3 | // DCPathButton 4 | // 5 | // Created by tang dixi on 31/7/14. 6 | // Copyright (c) 2014 Tangdxi. All rights reserved. 7 | // 8 | 9 | #import "DCPathItemButton.h" 10 | 11 | @interface DCPathItemButton () 12 | 13 | @property (strong, nonatomic) UIImageView *backgroundImageView; 14 | 15 | @end 16 | 17 | @implementation DCPathItemButton 18 | 19 | - (id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage backgroundImage:(UIImage *)backgroundImage backgroundHighlightedImage:(UIImage *)backgroundHighlightedImage 20 | { 21 | if (self = [super init]) { 22 | 23 | // Make sure the iteam has a certain frame 24 | // 25 | CGRect itemFrame = CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height); 26 | 27 | if (!backgroundImage || !backgroundHighlightedImage) { 28 | itemFrame = CGRectMake(0, 0, image.size.width, image.size.height); 29 | } 30 | self.frame = itemFrame; 31 | 32 | // Configure the item image 33 | // 34 | self.image = backgroundImage; 35 | self.highlightedImage = backgroundHighlightedImage; 36 | 37 | self.userInteractionEnabled = YES; 38 | 39 | // Configure background 40 | // 41 | _backgroundImageView = [[UIImageView alloc]initWithImage:image 42 | highlightedImage:highlightedImage]; 43 | 44 | _backgroundImageView.center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 45 | 46 | [self addSubview:_backgroundImageView]; 47 | 48 | } 49 | return self; 50 | } 51 | 52 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 53 | { 54 | self.highlighted = YES; 55 | self.backgroundImageView.highlighted = YES; 56 | } 57 | 58 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 59 | { 60 | CGPoint currentLocation = [[touches anyObject]locationInView:self]; 61 | 62 | if (! CGRectContainsPoint([self scaleRect:self.bounds], currentLocation)) { 63 | self.highlighted = NO; 64 | self.backgroundImageView.highlighted = NO; 65 | 66 | return ; 67 | } 68 | 69 | self.highlighted = YES; 70 | self.backgroundImageView.highlighted = YES; 71 | } 72 | 73 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 74 | { 75 | if ([_delegate respondsToSelector:@selector(itemButtonTapped:)]) { 76 | [_delegate itemButtonTapped:self]; 77 | } 78 | 79 | self.highlighted = NO; 80 | self.backgroundImageView.highlighted = NO; 81 | } 82 | 83 | #pragma mark - Scale Item Button 84 | 85 | - (CGRect)scaleRect:(CGRect)originRect 86 | { 87 | return CGRectMake(- originRect.size.width * 2, 88 | - originRect.size.height * 2, 89 | originRect.size.width * 5, 90 | originRect.size.height * 5); 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/Sounds/bloom.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/项目案例/弹球/Sounds/bloom.caf -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/Sounds/fold.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/项目案例/弹球/Sounds/fold.caf -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/弹球/Sounds/selected.caf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/YTAnimationDemo/项目案例/弹球/Sounds/selected.caf -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/点赞/MCFireworksButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // MCFireworksButton.h 3 | // MCFireworksButton 4 | // 5 | // Created by Matthew Cheok on 17/3/14. 6 | // Copyright (c) 2014 Matthew Cheok. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MCFireworksButton : UIButton 12 | 13 | @property (strong, nonatomic) UIImage *particleImage; 14 | @property (assign, nonatomic) CGFloat particleScale; 15 | @property (assign, nonatomic) CGFloat particleScaleRange; 16 | 17 | - (void)animate; 18 | - (void)popOutsideWithDuration:(NSTimeInterval)duration; 19 | - (void)popInsideWithDuration:(NSTimeInterval)duration; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/点赞/MCFireworksButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // MCFireworksButton.m 3 | // MCFireworksButton 4 | // 5 | // Created by Matthew Cheok on 17/3/14. 6 | // Copyright (c) 2014 Matthew Cheok. All rights reserved. 7 | // 8 | 9 | #import "MCFireworksButton.h" 10 | #import "MCFireworksView.h" 11 | 12 | @interface MCFireworksButton () 13 | 14 | @property (strong, nonatomic) MCFireworksView *fireworksView; 15 | 16 | @end 17 | 18 | @implementation MCFireworksButton 19 | 20 | - (void)setup { 21 | self.clipsToBounds = NO; 22 | 23 | _fireworksView = [[MCFireworksView alloc] init]; 24 | [self insertSubview:_fireworksView atIndex:0]; 25 | } 26 | 27 | - (id)initWithFrame:(CGRect)frame { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | [self setup]; 31 | } 32 | return self; 33 | } 34 | 35 | - (id)initWithCoder:(NSCoder *)aDecoder { 36 | self = [super initWithCoder:aDecoder]; 37 | if (self) { 38 | [self setup]; 39 | } 40 | return self; 41 | } 42 | 43 | - (void)layoutSubviews { 44 | [super layoutSubviews]; 45 | self.fireworksView.frame = self.bounds; 46 | 47 | [self insertSubview:self.fireworksView atIndex:0]; 48 | } 49 | 50 | #pragma mark - Methods 51 | 52 | - (void)animate { 53 | [self.fireworksView animate]; 54 | } 55 | 56 | - (void)popOutsideWithDuration:(NSTimeInterval)duration { 57 | __weak typeof(self) weakSelf = self; 58 | self.transform = CGAffineTransformIdentity; 59 | [UIView animateKeyframesWithDuration:duration delay:0 options:0 animations: ^{ 60 | [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1 / 3.0 animations: ^{ 61 | typeof(self) strongSelf = weakSelf; 62 | strongSelf.transform = CGAffineTransformMakeScale(1.5, 1.5); 63 | }]; 64 | [UIView addKeyframeWithRelativeStartTime:1/3.0 relativeDuration:1/3.0 animations: ^{ 65 | typeof(self) strongSelf = weakSelf; 66 | strongSelf.transform = CGAffineTransformMakeScale(0.8, 0.8); 67 | }]; 68 | [UIView addKeyframeWithRelativeStartTime:2/3.0 relativeDuration:1/3.0 animations: ^{ 69 | typeof(self) strongSelf = weakSelf; 70 | strongSelf.transform = CGAffineTransformMakeScale(1.0, 1.0); 71 | }]; 72 | } completion:nil]; 73 | } 74 | 75 | - (void)popInsideWithDuration:(NSTimeInterval)duration { 76 | __weak typeof(self) weakSelf = self; 77 | self.transform = CGAffineTransformIdentity; 78 | [UIView animateKeyframesWithDuration:duration delay:0 options:0 animations: ^{ 79 | [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1 / 2.0 animations: ^{ 80 | typeof(self) strongSelf = weakSelf; 81 | strongSelf.transform = CGAffineTransformMakeScale(0.8, 0.8); 82 | }]; 83 | [UIView addKeyframeWithRelativeStartTime:1/2.0 relativeDuration:1/2.0 animations: ^{ 84 | typeof(self) strongSelf = weakSelf; 85 | strongSelf.transform = CGAffineTransformMakeScale(1.0, 1.0); 86 | }]; 87 | } completion:nil]; 88 | } 89 | 90 | #pragma mark - Properties 91 | 92 | - (UIImage *)particleImage { 93 | return self.fireworksView.particleImage; 94 | } 95 | 96 | - (void)setParticleImage:(UIImage *)particleImage { 97 | self.fireworksView.particleImage = particleImage; 98 | } 99 | 100 | - (CGFloat)particleScale { 101 | return self.fireworksView.particleScale; 102 | } 103 | 104 | - (void)setParticleScale:(CGFloat)particleScale { 105 | self.fireworksView.particleScale = particleScale; 106 | } 107 | 108 | - (CGFloat)particleScaleRange { 109 | return self.fireworksView.particleScaleRange; 110 | } 111 | 112 | - (void)setParticleScaleRange:(CGFloat)particleScaleRange { 113 | self.fireworksView.particleScaleRange = particleScaleRange; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/点赞/MCFireworksView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MCFireworksView.h 3 | // MCFireworksButton 4 | // 5 | // Created by Matthew Cheok on 17/3/14. 6 | // Copyright (c) 2014 Matthew Cheok. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MCFireworksView : UIView 12 | 13 | @property (strong, nonatomic) UIImage *particleImage; 14 | @property (assign, nonatomic) CGFloat particleScale; 15 | @property (assign, nonatomic) CGFloat particleScaleRange; 16 | 17 | - (void)animate; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/点赞/MCFireworksView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MCFireworksView.m 3 | // MCFireworksButton 4 | // 5 | // Created by Matthew Cheok on 17/3/14. 6 | // Copyright (c) 2014 Matthew Cheok. All rights reserved. 7 | // 8 | 9 | #import "MCFireworksView.h" 10 | 11 | @interface MCFireworksView () 12 | 13 | @property (strong, nonatomic) NSArray *emitterCells; 14 | @property (strong, nonatomic) CAEmitterLayer *chargeLayer; 15 | @property (strong, nonatomic) CAEmitterLayer *explosionLayer; 16 | 17 | @end 18 | 19 | @implementation MCFireworksView 20 | 21 | - (void)setup { 22 | self.clipsToBounds = NO; 23 | self.userInteractionEnabled = NO; 24 | 25 | CAEmitterCell *explosionCell = [CAEmitterCell emitterCell]; 26 | explosionCell.name = @"explosion"; 27 | explosionCell.alphaRange = 0.20; 28 | explosionCell.alphaSpeed = -1.0; 29 | 30 | explosionCell.lifetime = 0.7; 31 | explosionCell.lifetimeRange = 0.3; 32 | explosionCell.birthRate = 0; 33 | explosionCell.velocity = 40.00; 34 | explosionCell.velocityRange = 10.00; 35 | 36 | _explosionLayer = [CAEmitterLayer layer]; 37 | _explosionLayer.name = @"emitterLayer"; 38 | _explosionLayer.emitterShape = kCAEmitterLayerCircle; 39 | _explosionLayer.emitterMode = kCAEmitterLayerOutline; 40 | _explosionLayer.emitterSize = CGSizeMake(25, 0); 41 | _explosionLayer.emitterCells = @[explosionCell]; 42 | _explosionLayer.renderMode = kCAEmitterLayerOldestFirst; 43 | _explosionLayer.masksToBounds = NO; 44 | _explosionLayer.seed = 1366128504; 45 | [self.layer addSublayer:_explosionLayer]; 46 | 47 | CAEmitterCell *chargeCell = [CAEmitterCell emitterCell]; 48 | chargeCell.name = @"charge"; 49 | chargeCell.alphaRange = 0.20; 50 | chargeCell.alphaSpeed = -1.0; 51 | 52 | chargeCell.lifetime = 0.3; 53 | chargeCell.lifetimeRange = 0.1; 54 | chargeCell.birthRate = 0; 55 | chargeCell.velocity = -40.0; 56 | chargeCell.velocityRange = 0.00; 57 | 58 | _chargeLayer = [CAEmitterLayer layer]; 59 | _chargeLayer.name = @"emitterLayer"; 60 | _chargeLayer.emitterShape = kCAEmitterLayerCircle; 61 | _chargeLayer.emitterMode = kCAEmitterLayerOutline; 62 | _chargeLayer.emitterSize = CGSizeMake(25, 0); 63 | _chargeLayer.emitterCells = @[chargeCell]; 64 | _chargeLayer.renderMode = kCAEmitterLayerOldestFirst; 65 | _chargeLayer.masksToBounds = NO; 66 | _chargeLayer.seed = 1366128504; 67 | [self.layer addSublayer:_chargeLayer]; 68 | 69 | self.emitterCells = @[chargeCell, explosionCell]; 70 | } 71 | 72 | - (id)initWithFrame:(CGRect)frame { 73 | self = [super initWithFrame:frame]; 74 | if (self) { 75 | [self setup]; 76 | } 77 | return self; 78 | } 79 | 80 | - (id)initWithCoder:(NSCoder *)aDecoder { 81 | self = [super initWithCoder:aDecoder]; 82 | if (self) { 83 | [self setup]; 84 | } 85 | return self; 86 | } 87 | 88 | - (void)layoutSubviews { 89 | [super layoutSubviews]; 90 | CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 91 | self.chargeLayer.emitterPosition = center; 92 | self.explosionLayer.emitterPosition = center; 93 | } 94 | 95 | #pragma mark - Methods 96 | 97 | - (void)animate { 98 | self.chargeLayer.beginTime = CACurrentMediaTime(); 99 | [self.chargeLayer setValue:@80 forKeyPath:@"emitterCells.charge.birthRate"]; 100 | [self performSelector:@selector(explode) withObject:nil afterDelay:0.2]; 101 | } 102 | 103 | - (void)explode { 104 | [self.chargeLayer setValue:@0 forKeyPath:@"emitterCells.charge.birthRate"]; 105 | self.explosionLayer.beginTime = CACurrentMediaTime(); 106 | [self.explosionLayer setValue:@500 forKeyPath:@"emitterCells.explosion.birthRate"]; 107 | [self performSelector:@selector(stop) withObject:nil afterDelay:0.1]; 108 | } 109 | 110 | - (void)stop { 111 | [self.chargeLayer setValue:@0 forKeyPath:@"emitterCells.charge.birthRate"]; 112 | [self.explosionLayer setValue:@0 forKeyPath:@"emitterCells.explosion.birthRate"]; 113 | } 114 | 115 | #pragma mark - Properties 116 | 117 | - (void)setParticleImage:(UIImage *)particleImage { 118 | _particleImage = particleImage; 119 | for (CAEmitterCell *cell in self.emitterCells) { 120 | cell.contents = (id)[particleImage CGImage]; 121 | } 122 | } 123 | 124 | - (void)setParticleScale:(CGFloat)particleScale { 125 | _particleScale = particleScale; 126 | for (CAEmitterCell *cell in self.emitterCells) { 127 | cell.scale = particleScale; 128 | } 129 | } 130 | 131 | - (void)setParticleScaleRange:(CGFloat)particleScaleRange { 132 | _particleScaleRange = particleScaleRange; 133 | for (CAEmitterCell *cell in self.emitterCells) { 134 | cell.scaleRange = particleScaleRange; 135 | } 136 | } 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/进度/YTProgressView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YTProgressView.swift 3 | // YTAnimationDemo 4 | // 5 | // Created by YTiOSer on 18/5/28. 6 | // Copyright © 2018 YTiOSer. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class YTProgressView: UIView { 12 | 13 | fileprivate var label_Progress: UILabel! //显示progress数 14 | fileprivate var num_Progress: Int = 0 //动画显示进度 15 | fileprivate var progress: Int = 0 //设置progress 16 | fileprivate var layer_Gradient: CAGradientLayer! //渐变色layer 17 | fileprivate var width_MainPath: CGFloat = 0.0 // 进度条宽 18 | fileprivate var layer_BackPath: CAShapeLayer! // 进度里圈layer CAShapeLayer GPU执行 19 | fileprivate var layer_MainPathLayer: CAShapeLayer! //外圈layer 20 | fileprivate var timer_ProgressLabel: Timer! 21 | 22 | override init(frame: CGRect) { 23 | super.init(frame: frame) 24 | 25 | } 26 | 27 | convenience init(progress: Int, width: CGFloat) { 28 | self.init(frame: CGRect.zero) 29 | self.progress = progress 30 | self.width_MainPath = width 31 | 32 | createView() 33 | drawCircle() 34 | } 35 | 36 | required init?(coder aDecoder: NSCoder) { 37 | fatalError("init(coder:) has not been implemented") 38 | } 39 | 40 | } 41 | 42 | 43 | extension YTProgressView { 44 | 45 | func drawCircle(){ 46 | 47 | //贝塞尔曲线画圆 48 | let path_Back = UIBezierPath.init(arcCenter: CGPoint.init(x: kScreenW / 2, y: kScreenH / 2), radius: kScreenW / 5 - width_MainPath, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3, clockwise: true) 49 | let path_Main = UIBezierPath.init(arcCenter: CGPoint.init(x: kScreenW / 2, y: kScreenH / 2), radius: kScreenW / 5 - width_MainPath + 3, startAngle: CGFloat.pi, endAngle: CGFloat.pi * 3, clockwise: true) 50 | 51 | layer_BackPath.path = path_Back.cgPath 52 | layer_MainPathLayer.path = path_Main.cgPath 53 | 54 | layer_Gradient.mask = layer_MainPathLayer //用 layer_MainPathLayer 截取渐变层 55 | 56 | //动画 显示路径 57 | let animation = CABasicAnimation.init(keyPath: "strokeEnd") 58 | animation.duration = CFTimeInterval(Double(progress) * 0.01) 59 | animation.fromValue = NSNumber.init(value: 0) 60 | animation.toValue = NSNumber.init(value: Double(progress) * 0.01) 61 | animation.fillMode = "forwards" 62 | animation.isRemovedOnCompletion = false //完成后不删除动画 63 | layer_MainPathLayer.add(animation, forKey: "strokeEndAnimation") 64 | 65 | if progress > 0{ 66 | DispatchQueue.global().async { 67 | self.timer_ProgressLabel = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(YTProgressView.progressLabelTimerAction), userInfo: nil, repeats: true) 68 | RunLoop.current.run() 69 | } 70 | }else{ 71 | label_Progress.text = "0%" 72 | } 73 | 74 | } 75 | 76 | func progressLabelTimerAction() { 77 | 78 | DispatchQueue.main.async { 79 | self.label_Progress.text = String(self.num_Progress) + "%" 80 | } 81 | 82 | if num_Progress >= progress{ //销毁计时器 83 | timer_ProgressLabel.invalidate() 84 | timer_ProgressLabel = nil 85 | }else{ 86 | num_Progress += 1 87 | } 88 | 89 | } 90 | 91 | } 92 | 93 | 94 | extension YTProgressView { 95 | 96 | func createView() { 97 | 98 | label_Progress = UILabel() 99 | label_Progress.text = "" 100 | label_Progress.textAlignment = .center 101 | label_Progress.font = UIFont.systemFont(ofSize: 25) 102 | addSubview(label_Progress) 103 | label_Progress.snp.makeConstraints { (make) in 104 | make.centerX.centerY.equalTo(self) 105 | make.width.equalTo(kScreenW) 106 | make.height.equalTo(30) 107 | } 108 | 109 | layer_BackPath = CAShapeLayer() 110 | layer_BackPath.fillColor = UIColor.clear.cgColor //填充颜色 111 | layer_BackPath.strokeColor = UIColor.white.withAlphaComponent(0.5).cgColor //划线颜色 112 | layer_BackPath.lineWidth = width_MainPath 113 | layer.addSublayer(layer_BackPath) 114 | 115 | layer_MainPathLayer = CAShapeLayer() 116 | layer_MainPathLayer.fillColor = UIColor.clear.cgColor 117 | layer_MainPathLayer.strokeColor = UIColor.white.cgColor 118 | layer_MainPathLayer.lineWidth = width_MainPath 119 | layer.addSublayer(layer_MainPathLayer) 120 | 121 | //渐变色 122 | layer_Gradient = CAGradientLayer() 123 | layer_Gradient.frame = CGRect.init(x: 0, y: 0, width: kScreenW, height: kScreenH) 124 | layer_Gradient.type = "axial" //线性变化 默认目前只有这一个type 125 | layer_Gradient.colors = [UIColor.init(hex: 0xf31414).cgColor, UIColor.init(hex: 0xf27200).cgColor, UIColor.init(hex: 0xffff00).cgColor, UIColor.init(hex: 0x2bee22).cgColor, UIColor.init(hex: 0x32a7eb).cgColor] 126 | layer_Gradient.locations = [0, 0.3, 0.5, 0.7, 1] //每个渐变颜色的终止位置,这些值必须是递增的,数组的长度和colors的长度最好一致 127 | //startPoint endPoint 分别表示渐变层的起始位置和终止位置,这两个点被定义在一个单元坐标空间,[0,0]表示左上角位置,[1,1]表示右下角位置,默认值分别是[.5,0] and [.5,1]; 128 | layer_Gradient.startPoint = CGPoint.init(x: 0, y: 0) 129 | layer_Gradient.endPoint = CGPoint.init(x: 1, y: 0) 130 | layer.addSublayer(layer_Gradient) 131 | 132 | } 133 | 134 | } 135 | 136 | // MARK: UIColor extension 137 | extension UIColor { 138 | 139 | convenience init(hex: Int32) { 140 | let r = CGFloat(((hex & 0xFF0000) >> 16)) / 255.0 141 | let g = CGFloat(((hex & 0x00FF00) >> 8)) / 255.0 142 | let b = CGFloat(hex & 0x0000FF) / 255.0 143 | 144 | self.init(red: r, green: g, blue: b, alpha: 1.0) 145 | } 146 | 147 | } 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /YTAnimationDemo/项目案例/钉钉/DWBubbleMenuButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // DWBubbleMenuButton.h 3 | // DWBubbleMenuButtonExample 4 | // 5 | // Created by Derrick Walker on 10/8/14. 6 | // Copyright (c) 2014 Derrick Walker. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, ExpansionDirection) { 12 | DirectionLeft = 0, 13 | DirectionRight, 14 | DirectionUp, 15 | DirectionDown 16 | }; 17 | 18 | 19 | @class DWBubbleMenuButton; 20 | 21 | @protocol DWBubbleMenuViewDelegate 22 | 23 | @optional 24 | - (void)bubbleMenuButtonWillExpand:(DWBubbleMenuButton *)expandableView; 25 | - (void)bubbleMenuButtonDidExpand:(DWBubbleMenuButton *)expandableView; 26 | - (void)bubbleMenuButtonWillCollapse:(DWBubbleMenuButton *)expandableView; 27 | - (void)bubbleMenuButtonDidCollapse:(DWBubbleMenuButton *)expandableView; 28 | 29 | @end 30 | 31 | @interface DWBubbleMenuButton : UIView 32 | 33 | @property (nonatomic, weak, readonly) NSArray *buttons; 34 | @property (nonatomic, strong) UIView *homeButtonView; 35 | @property (nonatomic, readonly) BOOL isCollapsed; 36 | @property (nonatomic, weak) id delegate; 37 | 38 | // The direction in which the menu expands 39 | @property (nonatomic) enum ExpansionDirection direction; 40 | 41 | // Indicates whether the home button will animate it's touch highlighting, this is enabled by default 42 | @property (nonatomic) BOOL animatedHighlighting; 43 | 44 | // Indicates whether menu should collapse after a button selection, this is enabled by default 45 | @property (nonatomic) BOOL collapseAfterSelection; 46 | 47 | // The duration of the expand/collapse animation 48 | @property (nonatomic) float animationDuration; 49 | 50 | // The default alpha of the homeButtonView when not tapped 51 | @property (nonatomic) float standbyAlpha; 52 | 53 | // The highlighted alpha of the homeButtonView when tapped 54 | @property (nonatomic) float highlightAlpha; 55 | 56 | // The spacing between menu buttons when expanded 57 | @property (nonatomic) float buttonSpacing; 58 | 59 | // Initializers 60 | - (id)initWithFrame:(CGRect)frame expansionDirection:(ExpansionDirection)direction; 61 | 62 | // Public Methods 63 | - (void)addButtons:(NSArray *)buttons; 64 | - (void)addButton:(UIButton *)button; 65 | - (void)showButtons; 66 | - (void)dismissButtons; 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /images/tanqiu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/tanqiu.gif -------------------------------------------------------------------------------- /images/抖动.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/抖动.gif -------------------------------------------------------------------------------- /images/旋转.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/旋转.gif -------------------------------------------------------------------------------- /images/点赞.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/点赞.gif -------------------------------------------------------------------------------- /images/组动画2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/组动画2.gif -------------------------------------------------------------------------------- /images/过渡动画.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/过渡动画.gif -------------------------------------------------------------------------------- /images/进度条.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YTiOSer/YTAnimation/8d5438674d7574b8a6542469a0558b4bead93f50/images/进度条.gif --------------------------------------------------------------------------------