├── ReadMe └── pathScreen.gif ├── Assets.xcassets ├── Contents.json ├── main_buy.imageset │ ├── main_buy@2x.png │ └── Contents.json ├── main_rent.imageset │ ├── main_rent@2x.png │ └── Contents.json ├── main_share.imageset │ ├── main_share@2x.png │ └── Contents.json ├── main_zhuan.imageset │ ├── main_zhuan@2x.png │ └── Contents.json ├── main_letOut.imageset │ ├── main_letOut@2x.png │ └── Contents.json ├── main_near_null.imageset │ ├── main_near_null@2x.png │ └── Contents.json ├── main_path_shop.imageset │ ├── main_path_shop@2x.png │ └── Contents.json ├── main_image_shop.imageset │ ├── main_image_shop@2x.png │ └── Contents.json ├── main_overllsell.imageset │ ├── main_overllsell@2x.png │ └── Contents.json ├── main_Path_workshop.imageset │ ├── main_Path_workshop@2x.png │ └── Contents.json ├── main_image_building.imageset │ ├── main_image_building@2x.png │ └── Contents.json ├── main_image_business.imageset │ ├── main_image_business@2x.png │ └── Contents.json ├── main_image_workshop.imageset │ ├── main_image_workshop@2x.png │ └── Contents.json ├── main_path_building.imageset │ ├── main_path_building@2x.png │ └── Contents.json ├── main_path_business.imageset │ ├── main_path_business@2x.png │ └── Contents.json ├── main_image_arrow_down.imageset │ ├── main_image_arrow_down@2x.png │ └── Contents.json └── AppIcon.appiconset │ └── Contents.json ├── README.md ├── ESPathIconView ├── get_notification.wav ├── ESPathIcon.h ├── ESPathIconAnimationView.h ├── ESPathIcon.m └── ESPathIconAnimationView.m ├── TPathIconAnimation.xcdatamodeld ├── .xccurrentversion └── TPathIconAnimation.xcdatamodel │ └── contents ├── ViewController.h ├── main.m ├── Commen └── TCommen.h ├── TPathIconAnimation.pch ├── AppDelegate.h ├── ESView ├── UIViewExt.h └── UIViewExt.m ├── Helper ├── THelper.h └── THelper.m ├── Info.plist ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── AppDelegate.m └── ViewController.m /ReadMe/pathScreen.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/ReadMe/pathScreen.gif -------------------------------------------------------------------------------- /Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TPathIconAnimation 2 | ![image](https://github.com/tikeyc/TPathIconAnimation/raw/master/ReadMe/pathScreen.gif) 3 | -------------------------------------------------------------------------------- /ESPathIconView/get_notification.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/ESPathIconView/get_notification.wav -------------------------------------------------------------------------------- /Assets.xcassets/main_buy.imageset/main_buy@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_buy.imageset/main_buy@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_rent.imageset/main_rent@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_rent.imageset/main_rent@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_share.imageset/main_share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_share.imageset/main_share@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_zhuan.imageset/main_zhuan@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_zhuan.imageset/main_zhuan@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_letOut.imageset/main_letOut@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_letOut.imageset/main_letOut@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_near_null.imageset/main_near_null@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_near_null.imageset/main_near_null@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_path_shop.imageset/main_path_shop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_path_shop.imageset/main_path_shop@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_image_shop.imageset/main_image_shop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_image_shop.imageset/main_image_shop@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_overllsell.imageset/main_overllsell@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_overllsell.imageset/main_overllsell@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_Path_workshop.imageset/main_Path_workshop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_Path_workshop.imageset/main_Path_workshop@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_image_building.imageset/main_image_building@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_image_building.imageset/main_image_building@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_image_business.imageset/main_image_business@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_image_business.imageset/main_image_business@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_image_workshop.imageset/main_image_workshop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_image_workshop.imageset/main_image_workshop@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_path_building.imageset/main_path_building@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_path_building.imageset/main_path_building@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_path_business.imageset/main_path_business@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_path_business.imageset/main_path_business@2x.png -------------------------------------------------------------------------------- /Assets.xcassets/main_image_arrow_down.imageset/main_image_arrow_down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikeyc/TPathIconAnimation/HEAD/Assets.xcassets/main_image_arrow_down.imageset/main_image_arrow_down@2x.png -------------------------------------------------------------------------------- /TPathIconAnimation.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | TPathIconAnimation.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TPathIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | - (IBAction)typeButtonActions:(UIButton *)sender; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TPathIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TPathIconAnimation.xcdatamodeld/TPathIconAnimation.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Assets.xcassets/main_buy.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_buy@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_rent.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_rent@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_letOut.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_letOut@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_share@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_zhuan.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_zhuan@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_near_null.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_near_null@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_path_shop.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_path_shop@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_image_shop.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_image_shop@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_overllsell.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_overllsell@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_Path_workshop.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_Path_workshop@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_image_building.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_image_building@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_image_business.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_image_business@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_image_workshop.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_image_workshop@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_path_building.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_path_building@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_path_business.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_path_business@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 | } -------------------------------------------------------------------------------- /Assets.xcassets/main_image_arrow_down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "main_image_arrow_down@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 | } -------------------------------------------------------------------------------- /Commen/TCommen.h: -------------------------------------------------------------------------------- 1 | // 2 | // TCommen.h 3 | // TLaunchScreenAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #ifndef TCommen_h 10 | #define TCommen_h 11 | 12 | #define RGBColor(r, g, b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1] 13 | #define RGBColorA(r, g, b, a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a] 14 | #define kScreenWidth [[UIScreen mainScreen] bounds].size.width 15 | #define kScreenHeight [[UIScreen mainScreen] bounds].size.height 16 | 17 | 18 | #endif /* TCommen_h */ 19 | -------------------------------------------------------------------------------- /TPathIconAnimation.pch: -------------------------------------------------------------------------------- 1 | // 2 | // TPathIconAnimation.pch 3 | // TPathIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #ifndef TPathIconAnimation_pch 10 | #define TPathIconAnimation_pch 11 | 12 | // Include any system framework and library headers here that should be included in all compilation units. 13 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 14 | 15 | #import "TCommen.h" 16 | #import "UIViewExt.h" 17 | #import "THelper.h" 18 | 19 | #endif /* TPathIconAnimation_pch */ 20 | -------------------------------------------------------------------------------- /AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TPathIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 17 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 18 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 19 | 20 | - (void)saveContext; 21 | - (NSURL *)applicationDocumentsDirectory; 22 | 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /ESView/UIViewExt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Erica Sadun, http://ericasadun.com 3 | iPhone Developer's Cookbook, 3.0 Edition 4 | BSD License, Use at your own risk 5 | */ 6 | 7 | #import 8 | 9 | CGPoint CGRectGetCenter(CGRect rect); 10 | CGRect CGRectMoveToCenter(CGRect rect, CGPoint center); 11 | 12 | @interface UIView (ViewFrameGeometry) 13 | @property CGPoint origin; 14 | @property CGSize size; 15 | 16 | @property (readonly) CGPoint bottomLeft; 17 | @property (readonly) CGPoint bottomRight; 18 | @property (readonly) CGPoint topRight; 19 | 20 | @property CGFloat height; 21 | @property CGFloat width; 22 | 23 | @property CGFloat top; 24 | @property CGFloat left; 25 | 26 | @property CGFloat bottom; 27 | @property CGFloat right; 28 | 29 | - (void) moveBy: (CGPoint) delta; 30 | - (void) scaleBy: (CGFloat) scaleFactor; 31 | - (void) fitInSize: (CGSize) aSize; 32 | @end -------------------------------------------------------------------------------- /ESPathIconView/ESPathIcon.h: -------------------------------------------------------------------------------- 1 | // 2 | // ESPathIconView.h 3 | // Estate 4 | // 5 | // Created by tikeyc on 14-5-23. 6 | // Copyright (c) 2014年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void (^CliciIconBlock) (id result); 12 | 13 | @interface ESPathIcon : UIView 14 | 15 | { 16 | CGPoint _startPoint; 17 | CGPoint _nearbyPoint; 18 | CGPoint _farPoint; 19 | CGPoint _endPoint; 20 | CAKeyframeAnimation *_animation; 21 | } 22 | @property (nonatomic,assign)CGPoint startPoint; 23 | @property (nonatomic,assign)CGPoint nearbyPoint; 24 | @property (nonatomic,assign)CGPoint farPoint; 25 | @property (nonatomic,assign)CGPoint endPoint; 26 | @property (nonatomic,strong)CAKeyframeAnimation *animation; 27 | @property (nonatomic,copy)CliciIconBlock block; 28 | 29 | - (id)initWithImageName:(NSString *)imageName withLabelTitle:(NSString *)title; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ESPathIconView/ESPathIconAnimationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ESPathIconAnimationView.h 3 | // Estate 4 | // 5 | // Created by tikeyc on 14-5-23. 6 | // Copyright (c) 2014年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define animation_Time 0.6 12 | #define animation_Time_Gap 0.1 13 | 14 | typedef enum { 15 | BUSINESS = 0, 16 | SHOP, 17 | BUILDING, 18 | WORKSHOP 19 | } ShopType; 20 | 21 | @class ESPathIconAnimationView; 22 | 23 | @protocol ESPathIconAnimationViewDelegate 24 | 25 | - (void)selectedIconIndex:(int)index withType:(ShopType)shopType; 26 | 27 | @end 28 | 29 | @interface ESPathIconAnimationView : UIView 30 | 31 | 32 | @property (nonatomic,weak)id delegate; 33 | 34 | @property (nonatomic,assign)BOOL isOpenIcon; 35 | 36 | 37 | - (id)initWithFrame:(CGRect)frame withShowType:(ShopType)type; 38 | 39 | - (void)addAnimationToIcon; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Helper/THelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // THelper.h 3 | // THomeIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface THelper : NSObject 12 | 13 | 14 | + (UILabel *)labelWithFrame:(CGRect)frame 15 | text:(NSString *)text 16 | textColor:(UIColor *)color 17 | textAlignment:(NSTextAlignment)alignment 18 | font:(UIFont *)font; 19 | 20 | + (UIButton *)buttonsetIamgeWithFrame:(CGRect)frame 21 | nfile:(NSString *)nfileName 22 | sfile:(NSString *)sfileName 23 | tag:(NSInteger)buttonTag 24 | action:(SEL)action; 25 | 26 | + (NSMutableArray *)exchangeArrayItem:(NSMutableArray *)array; 27 | 28 | 29 | + (float)huDuFromdu:(float)du; 30 | + (float)sin:(float)du; 31 | + (float)cos:(float)du; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ESPathIconView/ESPathIcon.m: -------------------------------------------------------------------------------- 1 | // 2 | // ESPathIconView.m 3 | // Estate 4 | // 5 | // Created by tikeyc on 14-5-23. 6 | // Copyright (c) 2014年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import "ESPathIcon.h" 10 | 11 | @implementation ESPathIcon 12 | 13 | { 14 | UIImage *_image; 15 | NSString *_title; 16 | } 17 | 18 | - (id)initWithImageName:(NSString *)imageName withLabelTitle:(NSString *)title{ 19 | self = [super init]; 20 | if (self) { 21 | _image = [UIImage imageNamed:imageName]; 22 | _title = title; 23 | self.bounds = CGRectMake(0, 0, _image.size.width, _image.size.height + 6 + 13); 24 | [self initSubViews]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)initSubViews{ 30 | // 31 | UIButton *iconButton = [UIButton buttonWithType:UIButtonTypeCustom]; 32 | iconButton.frame = CGRectMake(0, 0, _image.size.width, _image.size.height); 33 | [iconButton setImage:_image forState:UIControlStateNormal]; 34 | iconButton.showsTouchWhenHighlighted = YES; 35 | [iconButton addTarget:self action:@selector(clickIcon:) forControlEvents:UIControlEventTouchUpInside]; 36 | [self addSubview:iconButton]; 37 | // 38 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, iconButton.bottom + 6, iconButton.width, 13)]; 39 | label.backgroundColor = [UIColor clearColor]; 40 | label.font = [UIFont systemFontOfSize:13.0f]; 41 | label.textColor = RGBColor(255, 255, 255); 42 | label.textAlignment = NSTextAlignmentCenter; 43 | label.text = _title; 44 | label.layer.shadowOffset = CGSizeMake(5, 5); 45 | label.layer.shadowOpacity = 0.5; 46 | [self addSubview:label]; 47 | } 48 | 49 | #pragma mark - Actions method 50 | 51 | 52 | - (void)clickIcon:(UIButton *)button{ 53 | if (self.block) { 54 | self.block(self); 55 | } 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Helper/THelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // THelper.m 3 | // THomeIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import "THelper.h" 10 | 11 | @implementation THelper 12 | 13 | 14 | + (UILabel *)labelWithFrame:(CGRect)frame 15 | text:(NSString *)text 16 | textColor:(UIColor *)color 17 | textAlignment:(NSTextAlignment)alignment 18 | font:(UIFont *)font 19 | { 20 | UILabel *label = [[UILabel alloc] initWithFrame:frame]; 21 | label.text = text; 22 | label.textColor = color; 23 | label.textAlignment = alignment; 24 | label.font = font; 25 | label.backgroundColor = [UIColor clearColor]; 26 | return label; 27 | } 28 | 29 | + (UIButton *)buttonsetIamgeWithFrame:(CGRect)frame 30 | nfile:(NSString *)nfileName 31 | sfile:(NSString *)sfileName 32 | tag:(NSInteger)buttonTag 33 | action:(SEL)action 34 | { 35 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 36 | [button setFrame:frame]; 37 | [button setImage:[UIImage imageNamed:nfileName] forState:UIControlStateNormal]; 38 | [button setImage:[UIImage imageNamed:sfileName] forState:UIControlStateHighlighted]; 39 | [button setTag:buttonTag]; 40 | [button addTarget:nil action:action forControlEvents:UIControlEventTouchUpInside]; 41 | return button; 42 | } 43 | 44 | + (NSMutableArray *)exchangeArrayItem:(NSMutableArray *)array{ 45 | for (int i = 0; i < array.count/2; i++) { 46 | [array exchangeObjectAtIndex:i withObjectAtIndex:array.count -1 - i]; 47 | } 48 | return array; 49 | } 50 | 51 | #pragma mark 度转弧度 52 | + (float)huDuFromdu:(float)du 53 | { 54 | return M_PI/(180/du); 55 | } 56 | 57 | #pragma mark 计算sin 58 | + (float)sin:(float)du 59 | { 60 | return sinf(M_PI/(180/du)); 61 | } 62 | 63 | #pragma mark 计算cos 64 | + (float)cos:(float)du 65 | { 66 | return cosf(M_PI/(180/du)); 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ESView/UIViewExt.m: -------------------------------------------------------------------------------- 1 | /* 2 | Erica Sadun, http://ericasadun.com 3 | iPhone Developer's Cookbook, 3.0 Edition 4 | BSD License, Use at your own risk 5 | */ 6 | 7 | #import "UIViewExt.h" 8 | 9 | CGPoint CGRectGetCenter(CGRect rect) 10 | { 11 | CGPoint pt; 12 | pt.x = CGRectGetMidX(rect); 13 | pt.y = CGRectGetMidY(rect); 14 | return pt; 15 | } 16 | 17 | CGRect CGRectMoveToCenter(CGRect rect, CGPoint center) 18 | { 19 | CGRect newrect = CGRectZero; 20 | newrect.origin.x = center.x-CGRectGetMidX(rect); 21 | newrect.origin.y = center.y-CGRectGetMidY(rect); 22 | newrect.size = rect.size; 23 | return newrect; 24 | } 25 | 26 | @implementation UIView (ViewGeometry) 27 | 28 | // Retrieve and set the origin 29 | - (CGPoint) origin 30 | { 31 | return self.frame.origin; 32 | } 33 | 34 | - (void) setOrigin: (CGPoint) aPoint 35 | { 36 | CGRect newframe = self.frame; 37 | newframe.origin = aPoint; 38 | self.frame = newframe; 39 | } 40 | 41 | 42 | // Retrieve and set the size 43 | - (CGSize) size 44 | { 45 | return self.frame.size; 46 | } 47 | 48 | - (void) setSize: (CGSize) aSize 49 | { 50 | CGRect newframe = self.frame; 51 | newframe.size = aSize; 52 | self.frame = newframe; 53 | } 54 | 55 | // Query other frame locations 56 | - (CGPoint) bottomRight 57 | { 58 | CGFloat x = self.frame.origin.x + self.frame.size.width; 59 | CGFloat y = self.frame.origin.y + self.frame.size.height; 60 | return CGPointMake(x, y); 61 | } 62 | 63 | - (CGPoint) bottomLeft 64 | { 65 | CGFloat x = self.frame.origin.x; 66 | CGFloat y = self.frame.origin.y + self.frame.size.height; 67 | return CGPointMake(x, y); 68 | } 69 | 70 | - (CGPoint) topRight 71 | { 72 | CGFloat x = self.frame.origin.x + self.frame.size.width; 73 | CGFloat y = self.frame.origin.y; 74 | return CGPointMake(x, y); 75 | } 76 | 77 | 78 | // Retrieve and set height, width, top, bottom, left, right 79 | - (CGFloat) height 80 | { 81 | return self.frame.size.height; 82 | } 83 | 84 | - (void) setHeight: (CGFloat) newheight 85 | { 86 | CGRect newframe = self.frame; 87 | newframe.size.height = newheight; 88 | self.frame = newframe; 89 | } 90 | 91 | - (CGFloat) width 92 | { 93 | return self.frame.size.width; 94 | } 95 | 96 | - (void) setWidth: (CGFloat) newwidth 97 | { 98 | CGRect newframe = self.frame; 99 | newframe.size.width = newwidth; 100 | self.frame = newframe; 101 | } 102 | 103 | - (CGFloat) top 104 | { 105 | return self.frame.origin.y; 106 | } 107 | 108 | - (void) setTop: (CGFloat) newtop 109 | { 110 | CGRect newframe = self.frame; 111 | newframe.origin.y = newtop; 112 | self.frame = newframe; 113 | } 114 | 115 | - (CGFloat) left 116 | { 117 | return self.frame.origin.x; 118 | } 119 | 120 | - (void) setLeft: (CGFloat) newleft 121 | { 122 | CGRect newframe = self.frame; 123 | newframe.origin.x = newleft; 124 | self.frame = newframe; 125 | } 126 | 127 | - (CGFloat) bottom 128 | { 129 | return self.frame.origin.y + self.frame.size.height; 130 | } 131 | 132 | - (void) setBottom: (CGFloat) newbottom 133 | { 134 | CGRect newframe = self.frame; 135 | newframe.origin.y = newbottom - self.frame.size.height; 136 | self.frame = newframe; 137 | } 138 | 139 | - (CGFloat) right 140 | { 141 | return self.frame.origin.x + self.frame.size.width; 142 | } 143 | 144 | - (void) setRight: (CGFloat) newright 145 | { 146 | CGFloat delta = newright - (self.frame.origin.x + self.frame.size.width); 147 | CGRect newframe = self.frame; 148 | newframe.origin.x += delta ; 149 | self.frame = newframe; 150 | } 151 | 152 | // Move via offset 153 | - (void) moveBy: (CGPoint) delta 154 | { 155 | CGPoint newcenter = self.center; 156 | newcenter.x += delta.x; 157 | newcenter.y += delta.y; 158 | self.center = newcenter; 159 | } 160 | 161 | // Scaling 162 | - (void) scaleBy: (CGFloat) scaleFactor 163 | { 164 | CGRect newframe = self.frame; 165 | newframe.size.width *= scaleFactor; 166 | newframe.size.height *= scaleFactor; 167 | self.frame = newframe; 168 | } 169 | 170 | // Ensure that both dimensions fit within the given size by scaling down 171 | - (void) fitInSize: (CGSize) aSize 172 | { 173 | CGFloat scale; 174 | CGRect newframe = self.frame; 175 | 176 | if (newframe.size.height && (newframe.size.height > aSize.height)) 177 | { 178 | scale = aSize.height / newframe.size.height; 179 | newframe.size.width *= scale; 180 | newframe.size.height *= scale; 181 | } 182 | 183 | if (newframe.size.width && (newframe.size.width >= aSize.width)) 184 | { 185 | scale = aSize.width / newframe.size.width; 186 | newframe.size.width *= scale; 187 | newframe.size.height *= scale; 188 | } 189 | 190 | self.frame = newframe; 191 | } 192 | @end -------------------------------------------------------------------------------- /AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TPathIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | // Saves changes in the application's managed object context before the application terminates. 44 | [self saveContext]; 45 | } 46 | 47 | #pragma mark - Core Data stack 48 | 49 | @synthesize managedObjectContext = _managedObjectContext; 50 | @synthesize managedObjectModel = _managedObjectModel; 51 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 52 | 53 | - (NSURL *)applicationDocumentsDirectory { 54 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.vizz.TPathIconAnimation" in the application's documents directory. 55 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 56 | } 57 | 58 | - (NSManagedObjectModel *)managedObjectModel { 59 | // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 60 | if (_managedObjectModel != nil) { 61 | return _managedObjectModel; 62 | } 63 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TPathIconAnimation" withExtension:@"momd"]; 64 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 65 | return _managedObjectModel; 66 | } 67 | 68 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 69 | // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. 70 | if (_persistentStoreCoordinator != nil) { 71 | return _persistentStoreCoordinator; 72 | } 73 | 74 | // Create the coordinator and store 75 | 76 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 77 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TPathIconAnimation.sqlite"]; 78 | NSError *error = nil; 79 | NSString *failureReason = @"There was an error creating or loading the application's saved data."; 80 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 81 | // Report any error we got. 82 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 83 | dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 84 | dict[NSLocalizedFailureReasonErrorKey] = failureReason; 85 | dict[NSUnderlyingErrorKey] = error; 86 | error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 87 | // Replace this with code to handle the error appropriately. 88 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 89 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 90 | abort(); 91 | } 92 | 93 | return _persistentStoreCoordinator; 94 | } 95 | 96 | 97 | - (NSManagedObjectContext *)managedObjectContext { 98 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 99 | if (_managedObjectContext != nil) { 100 | return _managedObjectContext; 101 | } 102 | 103 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 104 | if (!coordinator) { 105 | return nil; 106 | } 107 | _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 108 | [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 109 | return _managedObjectContext; 110 | } 111 | 112 | #pragma mark - Core Data Saving support 113 | 114 | - (void)saveContext { 115 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 116 | if (managedObjectContext != nil) { 117 | NSError *error = nil; 118 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 119 | // Replace this implementation with code to handle the error appropriately. 120 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 121 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 122 | abort(); 123 | } 124 | } 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TPathIconAnimation 4 | // 5 | // Created by tikeyc on 16/1/12. 6 | // Copyright © 2016年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "ESPathIconAnimationView.h" 12 | #import "ESPathIcon.h" 13 | 14 | @interface ViewController () 15 | 16 | { 17 | ESPathIconAnimationView *_pathIconBusicessView; 18 | ESPathIconAnimationView *_pathIconShopView; 19 | ESPathIconAnimationView *_pathIconBuildView; 20 | ESPathIconAnimationView *_pathIconWorkShopView; 21 | 22 | UIView *_bgView; 23 | UITapGestureRecognizer *_tap; 24 | 25 | ShopType _shopType; 26 | } 27 | 28 | @end 29 | 30 | #define XGap 5 31 | 32 | @implementation ViewController 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | // Do any additional setup after loading the view, typically from a nib. 37 | self.edgesForExtendedLayout = UIRectEdgeNone; 38 | 39 | } 40 | 41 | - (void)didReceiveMemoryWarning { 42 | [super didReceiveMemoryWarning]; 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | 47 | #pragma mark - Actions Method 48 | 49 | - (IBAction)typeButtonActions:(UIButton *)sender { 50 | 51 | if (_bgView != nil) { 52 | return; 53 | } 54 | if (_bgView == nil) { 55 | // 56 | _bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height)]; 57 | _bgView.backgroundColor = RGBColorA(0, 0, 0, 0.7); 58 | [self.view addSubview:_bgView]; 59 | // 60 | _tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hiddenBgView:)]; 61 | _tap.enabled = NO;//先禁用掉,防止多次点击,特别是动画还没结束 62 | [_bgView addGestureRecognizer:_tap]; 63 | [self performSelector:@selector(setTapEnabled:) withObject:_tap afterDelay:animation_Time + animation_Time_Gap*3]; 64 | } 65 | _bgView.hidden = NO; 66 | 67 | if (sender.tag == 0) { 68 | _shopType = BUSINESS; 69 | if (_pathIconBusicessView == nil) { 70 | _pathIconBusicessView = [[ESPathIconAnimationView alloc] initWithFrame:CGRectMake(0, 0, _bgView.width, _bgView.height) withShowType:_shopType]; 71 | 72 | _pathIconBusicessView.delegate = self; 73 | [_bgView addSubview:_pathIconBusicessView]; 74 | }else{ 75 | _pathIconBusicessView.hidden = NO; 76 | _pathIconShopView.hidden = YES; 77 | _pathIconBuildView.hidden = YES; 78 | _pathIconWorkShopView.hidden = YES; 79 | [_pathIconShopView addAnimationToIcon]; 80 | } 81 | 82 | }else { 83 | 84 | if (sender.tag == 1) { 85 | _shopType = SHOP; 86 | if (_pathIconShopView == nil) { 87 | _pathIconShopView = [[ESPathIconAnimationView alloc] initWithFrame:CGRectMake(0, 0, _bgView.width, _bgView.height) withShowType:_shopType]; 88 | 89 | _pathIconShopView.delegate = self; 90 | [_bgView addSubview:_pathIconShopView]; 91 | }else{ 92 | _pathIconBusicessView.hidden = YES; 93 | _pathIconShopView.hidden = NO; 94 | _pathIconBuildView.hidden = YES; 95 | _pathIconWorkShopView.hidden = YES; 96 | [_pathIconShopView addAnimationToIcon]; 97 | } 98 | } 99 | if (sender.tag == 2) { 100 | _shopType = BUILDING; 101 | if (_pathIconBuildView == nil) { 102 | _pathIconBuildView = [[ESPathIconAnimationView alloc] initWithFrame:_bgView.bounds withShowType:_shopType]; 103 | _pathIconBuildView.delegate = self; 104 | [_bgView addSubview:_pathIconBuildView]; 105 | }else{ 106 | _pathIconBusicessView.hidden = YES; 107 | _pathIconShopView.hidden = YES; 108 | _pathIconBuildView.hidden = NO; 109 | _pathIconWorkShopView.hidden = YES; 110 | [_pathIconBuildView addAnimationToIcon]; 111 | } 112 | 113 | } 114 | if (sender.tag == 3) { 115 | _shopType = WORKSHOP; 116 | if (_pathIconWorkShopView == nil) { 117 | _pathIconWorkShopView = [[ESPathIconAnimationView alloc] initWithFrame:_bgView.bounds withShowType:_shopType]; 118 | _pathIconWorkShopView.delegate = self; 119 | [_bgView addSubview:_pathIconWorkShopView]; 120 | }else{ 121 | _pathIconBusicessView.hidden = YES; 122 | _pathIconShopView.hidden = YES; 123 | _pathIconBuildView.hidden = YES; 124 | _pathIconWorkShopView.hidden = NO; 125 | [_pathIconWorkShopView addAnimationToIcon]; 126 | } 127 | } 128 | } 129 | 130 | } 131 | /** 132 | * Description 先禁用掉,防止多次点击,特别是动画还没结束 133 | * 134 | * @param tap 135 | */ 136 | - (void)setTapEnabled:(UITapGestureRecognizer *)tap{ 137 | tap.enabled = YES; 138 | } 139 | 140 | - (void)hiddenBgView:(UITapGestureRecognizer *)tap{ 141 | tap.enabled = NO;//先禁用掉,防止多次点击,特别是动画还没结束 142 | float delayTime = animation_Time+animation_Time_Gap*3; 143 | if (_shopType == SHOP) { 144 | [_pathIconShopView addAnimationToIcon]; 145 | // _pathIconShopView.hidden = !_pathIconShopView.hidden; 146 | }else if (_shopType == BUILDING){ 147 | [_pathIconBuildView addAnimationToIcon]; 148 | // _pathIconBuildView.hidden = !_pathIconBuildView.hidden; 149 | }else if (_shopType == WORKSHOP){ 150 | [_pathIconWorkShopView addAnimationToIcon]; 151 | // _pathIconWorkShopView.hidden = !_pathIconWorkShopView.hidden; 152 | }else if (_shopType == BUSINESS){ 153 | [_pathIconBusicessView addAnimationToIcon]; 154 | delayTime = animation_Time+animation_Time_Gap; 155 | } 156 | [self performSelector:@selector(afterDelayHiddenBgView:) withObject:tap afterDelay:delayTime]; 157 | } 158 | /** 159 | * Description 延迟隐藏 动画介绍需要时间 160 | * 161 | * @param tap <#tap description#> 162 | */ 163 | - (void)afterDelayHiddenBgView:(UITapGestureRecognizer *)tap{ 164 | if (_shopType == SHOP) { 165 | for (int i = 0; i < _pathIconShopView.subviews.count; i++) { 166 | UIView *view = _pathIconShopView.subviews[i]; 167 | if (view.superview) { 168 | [view removeFromSuperview]; 169 | view = nil; 170 | } 171 | } 172 | _pathIconShopView.hidden = !_pathIconShopView.hidden; 173 | if (_pathIconShopView.superview) { 174 | [_pathIconShopView removeFromSuperview]; 175 | _pathIconShopView = nil; 176 | } 177 | }else if (_shopType == BUILDING){ 178 | for (int i = 0; i < _pathIconBuildView.subviews.count; i++) { 179 | UIView *view = _pathIconBuildView.subviews[i]; 180 | if (view.superview) { 181 | [view removeFromSuperview]; 182 | view = nil; 183 | } 184 | } 185 | _pathIconBuildView.hidden = !_pathIconBuildView.hidden; 186 | if (_pathIconBuildView.superview) { 187 | [_pathIconBuildView removeFromSuperview]; 188 | _pathIconBuildView = nil; 189 | } 190 | }else if (_shopType == WORKSHOP){ 191 | for (int i = 0; i < _pathIconWorkShopView.subviews.count; i++) { 192 | UIView *view = _pathIconWorkShopView.subviews[i]; 193 | if (view.superview) { 194 | [view removeFromSuperview]; 195 | view = nil; 196 | } 197 | } 198 | _pathIconWorkShopView.hidden = !_pathIconWorkShopView.hidden; 199 | if (_pathIconWorkShopView.superview) { 200 | [_pathIconWorkShopView removeFromSuperview]; 201 | _pathIconWorkShopView = nil; 202 | } 203 | }else if (_shopType == BUSINESS){ 204 | for (int i = 0; i < _pathIconBusicessView.subviews.count; i++) { 205 | UIView *view = _pathIconBusicessView.subviews[i]; 206 | if (view.superview) { 207 | [view removeFromSuperview]; 208 | view = nil; 209 | } 210 | } 211 | _pathIconBusicessView.hidden = !_pathIconBusicessView.hidden; 212 | if (_pathIconBusicessView.superview) { 213 | [_pathIconBusicessView removeFromSuperview]; 214 | _pathIconBusicessView = nil; 215 | } 216 | 217 | } 218 | _bgView.hidden = !_bgView.hidden; 219 | if (_bgView.superview) { 220 | [_bgView removeGestureRecognizer:_tap]; 221 | [_bgView removeFromSuperview]; 222 | _bgView = nil; 223 | } 224 | } 225 | 226 | 227 | 228 | #pragma mark - ESPathIconAnimationViewDelegate 229 | 230 | - (void)selectedIconIndex:(int)index withType:(ShopType)shopType{ 231 | [self hiddenBgView:_tap]; 232 | 233 | switch (shopType) { 234 | case BUSINESS: 235 | 236 | break; 237 | case SHOP: 238 | 239 | break; 240 | case BUILDING: 241 | 242 | break; 243 | case WORKSHOP: 244 | 245 | break; 246 | default: 247 | break; 248 | } 249 | } 250 | 251 | 252 | 253 | 254 | @end 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /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 | 31 | 41 | 51 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /ESPathIconView/ESPathIconAnimationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ESPathIconAnimationView.m 3 | // Estate 4 | // 5 | // Created by tikeyc on 14-5-23. 6 | // Copyright (c) 2014年 tikeyc. All rights reserved. 7 | // 8 | 9 | #import "ESPathIconAnimationView.h" 10 | #import "ESPathIcon.h" 11 | #import 12 | #define bigIcon_R 176 13 | #define nearbyIcon_R 40 14 | #define farIcon_R 20 15 | #define xGap 5 16 | 17 | @implementation ESPathIconAnimationView 18 | 19 | { 20 | SystemSoundID soundID; 21 | 22 | ShopType _shopType; 23 | 24 | UIButton *_bigIcon; 25 | ESPathIcon *_pathIcon1; 26 | ESPathIcon *_pathIcon2; 27 | ESPathIcon *_pathIcon3; 28 | ESPathIcon *_pathIcon4; 29 | 30 | BOOL _isDoubleClickIcon;//解决同时点击多个icon的BUG 31 | 32 | NSMutableArray *_pathIcons; 33 | BOOL _isOpenIcon; 34 | 35 | CAKeyframeAnimation *animationOpen; 36 | CAKeyframeAnimation *animationClose; 37 | } 38 | 39 | - (id)initWithFrame:(CGRect)frame withShowType:(ShopType)shopType 40 | { 41 | self = [super initWithFrame:frame]; 42 | if (self) { 43 | _shopType = shopType; 44 | _isOpenIcon = YES; 45 | //注册一个系统声音 46 | NSString *filePath = [[NSBundle mainBundle] pathForResource:@"get_notification" ofType:@"wav"]; 47 | NSURL *url = [NSURL fileURLWithPath:filePath]; 48 | AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &soundID); 49 | //播放系统声音提示用户 50 | AudioServicesPlaySystemSound(soundID); 51 | //震动 52 | // AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); 53 | [self initSubViews]; 54 | } 55 | return self; 56 | } 57 | 58 | - (void)initSubViews{ 59 | // 60 | _bigIcon = [UIButton buttonWithType:UIButtonTypeCustom]; 61 | UIImage *image = nil; 62 | if (_shopType == SHOP) { 63 | image = [UIImage imageNamed:@"main_path_shop.png"]; 64 | }else if (_shopType == BUILDING) { 65 | image = [UIImage imageNamed:@"main_path_building.png"]; 66 | }else if (_shopType == WORKSHOP) { 67 | image = [UIImage imageNamed:@"main_Path_workshop.png"]; 68 | }else if (_shopType == BUSINESS){ 69 | image = [UIImage imageNamed:@"main_path_business.png"]; 70 | } 71 | [_bigIcon setImage:image forState:UIControlStateNormal]; 72 | _bigIcon.userInteractionEnabled = NO; 73 | [_bigIcon addTarget:self action:@selector(bigIconClick:) forControlEvents:UIControlEventTouchUpInside]; 74 | _bigIcon.showsTouchWhenHighlighted = YES; 75 | if (_shopType == SHOP) { 76 | _bigIcon.frame = CGRectMake(self.width - 170/2 - xGap, xGap, 170/2, 170/2); 77 | }else if (_shopType == BUILDING){ 78 | _bigIcon.frame = CGRectMake(xGap, self.height - 170/2 - xGap, 170/2, 170/2); 79 | }else if (_shopType == WORKSHOP){ 80 | _bigIcon.frame = CGRectMake(self.width - 170/2 - xGap, self.height - 170/2 - xGap, 170/2, 170/2); 81 | }else if (_shopType == BUSINESS){ 82 | _bigIcon.frame = CGRectMake(xGap, xGap, 170/2, 170/2); 83 | } 84 | 85 | [self addSubview:_bigIcon]; 86 | 87 | // 88 | NSMutableArray *imgName,*titles; 89 | if (_shopType == BUSINESS) { 90 | imgName = [NSMutableArray arrayWithObjects:@"main_zhuan.png",@"main_overllsell.png",@"main_letOut.png",@"main_buy.png", nil]; 91 | titles = [NSMutableArray arrayWithObjects:@"转让",@"出售",@"求租",@"求购", nil]; 92 | }else{ 93 | imgName = [NSMutableArray arrayWithObjects:@"main_rent.png",@"main_overllsell.png",@"main_letOut.png",@"main_buy.png", nil]; 94 | titles = [NSMutableArray arrayWithObjects:@"出租",@"出售",@"求租",@"求购", nil]; 95 | } 96 | 97 | if (_shopType != SHOP && _shopType != BUSINESS) { 98 | imgName = [THelper exchangeArrayItem:imgName]; 99 | titles = [THelper exchangeArrayItem:titles]; 100 | } 101 | __weak ESPathIconAnimationView *this = self; 102 | long int count = imgName.count - 1; 103 | _pathIcons = [NSMutableArray array]; 104 | for (int i = 0; i < 4; i++) { 105 | __block ESPathIcon *pathIcon = [[ESPathIcon alloc] initWithImageName:imgName[i] withLabelTitle:titles[i]]; 106 | float offx = [THelper cos:(90/count)*i]; 107 | float offy = [THelper sin:(90/count)*i]; 108 | if (_shopType == SHOP) { 109 | pathIcon.endPoint = CGPointMake(_bigIcon.center.x - bigIcon_R*offx, _bigIcon.center.y + bigIcon_R*offy); 110 | //动画中间 较远点 111 | pathIcon.farPoint = CGPointMake(pathIcon.endPoint.x - farIcon_R*offx, pathIcon.endPoint.y + farIcon_R*offy); 112 | //动画中间较近点 113 | pathIcon.nearbyPoint = CGPointMake(pathIcon.endPoint.x + nearbyIcon_R*offx, pathIcon.endPoint.y - nearbyIcon_R*offy); 114 | }else if (_shopType == BUILDING){ 115 | pathIcon.endPoint = CGPointMake(_bigIcon.center.x + bigIcon_R*offx, _bigIcon.center.y - bigIcon_R*offy); 116 | //动画中间 较远点 117 | pathIcon.farPoint = CGPointMake(pathIcon.endPoint.x + farIcon_R*offx, pathIcon.endPoint.y - farIcon_R*offy); 118 | //动画中间较近点 119 | pathIcon.nearbyPoint = CGPointMake(pathIcon.endPoint.x - nearbyIcon_R*offx, pathIcon.endPoint.y + nearbyIcon_R*offy); 120 | }else if (_shopType == WORKSHOP){ 121 | pathIcon.endPoint = CGPointMake(_bigIcon.center.x - bigIcon_R*offx, _bigIcon.center.y - bigIcon_R*offy); 122 | //动画中间 较远点 123 | pathIcon.farPoint = CGPointMake(pathIcon.endPoint.x - farIcon_R*offx, pathIcon.endPoint.y - farIcon_R*offy); 124 | //动画中间较近点 125 | pathIcon.nearbyPoint = CGPointMake(pathIcon.endPoint.x + nearbyIcon_R*offx, pathIcon.endPoint.y + nearbyIcon_R*offy); 126 | }else if (_shopType == BUSINESS){ 127 | pathIcon.endPoint = CGPointMake(_bigIcon.center.x + bigIcon_R*offx, _bigIcon.center.y + bigIcon_R*offy); 128 | //动画中间 较远点 129 | pathIcon.farPoint = CGPointMake(pathIcon.endPoint.x + farIcon_R*offx, pathIcon.endPoint.y + farIcon_R*offy); 130 | //动画中间较近点 131 | pathIcon.nearbyPoint = CGPointMake(pathIcon.endPoint.x - nearbyIcon_R*offx, pathIcon.endPoint.y - nearbyIcon_R*offy); 132 | } 133 | pathIcon.center = _bigIcon.center; 134 | [_pathIcons addObject:pathIcon]; 135 | //动画起始点 136 | pathIcon.startPoint = _bigIcon.center; 137 | // 138 | if (_shopType == BUSINESS) { 139 | if (i == 1 || i == 3) { 140 | pathIcon.hidden = YES; 141 | [_pathIcons removeObject:pathIcon]; 142 | } 143 | } 144 | if (i == 0) { 145 | _pathIcon1 = pathIcon; 146 | }else if (i == 1){ 147 | _pathIcon2 = pathIcon; 148 | }else if (i == 2){ 149 | _pathIcon3 = pathIcon; 150 | }else if (i == 3){ 151 | _pathIcon4 = pathIcon; 152 | } 153 | 154 | pathIcon.block = ^(id result){ 155 | if (_isDoubleClickIcon) {//解决同时点击多个icon的BUG 156 | return; 157 | }//不重置_isDoubleClickIcon是因为动画完后,视图已近销毁 158 | _isDoubleClickIcon = YES; 159 | // 160 | [UIView animateWithDuration:0.2 animations:^{ 161 | _bigIcon.transform = CGAffineTransformMakeScale(0.2, 0.2); 162 | _bigIcon.alpha = 0.3; 163 | } completion:^(BOOL finished) { 164 | _bigIcon.hidden = YES; 165 | }]; 166 | // 167 | for (ESPathIcon *pathIcons in _pathIcons) { 168 | if (pathIcons == result) { 169 | [UIView animateWithDuration:0.2 animations:^{ 170 | pathIcons.transform = CGAffineTransformMakeScale(1.8, 1.8); 171 | pathIcons.alpha = 0.3; 172 | } completion:^(BOOL finished) { 173 | pathIcons.hidden = YES; 174 | }]; 175 | }else{ 176 | [UIView animateWithDuration:0.2 animations:^{ 177 | pathIcons.transform = CGAffineTransformMakeScale(0.2, 0.2); 178 | pathIcons.alpha = 0.3; 179 | } completion:^(BOOL finished) { 180 | pathIcons.hidden = YES; 181 | }]; 182 | } 183 | } 184 | NSString *indexString = [NSString stringWithFormat:@"%d",i+10]; 185 | if (_shopType != SHOP && _shopType != BUSINESS) { 186 | indexString = [NSString stringWithFormat:@"%lu",_pathIcons.count - 1 - i + 10]; 187 | } 188 | [this performSelector:@selector(afteDelayRespodsToSelectorDelegate:) withObject:indexString afterDelay:0.3]; 189 | }; 190 | [self insertSubview:pathIcon belowSubview:_bigIcon]; 191 | } 192 | [self addAnimationToIcon]; 193 | } 194 | //延迟 等动画结束后 在调用其它方法(如:push) 195 | - (void)afteDelayRespodsToSelectorDelegate:(NSString *)index{ 196 | if ([self.delegate respondsToSelector:@selector(selectedIconIndex:withType:)]) { 197 | [self.delegate selectedIconIndex:[index intValue] withType:_shopType]; 198 | } 199 | 200 | } 201 | 202 | - (void)bigIconClick:(UIButton *)button{ 203 | NSLog(@"bigIconClick"); 204 | if ([self.delegate respondsToSelector:@selector(selectedIconIndex:withType:)]) { 205 | [self.delegate selectedIconIndex:0 withType:0]; 206 | } 207 | } 208 | //运行动画 209 | - (void)addAnimationToIcon{ 210 | //_bigIcon animation 211 | _bigIcon.userInteractionEnabled = NO; 212 | /* 213 | float angle = 0.0; 214 | if (_shopType == SHOP) { 215 | if (_isOpenIcon) { 216 | angle = -(90+45); 217 | [UIView animateWithDuration:animation_Time animations:^{ 218 | _bigIcon.transform = CGAffineTransformMakeRotation(angle * (M_PI / 180.0f)); 219 | }]; 220 | }else{ 221 | [UIView animateWithDuration:animation_Time animations:^{ 222 | _bigIcon.transform = CGAffineTransformIdentity; 223 | }]; 224 | } 225 | 226 | }else if (_shopType == BUILDING){ 227 | if (_isOpenIcon) { 228 | angle = 45; 229 | [UIView animateWithDuration:animation_Time animations:^{ 230 | _bigIcon.transform = CGAffineTransformMakeRotation(angle * (M_PI / 180.0f)); 231 | }]; 232 | }else{ 233 | [UIView animateWithDuration:animation_Time animations:^{ 234 | _bigIcon.transform = CGAffineTransformIdentity; 235 | }]; 236 | } 237 | 238 | }else if (_shopType == WORKSHOP){ 239 | if (_isOpenIcon) { 240 | angle = -45; 241 | [UIView animateWithDuration:animation_Time animations:^{ 242 | _bigIcon.transform = CGAffineTransformMakeRotation(angle * (M_PI / 180.0f)); 243 | }]; 244 | }else{ 245 | [UIView animateWithDuration:animation_Time animations:^{ 246 | _bigIcon.transform = CGAffineTransformIdentity; 247 | }]; 248 | } 249 | 250 | } 251 | */ 252 | if (_isOpenIcon) { 253 | // [ESHelper exchangeArrayItem:_pathIcons]; 254 | }else{//交换icon,使的收起时按(后——>先)顺序收起 255 | [THelper exchangeArrayItem:_pathIcons]; 256 | } 257 | //_pathIcon animation 258 | for (int i = 0; i < _pathIcons.count; i++) { 259 | ESPathIcon *pathIcon = _pathIcons[i]; 260 | if (_isOpenIcon) { 261 | CGMutablePathRef path = CGPathCreateMutable(); 262 | CGPathMoveToPoint(path,NULL,pathIcon.startPoint.x,pathIcon.startPoint.y); 263 | CGPathAddLineToPoint(path, NULL, pathIcon.farPoint.x, pathIcon.farPoint.y); 264 | CGPathAddLineToPoint(path, NULL, pathIcon.nearbyPoint.x, pathIcon.nearbyPoint.y); 265 | CGPathAddLineToPoint(path, NULL, pathIcon.endPoint.x, pathIcon.endPoint.y); 266 | 267 | //创建 实例 268 | animationOpen = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 269 | animationOpen.delegate = self; 270 | //设置path属性 271 | animationOpen.path = path; 272 | CGPathRelease(path); 273 | [animationOpen setDuration:animation_Time]; 274 | animationOpen.fillMode = kCAFillModeForwards; 275 | animationOpen.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 276 | pathIcon.animation = animationOpen; 277 | [self performSelector:@selector(afterDelayAddAnimation:) withObject:pathIcon afterDelay:i*animation_Time_Gap]; 278 | }else{ 279 | CGMutablePathRef path = CGPathCreateMutable(); 280 | CGPathMoveToPoint(path, NULL, pathIcon.endPoint.x, pathIcon.endPoint.y); 281 | CGPathAddLineToPoint(path, NULL, pathIcon.nearbyPoint.x, pathIcon.nearbyPoint.y); 282 | CGPathAddLineToPoint(path, NULL, pathIcon.farPoint.x, pathIcon.farPoint.y); 283 | CGPathAddLineToPoint(path,NULL,pathIcon.startPoint.x,pathIcon.startPoint.y); 284 | 285 | //创建 实例 286 | animationClose = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 287 | animationClose.delegate = self; 288 | //设置path属性 289 | animationClose.path = path; 290 | CGPathRelease(path); 291 | [animationClose setDuration:animation_Time]; 292 | animationClose.fillMode = kCAFillModeForwards; 293 | animationClose.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 294 | pathIcon.animation = animationClose; 295 | [self performSelector:@selector(afterDelayAddAnimation:) withObject:pathIcon afterDelay:i*animation_Time_Gap]; 296 | 297 | } 298 | } 299 | //延迟 等动画结束后在设置_isOpenIcon 300 | [self performSelector:@selector(setIsOpen) withObject:nil afterDelay:animation_Time + animation_Time_Gap*(_pathIcons.count - 1)]; 301 | } 302 | 303 | - (void)setIsOpen{ 304 | _isOpenIcon = !_isOpenIcon; 305 | _bigIcon.userInteractionEnabled = YES; 306 | } 307 | //一次先——>后顺序展开icon 308 | - (void)afterDelayAddAnimation:(ESPathIcon *)pathIcon{ 309 | if (_isOpenIcon) { 310 | [pathIcon.layer addAnimation:pathIcon.animation forKey:NULL]; 311 | pathIcon.center = pathIcon.endPoint; 312 | }else{ 313 | [pathIcon.layer addAnimation:pathIcon.animation forKey:NULL]; 314 | pathIcon.center = pathIcon.startPoint; 315 | } 316 | 317 | } 318 | 319 | @end 320 | --------------------------------------------------------------------------------