├── iOS_movingAnnotation ├── en.lproj │ └── InfoPlist.strings ├── Resources │ ├── car1@2x.png │ ├── car2@2x.png │ ├── userPosition.png │ ├── userPosition@2x.png │ └── trackingPoints@2x.png ├── ViewController.h ├── AppDelegate.h ├── MovingAnnotationSource │ ├── PausableMovingAnnotation.h │ ├── PausableMovingAnnotation.m │ ├── CustomMovingAnnotation.m │ └── CustomMovingAnnotation.h ├── main.m ├── Prefix.pch ├── Info.plist ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── Main.storyboard ├── AppDelegate.m ├── LaunchScreen.storyboard └── ViewController.m ├── ios_movingAnnotation_demo.png ├── iOS_movingAnnotation.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── shaobin.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ ├── iOS_movingAnnotationUITests.xcscheme │ │ └── iOS_movingAnnotation.xcscheme └── project.pbxproj ├── iOS_movingAnnotation.xcworkspace └── contents.xcworkspacedata ├── Podfile ├── iOS_movingAnnotation_swift ├── Swift_Bridging_Header.h ├── CustomMovingAnnotation.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── AppDelegate.swift └── ViewController.swift ├── Podfile.lock ├── iOS_movingAnnotationUITests ├── Info.plist └── iOS_movingAnnotationUITests.m ├── .gitignore └── README.md /iOS_movingAnnotation/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ios_movingAnnotation_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/ios_movingAnnotation_demo.png -------------------------------------------------------------------------------- /iOS_movingAnnotation/Resources/car1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/iOS_movingAnnotation/Resources/car1@2x.png -------------------------------------------------------------------------------- /iOS_movingAnnotation/Resources/car2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/iOS_movingAnnotation/Resources/car2@2x.png -------------------------------------------------------------------------------- /iOS_movingAnnotation/Resources/userPosition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/iOS_movingAnnotation/Resources/userPosition.png -------------------------------------------------------------------------------- /iOS_movingAnnotation/Resources/userPosition@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/iOS_movingAnnotation/Resources/userPosition@2x.png -------------------------------------------------------------------------------- /iOS_movingAnnotation/Resources/trackingPoints@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/iOS_movingAnnotation/Resources/trackingPoints@2x.png -------------------------------------------------------------------------------- /iOS_movingAnnotation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS_movingAnnotation.xcodeproj/project.xcworkspace/xcuserdata/shaobin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/HEAD/iOS_movingAnnotation.xcodeproj/project.xcworkspace/xcuserdata/shaobin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS_movingAnnotation/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // test 4 | // 5 | // Created by yi chen on 14-8-20. 6 | // Copyright (c) 2014年 yi chen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /iOS_movingAnnotation.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '8.0' 3 | 4 | target 'iOS_movingAnnotation' do 5 | 6 | pod 'AMap3DMap' 7 | pod 'AMapSearch' 8 | 9 | end 10 | 11 | target 'iOS_movingAnnotation_swift' do 12 | 13 | pod 'AMap3DMap' 14 | pod 'AMapSearch' 15 | 16 | end 17 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // test 4 | // 5 | // Created by yi chen on 14-8-20. 6 | // Copyright (c) 2014年 yi chen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/Swift_Bridging_Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Swift_Bridging_Header.h 3 | // iOS_movingAnnotation 4 | // 5 | // Created by shaobin on 17/1/16. 6 | // Copyright © 2017年 yours. All rights reserved. 7 | // 8 | 9 | #ifndef Swift_Bridging_Header_h 10 | #define Swift_Bridging_Header_h 11 | 12 | #import 13 | 14 | #endif /* Swift_Bridging_Header_h */ 15 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/MovingAnnotationSource/PausableMovingAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // PausableMovingAnnotation.h 3 | // iOS_movingAnnotation 4 | // 5 | // Created by shaobin on 2018/3/5. 6 | // Copyright © 2018年 yours. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PausableMovingAnnotation : MAAnimatedAnnotation 12 | 13 | @property (nonatomic, assign) BOOL isPaused; //默认NO 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // test 4 | // 5 | // Created by yi chen on 14-8-20. 6 | // Copyright (c) 2014年 yi chen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/MovingAnnotationSource/PausableMovingAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // PausableMovingAnnotation.m 3 | // iOS_movingAnnotation 4 | // 5 | // Created by shaobin on 2018/3/5. 6 | // Copyright © 2018年 yours. All rights reserved. 7 | // 8 | 9 | #import "PausableMovingAnnotation.h" 10 | 11 | @implementation PausableMovingAnnotation 12 | 13 | - (void)step:(CGFloat)timeDelta { 14 | if(self.isPaused) { 15 | return; 16 | } 17 | 18 | [super step:timeDelta]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/MovingAnnotationSource/CustomMovingAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomMovingAnnotation.m 3 | // iOS_movingAnnotation 4 | // 5 | // Created by shaobin on 17/1/4. 6 | // Copyright © 2017年 yours. All rights reserved. 7 | // 8 | 9 | #import "CustomMovingAnnotation.h" 10 | 11 | @implementation CustomMovingAnnotation 12 | 13 | - (void)step:(CGFloat)timeDelta { 14 | [super step:timeDelta]; 15 | 16 | if(self.stepCallback) { 17 | self.stepCallback(); 18 | } 19 | } 20 | 21 | - (CLLocationDirection)rotateDegree { 22 | return 0; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/MovingAnnotationSource/CustomMovingAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomMovingAnnotation.h 3 | // iOS_movingAnnotation 4 | // 5 | // Created by shaobin on 17/1/4. 6 | // Copyright © 2017年 yours. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PausableMovingAnnotation.h" 11 | 12 | typedef void (^CustomMovingAnnotationCallback)(); 13 | 14 | @interface CustomMovingAnnotation : PausableMovingAnnotation 15 | 16 | @property (nonatomic, copy) CustomMovingAnnotationCallback stepCallback; 17 | 18 | - (CLLocationDirection)rotateDegree; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AMap3DMap (6.8.1): 3 | - AMapFoundation (~> 1.5) 4 | - AMapFoundation (1.5.6) 5 | - AMapSearch (6.6.0): 6 | - AMapFoundation (~> 1.4) 7 | 8 | DEPENDENCIES: 9 | - AMap3DMap 10 | - AMapSearch 11 | 12 | SPEC REPOS: 13 | https://github.com/cocoapods/specs.git: 14 | - AMap3DMap 15 | - AMapFoundation 16 | - AMapSearch 17 | 18 | SPEC CHECKSUMS: 19 | AMap3DMap: 9fa4ec6ab230bfbd3f0c0834f757fbd7038efe53 20 | AMapFoundation: 20fce2a12cd152e1092afdd04379cdac21932185 21 | AMapSearch: def5983c8ca1a6d7430970046dc814f6e337621d 22 | 23 | PODFILE CHECKSUM: 34da5f061657c4314291d68e5835dfc37337f03d 24 | 25 | COCOAPODS: 1.6.1 26 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/CustomMovingAnnotation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomMovingAnnotation.swift 3 | // iOS_movingAnnotation 4 | // 5 | // Created by shaobin on 17/1/16. 6 | // Copyright © 2017年 yours. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias CustomMovingAnnotationCallback = () -> Void 12 | 13 | class CustomMovingAnnotation: MAAnimatedAnnotation { 14 | var stepCallback : CustomMovingAnnotationCallback = {} 15 | 16 | override func step(_ timeDelta: CGFloat) { 17 | super.step(timeDelta) 18 | self.stepCallback() 19 | } 20 | 21 | override func rotateDegree() -> CLLocationDirection { 22 | return 0 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /iOS_movingAnnotationUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /iOS_movingAnnotation/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | 32 | UILaunchStoryboardName 33 | Launch Screen 34 | UIMainStoryboardFile 35 | Main 36 | UIRequiredDeviceCapabilities 37 | 38 | armv7 39 | 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /.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 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | 62 | # 63 | .DS_Store 64 | Result/ 65 | output/ 66 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/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 | 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 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/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 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/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 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/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 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /iOS_movingAnnotation/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 | 32 | -------------------------------------------------------------------------------- /iOS_movingAnnotationUITests/iOS_movingAnnotationUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iOS_movingAnnotationUITests.m 3 | // iOS_movingAnnotationUITests 4 | // 5 | // Created by hanxiaoming on 17/1/5. 6 | // Copyright © 2017年 yours. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iOS_movingAnnotationUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation iOS_movingAnnotationUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | 39 | XCUIApplication *app = [[XCUIApplication alloc] init]; 40 | [app.buttons[@"move"] tap]; 41 | 42 | 43 | sleep(10); 44 | 45 | [app.images[@"car1"] tap]; 46 | // [app.images[@"car1"] tap]; 47 | 48 | sleep(15); 49 | 50 | [app.buttons[@"stop"] tap]; 51 | 52 | // wait 53 | XCTestExpectation *e = [self expectationWithDescription:@"empty wait"]; 54 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 55 | [e fulfill]; 56 | }); 57 | [self waitForExpectationsWithTimeout:5 handler:nil]; 58 | 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /iOS_movingAnnotation.xcodeproj/xcshareddata/xcschemes/iOS_movingAnnotationUITests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 39 | 40 | 41 | 42 | 48 | 49 | 51 | 52 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // iOS_movingAnnotation_swift 4 | // 5 | // Created by shaobin on 17/1/16. 6 | // Copyright © 2017年 yours. 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 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // test 4 | // 5 | // Created by yi chen on 14-8-20. 6 | // Copyright (c) 2014年 yi chen. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | #import 12 | 13 | @implementation AppDelegate 14 | 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | [[AMapServices sharedServices] setEnableHTTPS:YES]; 19 | // Override point for customization after application launch. 20 | self.window.rootViewController = [[ViewController alloc] init]; 21 | [self.window makeKeyAndVisible]; 22 | 23 | return YES; 24 | } 25 | 26 | - (void)applicationWillResignActive:(UIApplication *)application 27 | { 28 | // 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. 29 | // 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. 30 | } 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application 33 | { 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 | - (void)applicationWillEnterForeground:(UIApplication *)application 39 | { 40 | // 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. 41 | } 42 | 43 | - (void)applicationDidBecomeActive:(UIApplication *)application 44 | { 45 | // 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. 46 | } 47 | 48 | - (void)applicationWillTerminate:(UIApplication *)application 49 | { 50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /iOS_movingAnnotation.xcodeproj/xcshareddata/xcschemes/iOS_movingAnnotation.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS_smooth_move 2 | annotation移动及转向动画 3 | 4 | - [高德官网申请Key](http://lbs.amap.com/dev/#/). 5 | - 阅读[开发指南](http://lbs.amap.com/api/ios-sdk/summary/). 6 | - 请先执行pod install --repo-update 安装依赖库 7 | - 查看Demo请打开.xcworkspace文件 8 | 9 | ## 核心类/接口 ## 10 | | 类 | 接口 | 说明 | 版本 | 11 | | -----|:-----:|:-----:|:-----:| 12 | | MAAnimatedAnnotation | - (void)addMoveAnimationWithKeyCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count withDuration:(CGFloat)duration withName:(NSString *)name completeCallback:(void(^)(BOOL isFinished))completeCallback; | 添加移动动画, 第一个添加的动画以当前coordinate为起始点,沿传入的coordinates点移动,否则以上一个动画终点为起始点 | 4.6.0 | 13 | 14 | 15 | ## 核心难点 ## 16 | ### objective-c 17 | - 添加MAAnimatedAnnotation 18 | ``` 19 | - (void)initRoute { 20 | int count = sizeof(s_coords) / sizeof(s_coords[0]); 21 | 22 | self.fullTraceLine = [MAPolyline polylineWithCoordinates:s_coords count:count]; 23 | [self.mapView addOverlay:self.fullTraceLine]; 24 | 25 | NSMutableArray * routeAnno = [NSMutableArray array]; 26 | for (int i = 0 ; i < count; i++) { 27 | MAPointAnnotation * a = [[MAPointAnnotation alloc] init]; 28 | a.coordinate = s_coords[i]; 29 | a.title = @"route"; 30 | [routeAnno addObject:a]; 31 | } 32 | [self.mapView addAnnotations:routeAnno]; 33 | [self.mapView showAnnotations:routeAnno animated:NO]; 34 | 35 | self.car1 = [[MAAnimatedAnnotation alloc] init]; 36 | self.car1.title = @"Car1"; 37 | [self.mapView addAnnotation:self.car1]; 38 | 39 | __weak typeof(self) weakSelf = self; 40 | self.car2 = [[CustomMovingAnnotation alloc] init]; 41 | self.car2.stepCallback = ^() { 42 | [weakSelf updatePassedTrace]; 43 | }; 44 | self.car2.title = @"Car2"; 45 | [self.mapView addAnnotation:self.car2]; 46 | 47 | [self.car1 setCoordinate:s_coords[0]]; 48 | [self.car2 setCoordinate:s_coords[0]]; 49 | } 50 | 51 | ``` 52 | - 开启动画 53 | ``` 54 | - (void)mov { 55 | double speed_car1 = 80.0 / 3.6; //80 km/h 56 | int count = sizeof(s_coords) / sizeof(s_coords[0]); 57 | [self.car1 setCoordinate:s_coords[0]]; 58 | [self.car1 addMoveAnimationWithKeyCoordinates:s_coords count:count withDuration:self.sumDistance / speed_car1 withName:nil completeCallback:^(BOOL isFinished) { 59 | ; 60 | }]; 61 | 62 | 63 | //小车2走过的轨迹置灰色, 采用添加多个动画方法 64 | double speed_car2 = 60.0 / 3.6; //60 km/h 65 | __weak typeof(self) weakSelf = self; 66 | [self.car2 setCoordinate:s_coords[0]]; 67 | self.passedTraceCoordIndex = 0; 68 | for(int i = 1; i < count; ++i) { 69 | NSNumber *num = [self.distanceArray objectAtIndex:i - 1]; 70 | [self.car2 addMoveAnimationWithKeyCoordinates:&(s_coords[i]) count:1 withDuration:num.doubleValue / speed_car2 withName:nil completeCallback:^(BOOL isFinished) { 71 | weakSelf.passedTraceCoordIndex = i; 72 | }]; 73 | } 74 | } 75 | ``` 76 | 77 | ### swift 78 | - 添加MAAnimatedAnnotation 79 | ``` 80 | func initRoute() { 81 | let count: Int = s_coords.count 82 | self.fullTraceLine = MAPolyline(coordinates: &s_coords, count: UInt(count)) 83 | self.mapView.add(self.fullTraceLine) 84 | var routeAnno = [Any]() 85 | for i in 0.. Void in 100 | weakSelf?.updatePassedTrace() 101 | } 102 | self.car2.title = "Car2" 103 | self.mapView.addAnnotation(self.car2) 104 | self.car1.coordinate = s_coords[0] 105 | self.car2.coordinate = s_coords[0] 106 | } 107 | ``` 108 | - 开启动画 109 | ``` 110 | func mov() { 111 | let speed_car1: Double = 120.0 / 3.6 112 | //80 km/h 113 | let count: Int = s_coords.count 114 | self.car1.coordinate = s_coords[0] 115 | let duration = self.sumDistance / speed_car1; 116 | self.car1.addMoveAnimation(withKeyCoordinates: &s_coords, count: UInt(count), withDuration: CGFloat(duration), withName: nil, completeCallback: {(_ isFinished: Bool) -> Void in 117 | }) 118 | 119 | //小车2走过的轨迹置灰色, 采用添加多个动画方法 120 | let speed_car2: Double = 100.0 / 3.6 121 | //60 km/h 122 | weak var weakSelf = self 123 | self.car2.coordinate = s_coords[0] 124 | self.passedTraceCoordIndex = 0 125 | for i in 1.. Void in 129 | weakSelf?.passedTraceCoordIndex = i 130 | }) 131 | } 132 | } 133 | 134 | ``` 135 | 136 | ### 截图效果 137 | 138 | ![result](https://raw.githubusercontent.com/amap-demo/iOS-smooth-move/master/ios_movingAnnotation_demo.png) 139 | -------------------------------------------------------------------------------- /iOS_movingAnnotation/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // test 4 | // 5 | // Created by yi chen on 14-8-20. 6 | // Copyright (c) 2014年 yi chen. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import "CustomMovingAnnotation.h" 12 | 13 | static CLLocationCoordinate2D s_coords[] = 14 | { 15 | {39.97617053371078, 116.3499049793749}, 16 | {39.97619854213431, 116.34978804908442}, 17 | {39.97623045687959, 116.349674596623}, 18 | {39.97626931100656, 116.34955525200917}, 19 | {39.976285626595036, 116.34943728748914}, 20 | {39.97628129172198, 116.34930864705592}, 21 | {39.976260803938594, 116.34918981582413}, 22 | {39.97623535890678, 116.34906721558868}, 23 | {39.976214717128855, 116.34895185151584}, 24 | {39.976280148755315, 116.34886935936889}, 25 | {39.97628182112874, 116.34873954611332}, 26 | {39.97626038855863, 116.34860763527448}, 27 | {39.976306080391836, 116.3484658907622}, 28 | {39.976358252119745, 116.34834585430347}, 29 | {39.97645709321835, 116.34831166130878}, 30 | {39.97655231226543, 116.34827643560175}, 31 | {39.976658372925556, 116.34824186261169}, 32 | {39.9767570732376, 116.34825080406188}, 33 | {39.976869087779995, 116.34825631960626}, 34 | {39.97698451764595, 116.34822111635201}, 35 | {39.977079745909876, 116.34822901510276}, 36 | {39.97718701787645, 116.34822234337618}, 37 | {39.97730766147824, 116.34821627457707}, 38 | {39.977417746816776, 116.34820593515043}, 39 | {39.97753930933358, 116.34821013897107}, 40 | {39.977652209132174, 116.34821304891533}, 41 | {39.977764016531076, 116.34820923399242}, 42 | {39.97786190186833, 116.3482045955917}, 43 | {39.977958856930286, 116.34822159449203}, 44 | {39.97807288885813, 116.3482256370537}, 45 | {39.978170063673524, 116.3482098441266}, 46 | {39.978266951404066, 116.34819564465377}, 47 | {39.978380693859116, 116.34820541974412}, 48 | {39.97848741209275, 116.34819672351216}, 49 | {39.978593409607825, 116.34816588867105}, 50 | {39.97870216883567, 116.34818489339459}, 51 | {39.978797222300166, 116.34818473446943}, 52 | {39.978893492422685, 116.34817728972234}, 53 | {39.978997133775266, 116.34816491505472}, 54 | {39.97911413849568, 116.34815408537773}, 55 | {39.97920553614499, 116.34812908154862}, 56 | {39.979308267469264, 116.34809495907906}, 57 | {39.97939658036473, 116.34805113358091}, 58 | {39.979491697188685, 116.3480310509613}, 59 | {39.979588529006875, 116.3480082124968}, 60 | {39.979685789111635, 116.34799530586834}, 61 | {39.979801430587926, 116.34798818413954}, 62 | {39.97990758587515, 116.3479996420353}, 63 | {39.980000796262615, 116.34798697544538}, 64 | {39.980116318796085, 116.3479912988137}, 65 | {39.98021407403913, 116.34799204219203}, 66 | {39.980325006125696, 116.34798535084123}, 67 | {39.98042511477518, 116.34797702460183}, 68 | {39.98054129336908, 116.34796288754136}, 69 | {39.980656820423505, 116.34797509821901}, 70 | {39.98074576792626, 116.34793922017285}, 71 | {39.98085620772756, 116.34792586413015}, 72 | {39.98098214824056, 116.3478962642899}, 73 | {39.98108306010269, 116.34782449883967}, 74 | {39.98115277119176, 116.34774758827285}, 75 | {39.98115430642997, 116.34761476652932}, 76 | {39.98114590845294, 116.34749135408349}, 77 | {39.98114337322547, 116.34734772765582}, 78 | {39.98115066909245, 116.34722082902628}, 79 | {39.98114532232906, 116.34708205250223}, 80 | {39.98112245161927, 116.346963237696}, 81 | {39.981136637759604, 116.34681500222743}, 82 | {39.981146248090866, 116.34669622104072}, 83 | {39.98112495260716, 116.34658043260109}, 84 | {39.9811107163792, 116.34643721418927}, 85 | {39.981085081075676, 116.34631638374302}, 86 | {39.98108046779486, 116.34614782996252}, 87 | {39.981049089345206, 116.3460256053666}, 88 | {39.98104839362087, 116.34588814050122}, 89 | {39.9810544889668, 116.34575119741586}, 90 | {39.981040940565734, 116.34562885420186}, 91 | {39.98105271658809, 116.34549232235582}, 92 | {39.981052294975264, 116.34537348820508}, 93 | {39.980956549928244, 116.3453513775533} 94 | }; 95 | 96 | @interface ViewController () 97 | 98 | @property (nonatomic, strong) MAMapView *mapView; 99 | 100 | ///车头方向跟随转动 101 | @property (nonatomic, strong) PausableMovingAnnotation *car1; 102 | ///车头方向不跟随转动 103 | @property (nonatomic, strong) CustomMovingAnnotation *car2; 104 | 105 | ///全轨迹overlay 106 | @property (nonatomic, strong) MAPolyline *fullTraceLine; 107 | ///走过轨迹的overlay 108 | @property (nonatomic, strong) MAPolyline *passedTraceLine; 109 | @property (nonatomic, assign) int passedTraceCoordIndex; 110 | 111 | @property (nonatomic, strong) NSArray *distanceArray; 112 | @property (nonatomic, assign) double sumDistance; 113 | 114 | @property (nonatomic, weak) MAAnnotationView *car1View; 115 | @property (nonatomic, weak) MAAnnotationView *car2View; 116 | 117 | @property (nonatomic, strong) NSMutableArray *carsArray; 118 | 119 | @property (nonatomic, strong) UIButton *pauseBtn; 120 | 121 | @end 122 | 123 | @implementation ViewController 124 | 125 | #pragma mark - Map Delegate 126 | - (void)mapInitComplete:(MAMapView *)mapView { 127 | [self initRoute]; 128 | } 129 | 130 | - (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)annotation 131 | { 132 | if (annotation == self.car1 || [self.carsArray containsObject:annotation]) { 133 | NSString *pointReuseIndetifier = @"pointReuseIndetifier1"; 134 | 135 | MAAnnotationView *annotationView = (MAAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier]; 136 | if(!annotationView) { 137 | annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier]; 138 | 139 | annotationView.canShowCallout = YES; 140 | 141 | UIImage *imge = [UIImage imageNamed:@"car1"]; 142 | annotationView.image = imge; 143 | 144 | if(annotation == self.car1) { 145 | self.car1View = annotationView; 146 | } 147 | } 148 | 149 | return annotationView; 150 | } else if(annotation == self.car2) { 151 | NSString *pointReuseIndetifier = @"pointReuseIndetifier2"; 152 | 153 | MAAnnotationView *annotationView = (MAAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier]; 154 | if(!annotationView) { 155 | annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier]; 156 | 157 | annotationView.canShowCallout = YES; 158 | 159 | UIImage *imge = [UIImage imageNamed:@"car2"]; 160 | annotationView.image = imge; 161 | 162 | self.car2View = annotationView; 163 | } 164 | 165 | return annotationView; 166 | } else if([annotation isKindOfClass:[MAPointAnnotation class]]) { 167 | NSString *pointReuseIndetifier = @"pointReuseIndetifier3"; 168 | MAAnnotationView *annotationView = (MAAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier]; 169 | if (annotationView == nil) { 170 | annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier]; 171 | annotationView.canShowCallout = YES; 172 | } 173 | 174 | if ([annotation.title isEqualToString:@"route"]) { 175 | annotationView.enabled = NO; 176 | annotationView.image = [UIImage imageNamed:@"trackingPoints"]; 177 | } 178 | 179 | [self.car1View.superview bringSubviewToFront:self.car1View]; 180 | [self.car2View.superview bringSubviewToFront:self.car2View]; 181 | 182 | return annotationView; 183 | } 184 | 185 | return nil; 186 | } 187 | 188 | - (MAPolylineRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id)overlay { 189 | if(overlay == self.fullTraceLine) { 190 | MAPolylineRenderer *polylineView = [[MAPolylineRenderer alloc] initWithPolyline:overlay]; 191 | 192 | polylineView.lineWidth = 6.f; 193 | polylineView.strokeColor = [UIColor colorWithRed:0 green:0.47 blue:1.0 alpha:0.9]; 194 | 195 | return polylineView; 196 | } else if(overlay == self.passedTraceLine) { 197 | MAPolylineRenderer *polylineView = [[MAPolylineRenderer alloc] initWithPolyline:overlay]; 198 | 199 | polylineView.lineWidth = 6.f; 200 | polylineView.strokeColor = [UIColor grayColor]; 201 | 202 | return polylineView; 203 | } 204 | 205 | return nil; 206 | } 207 | 208 | - (void)mapView:(MAMapView *)mapView didSelectAnnotationView:(MAAnnotationView *)view { 209 | NSLog(@"cooridnate :%f, %f", view.annotation.coordinate.latitude, view.annotation.coordinate.longitude); 210 | } 211 | 212 | #pragma mark life cycle 213 | 214 | - (void)viewDidLoad { 215 | [super viewDidLoad]; 216 | // Do any additional setup after loading the view, typically from a nib. 217 | 218 | self.mapView = [[MAMapView alloc] initWithFrame:self.view.bounds]; 219 | self.mapView.delegate = self; 220 | 221 | [self.view addSubview:self.mapView]; 222 | 223 | [self initBtn]; 224 | 225 | 226 | int count = sizeof(s_coords) / sizeof(s_coords[0]); 227 | double sum = 0; 228 | NSMutableArray *arr = [NSMutableArray arrayWithCapacity:count]; 229 | for(int i = 0; i < count - 1; ++i) { 230 | CLLocation *begin = [[CLLocation alloc] initWithLatitude:s_coords[i].latitude longitude:s_coords[i].longitude]; 231 | CLLocation *end = [[CLLocation alloc] initWithLatitude:s_coords[i+1].latitude longitude:s_coords[i+1].longitude]; 232 | CLLocationDistance distance = [end distanceFromLocation:begin]; 233 | [arr addObject:[NSNumber numberWithDouble:distance]]; 234 | sum += distance; 235 | } 236 | 237 | self.distanceArray = arr; 238 | self.sumDistance = sum; 239 | } 240 | 241 | - (void)viewDidAppear:(BOOL)animated { 242 | [super viewDidAppear:animated]; 243 | } 244 | 245 | - (void)initRoute { 246 | int count = sizeof(s_coords) / sizeof(s_coords[0]); 247 | 248 | self.fullTraceLine = [MAPolyline polylineWithCoordinates:s_coords count:count]; 249 | [self.mapView addOverlay:self.fullTraceLine]; 250 | 251 | NSMutableArray * routeAnno = [NSMutableArray array]; 252 | for (int i = 0 ; i < count; i++) { 253 | MAPointAnnotation * a = [[MAPointAnnotation alloc] init]; 254 | a.coordinate = s_coords[i]; 255 | a.title = @"route"; 256 | [routeAnno addObject:a]; 257 | } 258 | [self.mapView addAnnotations:routeAnno]; 259 | [self.mapView showAnnotations:routeAnno animated:NO]; 260 | 261 | self.car1 = [[PausableMovingAnnotation alloc] init]; 262 | self.car1.title = @"Car1"; 263 | [self.mapView addAnnotation:self.car1]; 264 | 265 | __weak typeof(self) weakSelf = self; 266 | self.car2 = [[CustomMovingAnnotation alloc] init]; 267 | self.car2.stepCallback = ^() { 268 | [weakSelf updatePassedTrace]; 269 | }; 270 | self.car2.title = @"Car2"; 271 | [self.mapView addAnnotation:self.car2]; 272 | 273 | [self.car1 setCoordinate:s_coords[0]]; 274 | [self.car2 setCoordinate:s_coords[0]]; 275 | 276 | 277 | #if 0 278 | const int carCount = 100; 279 | self.carsArray = [NSMutableArray arrayWithCapacity:carCount]; 280 | for(int i = 0; i < carCount; ++i) { 281 | MAAnimatedAnnotation *car = [[MAAnimatedAnnotation alloc] init]; 282 | car.title = [NSString stringWithFormat:@"car_%d", i]; 283 | float deltaX = ((float)(rand() % 100)) / 1000.0; 284 | float deltaY = ((float)(rand() % 100)) / 1000.0; 285 | car.coordinate = CLLocationCoordinate2DMake(39.97617053371078 + deltaX, 116.3499049793749 + deltaY); 286 | [self.carsArray addObject:car]; 287 | } 288 | [self.mapView addAnnotations:self.carsArray]; 289 | 290 | [NSTimer scheduledTimerWithTimeInterval:5 repeats:YES block:^(NSTimer * _Nonnull timer) { 291 | int temp = rand() % 10; 292 | for(int i = 0; i < carCount; ++i) { 293 | if(i % temp == 0) { 294 | MAAnimatedAnnotation *car = [self.carsArray objectAtIndex:i]; 295 | float deltaX = ((float)(rand() % 10)) / 1000.0; 296 | float deltaY = ((float)(rand() % 10)) / 1000.0; 297 | CLLocationCoordinate2D coord = car.coordinate; 298 | if(i % 2 == 0) { 299 | coord.latitude += deltaX; 300 | coord.longitude += deltaY; 301 | } else { 302 | coord.latitude -= deltaX; 303 | coord.longitude -= deltaY; 304 | } 305 | [car addMoveAnimationWithKeyCoordinates:&coord count:1 withDuration:1 withName:nil completeCallback:^(BOOL isFinished) { 306 | ; 307 | }]; 308 | } 309 | } 310 | }]; 311 | #endif 312 | } 313 | 314 | - (void)initBtn { 315 | UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 316 | btn.frame = CGRectMake(0, 100, 60, 40); 317 | btn.backgroundColor = [UIColor grayColor]; 318 | [btn setTitle:@"move" forState:UIControlStateNormal]; 319 | [btn addTarget:self action:@selector(mov) forControlEvents:UIControlEventTouchUpInside]; 320 | 321 | [self.view addSubview:btn]; 322 | 323 | UIButton * btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 324 | btn1.frame = CGRectMake(0, 200, 60, 40); 325 | btn1.backgroundColor = [UIColor grayColor]; 326 | [btn1 setTitle:@"stop" forState:UIControlStateNormal]; 327 | [btn1 addTarget:self action:@selector(stop) forControlEvents:UIControlEventTouchUpInside]; 328 | 329 | [self.view addSubview:btn1]; 330 | 331 | UIButton * btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 332 | btn2.frame = CGRectMake(0, 300, 60, 40); 333 | btn2.backgroundColor = [UIColor grayColor]; 334 | [btn2 setTitle:@"pause" forState:UIControlStateNormal]; 335 | [btn2 addTarget:self action:@selector(pause:) forControlEvents:UIControlEventTouchUpInside]; 336 | self.pauseBtn = btn2; 337 | [self.view addSubview:btn2]; 338 | } 339 | 340 | #pragma mark - Action 341 | 342 | - (void)mov { 343 | if(self.car1.isPaused) { 344 | [self pause:self.pauseBtn]; 345 | } 346 | 347 | double speed_car1 = 120.0 / 3.6; //80 km/h 348 | int count = sizeof(s_coords) / sizeof(s_coords[0]); 349 | [self.car1 setCoordinate:s_coords[0]]; 350 | [self.car1 addMoveAnimationWithKeyCoordinates:s_coords count:count withDuration:self.sumDistance / speed_car1 withName:nil completeCallback:^(BOOL isFinished) { 351 | ; 352 | }]; 353 | 354 | 355 | //小车2走过的轨迹置灰色, 采用添加多个动画方法 356 | double speed_car2 = 100.0 / 3.6; //60 km/h 357 | __weak typeof(self) weakSelf = self; 358 | [self.car2 setCoordinate:s_coords[0]]; 359 | self.passedTraceCoordIndex = 0; 360 | for(int i = 1; i < count; ++i) { 361 | NSNumber *num = [self.distanceArray objectAtIndex:i - 1]; 362 | [self.car2 addMoveAnimationWithKeyCoordinates:&(s_coords[i]) count:1 withDuration:num.doubleValue / speed_car2 withName:nil completeCallback:^(BOOL isFinished) { 363 | weakSelf.passedTraceCoordIndex = i; 364 | }]; 365 | } 366 | } 367 | 368 | - (void)stop { 369 | if(self.car1.isPaused) { 370 | [self pause:self.pauseBtn]; 371 | } 372 | for(MAAnnotationMoveAnimation *animation in [self.car1 allMoveAnimations]) { 373 | [animation cancel]; 374 | } 375 | self.car1.movingDirection = 0; 376 | [self.car1 setCoordinate:s_coords[0]]; 377 | 378 | for(MAAnnotationMoveAnimation *animation in [self.car2 allMoveAnimations]) { 379 | [animation cancel]; 380 | } 381 | self.car2.movingDirection = 0; 382 | [self.car2 setCoordinate:s_coords[0]]; 383 | 384 | if(self.passedTraceLine) { 385 | [self.mapView removeOverlay:self.passedTraceLine]; 386 | self.passedTraceLine = nil; 387 | } 388 | } 389 | 390 | - (void)pause:(UIButton*)btn { 391 | self.car2.isPaused = self.car1.isPaused = !self.car1.isPaused; 392 | 393 | if(self.car1.isPaused) { 394 | [btn setTitle:@"resume" forState:UIControlStateNormal]; 395 | } else { 396 | [btn setTitle:@"pause" forState:UIControlStateNormal]; 397 | } 398 | } 399 | 400 | //小车2走过的轨迹置灰色 401 | - (void)updatePassedTrace { 402 | if(self.car2.isAnimationFinished) { 403 | return; 404 | } 405 | 406 | if(self.passedTraceLine) { 407 | [self.mapView removeOverlay:self.passedTraceLine]; 408 | } 409 | 410 | int needCount = self.passedTraceCoordIndex + 2; 411 | CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * needCount); 412 | 413 | memcpy(coords, s_coords, sizeof(CLLocationCoordinate2D) * (self.passedTraceCoordIndex + 1)); 414 | coords[needCount - 1] = self.car2.coordinate; 415 | self.passedTraceLine = [MAPolyline polylineWithCoordinates:coords count:needCount]; 416 | [self.mapView addOverlay:self.passedTraceLine]; 417 | 418 | if(coords) { 419 | free(coords); 420 | } 421 | } 422 | 423 | @end 424 | -------------------------------------------------------------------------------- /iOS_movingAnnotation_swift/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // iOS_movingAnnotation_swift 4 | // 5 | // Created by shaobin on 17/1/16. 6 | // Copyright © 2017年 yours. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, MAMapViewDelegate { 12 | ///轨迹坐标点 13 | var s_coords : [CLLocationCoordinate2D] = [] 14 | 15 | var mapView: MAMapView! 16 | ///车头方向跟随转动 17 | var car1: MAAnimatedAnnotation! 18 | ///车头方向不跟随转动 19 | var car2: CustomMovingAnnotation! 20 | ///全轨迹overlay 21 | var fullTraceLine: MAPolyline! 22 | ///走过轨迹的overlay 23 | var passedTraceLine: MAPolyline! 24 | var passedTraceCoordIndex: Int = 0 25 | var distanceArray = [Double]() 26 | var sumDistance: Double = 0.0 27 | weak var car1View: MAAnnotationView? 28 | weak var car2View: MAAnnotationView? 29 | 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | // Do any additional setup after loading the view, typically from a nib. 34 | 35 | s_coords = [CLLocationCoordinate2D(latitude: 39.97617053371078, longitude: 116.3499049793749), 36 | CLLocationCoordinate2D(latitude: 39.97619854213431, longitude: 116.34978804908442), 37 | CLLocationCoordinate2D(latitude: 39.97623045687959, longitude: 116.349674596623), 38 | CLLocationCoordinate2D(latitude: 39.97626931100656, longitude: 116.34955525200917), 39 | CLLocationCoordinate2D(latitude: 39.976285626595036, longitude: 116.34943728748914), 40 | CLLocationCoordinate2D(latitude: 39.97628129172198, longitude: 116.34930864705592), 41 | 42 | CLLocationCoordinate2D(latitude: 39.976260803938594, longitude: 116.34918981582413), 43 | CLLocationCoordinate2D(latitude: 39.97623535890678, longitude: 116.34906721558868), 44 | CLLocationCoordinate2D(latitude: 39.976214717128855, longitude: 116.34895185151584), 45 | CLLocationCoordinate2D(latitude: 39.976280148755315, longitude: 116.34886935936889), 46 | CLLocationCoordinate2D(latitude: 39.97628182112874, longitude: 116.34873954611332), 47 | 48 | CLLocationCoordinate2D(latitude: 39.97626038855863, longitude: 116.34860763527448), 49 | CLLocationCoordinate2D(latitude: 39.976306080391836, longitude: 116.3484658907622), 50 | CLLocationCoordinate2D(latitude: 39.976358252119745, longitude: 116.34834585430347), 51 | CLLocationCoordinate2D(latitude: 39.97645709321835, longitude: 116.34831166130878), 52 | CLLocationCoordinate2D(latitude: 39.97655231226543, longitude: 116.34827643560175), 53 | 54 | CLLocationCoordinate2D(latitude: 39.976658372925556, longitude: 116.34824186261169), 55 | CLLocationCoordinate2D(latitude: 39.9767570732376, longitude: 116.34825080406188), 56 | CLLocationCoordinate2D(latitude: 39.976869087779995, longitude: 116.34825631960626), 57 | CLLocationCoordinate2D(latitude: 39.97698451764595, longitude: 116.34822111635201), 58 | CLLocationCoordinate2D(latitude: 39.977079745909876, longitude: 116.34822901510276), 59 | 60 | CLLocationCoordinate2D(latitude: 39.97718701787645, longitude: 116.34822234337618), 61 | CLLocationCoordinate2D(latitude: 39.97730766147824, longitude: 116.34821627457707), 62 | CLLocationCoordinate2D(latitude: 39.977417746816776, longitude: 116.34820593515043), 63 | CLLocationCoordinate2D(latitude: 39.97753930933358, longitude: 116.34821013897107), 64 | CLLocationCoordinate2D(latitude: 39.977652209132174, longitude: 116.34821304891533), 65 | 66 | CLLocationCoordinate2D(latitude: 39.977764016531076, longitude: 116.34820923399242), 67 | CLLocationCoordinate2D(latitude: 39.97786190186833, longitude: 116.3482045955917), 68 | CLLocationCoordinate2D(latitude: 39.977958856930286, longitude: 116.34822159449203), 69 | CLLocationCoordinate2D(latitude: 39.97807288885813, longitude: 116.3482256370537), 70 | CLLocationCoordinate2D(latitude: 39.978170063673524, longitude: 116.3482098441266), 71 | 72 | CLLocationCoordinate2D(latitude: 39.978266951404066, longitude: 116.34819564465377), 73 | CLLocationCoordinate2D(latitude: 39.978380693859116, longitude: 116.34820541974412), 74 | CLLocationCoordinate2D(latitude: 39.97848741209275, longitude: 116.34819672351216), 75 | CLLocationCoordinate2D(latitude: 39.978593409607825, longitude: 116.34816588867105), 76 | CLLocationCoordinate2D(latitude: 39.97870216883567, longitude: 116.34818489339459), 77 | 78 | CLLocationCoordinate2D(latitude: 39.978797222300166, longitude: 116.34818473446943), 79 | CLLocationCoordinate2D(latitude: 39.978893492422685, longitude: 116.34817728972234), 80 | CLLocationCoordinate2D(latitude: 39.978997133775266, longitude: 116.34816491505472), 81 | CLLocationCoordinate2D(latitude: 39.97911413849568, longitude: 116.34815408537773), 82 | CLLocationCoordinate2D(latitude: 39.97920553614499, longitude: 116.34812908154862), 83 | 84 | CLLocationCoordinate2D(latitude: 39.979308267469264, longitude: 116.34809495907906), 85 | CLLocationCoordinate2D(latitude: 39.97939658036473, longitude: 116.34805113358091), 86 | CLLocationCoordinate2D(latitude: 39.979491697188685, longitude: 116.3480310509613), 87 | CLLocationCoordinate2D(latitude: 39.979588529006875, longitude: 116.3480082124968), 88 | CLLocationCoordinate2D(latitude: 39.979685789111635, longitude: 116.34799530586834), 89 | 90 | CLLocationCoordinate2D(latitude: 39.979801430587926, longitude: 116.34798818413954), 91 | CLLocationCoordinate2D(latitude: 39.97990758587515, longitude: 116.3479996420353), 92 | CLLocationCoordinate2D(latitude: 39.980000796262615, longitude: 116.34798697544538), 93 | CLLocationCoordinate2D(latitude: 39.980116318796085, longitude: 116.3479912988137), 94 | CLLocationCoordinate2D(latitude: 39.98021407403913, longitude: 116.34799204219203), 95 | 96 | CLLocationCoordinate2D(latitude: 39.980325006125696, longitude: 116.34798535084123), 97 | CLLocationCoordinate2D(latitude: 39.98042511477518, longitude: 116.34797702460183), 98 | CLLocationCoordinate2D(latitude: 39.98054129336908, longitude: 116.34796288754136), 99 | CLLocationCoordinate2D(latitude: 39.980656820423505, longitude: 116.34797509821901), 100 | CLLocationCoordinate2D(latitude: 39.98074576792626, longitude: 116.34793922017285), 101 | 102 | CLLocationCoordinate2D(latitude: 39.98085620772756, longitude: 116.34792586413015), 103 | CLLocationCoordinate2D(latitude: 39.98098214824056, longitude: 116.3478962642899), 104 | CLLocationCoordinate2D(latitude: 39.98108306010269, longitude: 116.34782449883967), 105 | CLLocationCoordinate2D(latitude: 39.98115277119176, longitude: 116.34774758827285), 106 | CLLocationCoordinate2D(latitude: 39.98115430642997, longitude: 116.34761476652932), 107 | 108 | CLLocationCoordinate2D(latitude: 39.98114590845294, longitude: 116.34749135408349), 109 | CLLocationCoordinate2D(latitude: 39.98114337322547, longitude: 116.34734772765582), 110 | CLLocationCoordinate2D(latitude: 39.98115066909245, longitude: 116.34722082902628), 111 | CLLocationCoordinate2D(latitude: 39.98114532232906, longitude: 116.34708205250223), 112 | CLLocationCoordinate2D(latitude: 39.98112245161927, longitude: 116.346963237696), 113 | 114 | CLLocationCoordinate2D(latitude: 39.981136637759604, longitude: 116.34681500222743), 115 | CLLocationCoordinate2D(latitude: 39.981146248090866, longitude: 116.34669622104072), 116 | CLLocationCoordinate2D(latitude: 39.98112495260716, longitude: 116.34658043260109), 117 | CLLocationCoordinate2D(latitude: 39.9811107163792, longitude: 116.34643721418927), 118 | CLLocationCoordinate2D(latitude: 39.981085081075676, longitude: 116.34631638374302), 119 | 120 | CLLocationCoordinate2D(latitude: 39.98108046779486, longitude: 116.34614782996252), 121 | CLLocationCoordinate2D(latitude: 39.981049089345206, longitude: 116.3460256053666), 122 | CLLocationCoordinate2D(latitude: 39.98104839362087, longitude: 116.34588814050122), 123 | CLLocationCoordinate2D(latitude: 39.9810544889668, longitude: 116.34575119741586), 124 | CLLocationCoordinate2D(latitude: 39.981040940565734, longitude: 116.34562885420186), 125 | 126 | CLLocationCoordinate2D(latitude: 39.98105271658809, longitude: 116.34549232235582), 127 | CLLocationCoordinate2D(latitude: 39.981052294975264, longitude: 116.34537348820508), 128 | CLLocationCoordinate2D(latitude: 39.980956549928244, longitude: 116.3453513775533), 129 | 130 | ] 131 | 132 | self.initialize() 133 | } 134 | 135 | override func didReceiveMemoryWarning() { 136 | super.didReceiveMemoryWarning() 137 | // Dispose of any resources that can be recreated. 138 | } 139 | 140 | //MARK: - mapview Delegate 141 | func mapInitComplete(_ mapView: MAMapView) { 142 | self.initRoute() 143 | } 144 | 145 | func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! { 146 | if (annotation.isEqual(self.car1)) { 147 | let pointReuseIndetifier: String = "pointReuseIndetifier1" 148 | var annotationView: MAAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier) 149 | if annotationView == nil { 150 | annotationView = MAAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier) 151 | annotationView?.canShowCallout = true 152 | let imge = UIImage(named: "car1") 153 | annotationView?.image = imge 154 | self.car1View = annotationView 155 | } 156 | return annotationView! 157 | } else if (annotation.isEqual(self.car2)) { 158 | let pointReuseIndetifier: String = "pointReuseIndetifier2" 159 | var annotationView: MAAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier) 160 | if annotationView == nil { 161 | annotationView = MAAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier) 162 | annotationView?.canShowCallout = true 163 | let imge = UIImage(named: "car2") 164 | annotationView?.image = imge 165 | self.car2View = annotationView 166 | } 167 | return annotationView! 168 | } else if (annotation is MAPointAnnotation) { 169 | let pointReuseIndetifier: String = "pointReuseIndetifier3" 170 | var annotationView: MAAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier) 171 | if annotationView == nil { 172 | annotationView = MAAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier) 173 | annotationView?.canShowCallout = true 174 | } 175 | if (annotation.title == "route") { 176 | annotationView?.isEnabled = false 177 | annotationView?.image = UIImage(named: "trackingPoints") 178 | } 179 | 180 | self.car1View?.superview?.bringSubview(toFront: self.car1View!) 181 | self.car2View?.superview?.bringSubview(toFront: self.car2View!) 182 | return annotationView 183 | } 184 | return nil 185 | } 186 | 187 | func mapView(_ mapView: MAMapView!, rendererFor overlay: MAOverlay!) -> MAOverlayRenderer! { 188 | if (overlay as! MAPolyline == self.fullTraceLine) { 189 | let polylineView = MAPolylineRenderer(polyline: overlay as! MAPolyline!) 190 | polylineView?.lineWidth = 6.0 191 | polylineView?.strokeColor = UIColor(red: CGFloat(0), green: CGFloat(0.47), blue: CGFloat(1.0), alpha: CGFloat(0.9)) 192 | return polylineView 193 | } 194 | else if (overlay as! MAPolyline == self.passedTraceLine) { 195 | let polylineView = MAPolylineRenderer(polyline: overlay as! MAPolyline!) 196 | polylineView?.lineWidth = 6.0 197 | polylineView?.strokeColor = UIColor.gray 198 | return polylineView 199 | } 200 | 201 | return nil 202 | } 203 | 204 | func mapView(_ mapView: MAMapView, didSelect view: MAAnnotationView) { 205 | print("cooridnate :\(view.annotation.coordinate.latitude), \(view.annotation.coordinate.longitude)") 206 | } 207 | 208 | // MARK: life cycle 209 | 210 | func initialize() { 211 | // Do any additional setup after loading the view, typically from a nib. 212 | self.mapView = MAMapView(frame: self.view.frame) 213 | self.mapView.delegate = self 214 | self.view.addSubview(self.mapView) 215 | self.initBtn() 216 | let count: Int = s_coords.count 217 | var sum: Double = 0 218 | var arr = [Double]() /* capacity: count */ 219 | for i in 0.. Void in 251 | weakSelf?.updatePassedTrace() 252 | } 253 | self.car2.title = "Car2" 254 | self.mapView.addAnnotation(self.car2) 255 | self.car1.coordinate = s_coords[0] 256 | self.car2.coordinate = s_coords[0] 257 | } 258 | 259 | func initBtn() { 260 | let btn = UIButton(type: .roundedRect) 261 | btn.frame = CGRect(x: CGFloat(0), y: CGFloat(100), width: CGFloat(60), height: CGFloat(40)) 262 | btn.backgroundColor = UIColor.gray 263 | btn.setTitle("move", for: .normal) 264 | btn.addTarget(self, action: #selector(self.mov), for: .touchUpInside) 265 | self.view.addSubview(btn) 266 | let btn1 = UIButton(type: .roundedRect) 267 | btn1.frame = CGRect(x: CGFloat(0), y: CGFloat(200), width: CGFloat(60), height: CGFloat(40)) 268 | btn1.backgroundColor = UIColor.gray 269 | btn1.setTitle("stop", for: .normal) 270 | btn1.addTarget(self, action: #selector(self.stop), for: .touchUpInside) 271 | self.view.addSubview(btn1) 272 | } 273 | 274 | // MARK: - Action 275 | @objc func mov() { 276 | let speed_car1: Double = 120.0 / 3.6 277 | //80 km/h 278 | let count: Int = s_coords.count 279 | self.car1.coordinate = s_coords[0] 280 | let duration = self.sumDistance / speed_car1; 281 | self.car1.addMoveAnimation(withKeyCoordinates: &s_coords, count: UInt(count), withDuration: CGFloat(duration), withName: nil, completeCallback: {(_ isFinished: Bool) -> Void in 282 | }) 283 | 284 | //小车2走过的轨迹置灰色, 采用添加多个动画方法 285 | let speed_car2: Double = 100.0 / 3.6 286 | //60 km/h 287 | weak var weakSelf = self 288 | self.car2.coordinate = s_coords[0] 289 | self.passedTraceCoordIndex = 0 290 | for i in 1.. Void in 294 | weakSelf?.passedTraceCoordIndex = i 295 | }) 296 | } 297 | } 298 | 299 | @objc func stop() { 300 | for animation: MAAnnotationMoveAnimation in self.car1.allMoveAnimations() { 301 | animation.cancel() 302 | } 303 | self.car1.movingDirection = 0 304 | self.car1.coordinate = s_coords[0] 305 | for animation: MAAnnotationMoveAnimation in self.car2.allMoveAnimations() { 306 | animation.cancel() 307 | } 308 | self.car2.movingDirection = 0 309 | self.car2.coordinate = s_coords[0] 310 | if (self.passedTraceLine != nil) { 311 | self.mapView.remove(self.passedTraceLine) 312 | self.passedTraceLine = nil 313 | } 314 | } 315 | 316 | func updatePassedTrace() { 317 | if self.car2.isAnimationFinished() { 318 | return 319 | } 320 | if (self.passedTraceLine != nil) { 321 | self.mapView.remove(self.passedTraceLine) 322 | } 323 | let needCount: Int = self.passedTraceCoordIndex + 2 324 | 325 | let buffer = UnsafeMutablePointer.allocate(capacity: needCount) 326 | for i in 0.. /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 438 | showEnvVarsInLog = 0; 439 | }; 440 | AD55361329122779F61C1BB3 /* [CP] Copy Pods Resources */ = { 441 | isa = PBXShellScriptBuildPhase; 442 | buildActionMask = 2147483647; 443 | files = ( 444 | ); 445 | inputPaths = ( 446 | "${PODS_ROOT}/Target Support Files/Pods-iOS_movingAnnotation/Pods-iOS_movingAnnotation-resources.sh", 447 | "${PODS_ROOT}/AMap3DMap/MAMapKit.framework/AMap.bundle", 448 | ); 449 | name = "[CP] Copy Pods Resources"; 450 | outputPaths = ( 451 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AMap.bundle", 452 | ); 453 | runOnlyForDeploymentPostprocessing = 0; 454 | shellPath = /bin/sh; 455 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iOS_movingAnnotation/Pods-iOS_movingAnnotation-resources.sh\"\n"; 456 | showEnvVarsInLog = 0; 457 | }; 458 | DFC9EEC2D08A28C51B297629 /* [CP] Check Pods Manifest.lock */ = { 459 | isa = PBXShellScriptBuildPhase; 460 | buildActionMask = 2147483647; 461 | files = ( 462 | ); 463 | inputPaths = ( 464 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 465 | "${PODS_ROOT}/Manifest.lock", 466 | ); 467 | name = "[CP] Check Pods Manifest.lock"; 468 | outputPaths = ( 469 | "$(DERIVED_FILE_DIR)/Pods-iOS_movingAnnotation_swift-checkManifestLockResult.txt", 470 | ); 471 | runOnlyForDeploymentPostprocessing = 0; 472 | shellPath = /bin/sh; 473 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 474 | showEnvVarsInLog = 0; 475 | }; 476 | EC3E9B6690428F5C94A50605 /* [CP] Copy Pods Resources */ = { 477 | isa = PBXShellScriptBuildPhase; 478 | buildActionMask = 2147483647; 479 | files = ( 480 | ); 481 | inputPaths = ( 482 | "${PODS_ROOT}/Target Support Files/Pods-iOS_movingAnnotation_swift/Pods-iOS_movingAnnotation_swift-resources.sh", 483 | "${PODS_ROOT}/AMap3DMap/MAMapKit.framework/AMap.bundle", 484 | ); 485 | name = "[CP] Copy Pods Resources"; 486 | outputPaths = ( 487 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AMap.bundle", 488 | ); 489 | runOnlyForDeploymentPostprocessing = 0; 490 | shellPath = /bin/sh; 491 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iOS_movingAnnotation_swift/Pods-iOS_movingAnnotation_swift-resources.sh\"\n"; 492 | showEnvVarsInLog = 0; 493 | }; 494 | /* End PBXShellScriptBuildPhase section */ 495 | 496 | /* Begin PBXSourcesBuildPhase section */ 497 | 6A2D0F6B1E1E59220036ACED /* Sources */ = { 498 | isa = PBXSourcesBuildPhase; 499 | buildActionMask = 2147483647; 500 | files = ( 501 | 6A2D0F721E1E59220036ACED /* iOS_movingAnnotationUITests.m in Sources */, 502 | ); 503 | runOnlyForDeploymentPostprocessing = 0; 504 | }; 505 | B6152B8C1DBDDACB00254FC8 /* Sources */ = { 506 | isa = PBXSourcesBuildPhase; 507 | buildActionMask = 2147483647; 508 | files = ( 509 | B63E7088204D67FD00EA7ECE /* PausableMovingAnnotation.m in Sources */, 510 | B6152BD51DBDDC2500254FC8 /* ViewController.m in Sources */, 511 | B6F8F9F41E1CDA5A0036D1DC /* CustomMovingAnnotation.m in Sources */, 512 | B6152BCC1DBDDC2500254FC8 /* main.m in Sources */, 513 | B6152BC61DBDDC2500254FC8 /* AppDelegate.m in Sources */, 514 | ); 515 | runOnlyForDeploymentPostprocessing = 0; 516 | }; 517 | B6F63DF21E2C6AA400741516 /* Sources */ = { 518 | isa = PBXSourcesBuildPhase; 519 | buildActionMask = 2147483647; 520 | files = ( 521 | B6F63E091E2C6B0900741516 /* CustomMovingAnnotation.swift in Sources */, 522 | B6F63DFB1E2C6AA400741516 /* ViewController.swift in Sources */, 523 | B6F63DF91E2C6AA400741516 /* AppDelegate.swift in Sources */, 524 | ); 525 | runOnlyForDeploymentPostprocessing = 0; 526 | }; 527 | /* End PBXSourcesBuildPhase section */ 528 | 529 | /* Begin PBXTargetDependency section */ 530 | 6A2D0F751E1E59220036ACED /* PBXTargetDependency */ = { 531 | isa = PBXTargetDependency; 532 | target = B6152B8F1DBDDACB00254FC8 /* iOS_movingAnnotation */; 533 | targetProxy = 6A2D0F741E1E59220036ACED /* PBXContainerItemProxy */; 534 | }; 535 | /* End PBXTargetDependency section */ 536 | 537 | /* Begin PBXVariantGroup section */ 538 | B6152BAE1DBDDC2500254FC8 /* Main.storyboard */ = { 539 | isa = PBXVariantGroup; 540 | children = ( 541 | B6152BAF1DBDDC2500254FC8 /* Base */, 542 | ); 543 | name = Main.storyboard; 544 | sourceTree = ""; 545 | }; 546 | B6152BB01DBDDC2500254FC8 /* InfoPlist.strings */ = { 547 | isa = PBXVariantGroup; 548 | children = ( 549 | B6152BB11DBDDC2500254FC8 /* en */, 550 | ); 551 | name = InfoPlist.strings; 552 | sourceTree = ""; 553 | }; 554 | B6F63DFC1E2C6AA400741516 /* Main.storyboard */ = { 555 | isa = PBXVariantGroup; 556 | children = ( 557 | B6F63DFD1E2C6AA400741516 /* Base */, 558 | ); 559 | name = Main.storyboard; 560 | sourceTree = ""; 561 | }; 562 | B6F63E011E2C6AA400741516 /* LaunchScreen.storyboard */ = { 563 | isa = PBXVariantGroup; 564 | children = ( 565 | B6F63E021E2C6AA400741516 /* Base */, 566 | ); 567 | name = LaunchScreen.storyboard; 568 | sourceTree = ""; 569 | }; 570 | /* End PBXVariantGroup section */ 571 | 572 | /* Begin XCBuildConfiguration section */ 573 | 6A2D0F771E1E59220036ACED /* Debug */ = { 574 | isa = XCBuildConfiguration; 575 | buildSettings = { 576 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 577 | DEVELOPMENT_TEAM = YMJ372W38W; 578 | INFOPLIST_FILE = iOS_movingAnnotationUITests/Info.plist; 579 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 580 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 581 | PRODUCT_BUNDLE_IDENTIFIER = "com.autonavi.iOS-movingAnnotationUITests"; 582 | PRODUCT_NAME = "$(TARGET_NAME)"; 583 | PROVISIONING_PROFILE = "9b821a78-8ad6-4cf7-b6b0-31b43df04bbe"; 584 | PROVISIONING_PROFILE_SPECIFIER = openPlatform_development; 585 | TEST_TARGET_NAME = iOS_movingAnnotation; 586 | }; 587 | name = Debug; 588 | }; 589 | 6A2D0F781E1E59220036ACED /* Release */ = { 590 | isa = XCBuildConfiguration; 591 | buildSettings = { 592 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 593 | DEVELOPMENT_TEAM = YMJ372W38W; 594 | INFOPLIST_FILE = iOS_movingAnnotationUITests/Info.plist; 595 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 596 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 597 | PRODUCT_BUNDLE_IDENTIFIER = "com.autonavi.iOS-movingAnnotationUITests"; 598 | PRODUCT_NAME = "$(TARGET_NAME)"; 599 | PROVISIONING_PROFILE = "9b821a78-8ad6-4cf7-b6b0-31b43df04bbe"; 600 | PROVISIONING_PROFILE_SPECIFIER = openPlatform_development; 601 | TEST_TARGET_NAME = iOS_movingAnnotation; 602 | }; 603 | name = Release; 604 | }; 605 | B6152BA51DBDDACB00254FC8 /* Debug */ = { 606 | isa = XCBuildConfiguration; 607 | buildSettings = { 608 | ALWAYS_SEARCH_USER_PATHS = NO; 609 | CLANG_ANALYZER_NONNULL = YES; 610 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 611 | CLANG_CXX_LIBRARY = "libc++"; 612 | CLANG_ENABLE_MODULES = YES; 613 | CLANG_ENABLE_OBJC_ARC = YES; 614 | CLANG_WARN_BOOL_CONVERSION = YES; 615 | CLANG_WARN_CONSTANT_CONVERSION = YES; 616 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 617 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 618 | CLANG_WARN_EMPTY_BODY = YES; 619 | CLANG_WARN_ENUM_CONVERSION = YES; 620 | CLANG_WARN_INFINITE_RECURSION = YES; 621 | CLANG_WARN_INT_CONVERSION = YES; 622 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 623 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 624 | CLANG_WARN_UNREACHABLE_CODE = YES; 625 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 626 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 627 | COPY_PHASE_STRIP = NO; 628 | DEBUG_INFORMATION_FORMAT = dwarf; 629 | ENABLE_STRICT_OBJC_MSGSEND = YES; 630 | ENABLE_TESTABILITY = YES; 631 | GCC_C_LANGUAGE_STANDARD = gnu99; 632 | GCC_DYNAMIC_NO_PIC = NO; 633 | GCC_NO_COMMON_BLOCKS = YES; 634 | GCC_OPTIMIZATION_LEVEL = 0; 635 | GCC_PREPROCESSOR_DEFINITIONS = ( 636 | "DEBUG=1", 637 | "$(inherited)", 638 | ); 639 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 640 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 641 | GCC_WARN_UNDECLARED_SELECTOR = YES; 642 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 643 | GCC_WARN_UNUSED_FUNCTION = YES; 644 | GCC_WARN_UNUSED_VARIABLE = YES; 645 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 646 | MTL_ENABLE_DEBUG_INFO = YES; 647 | ONLY_ACTIVE_ARCH = YES; 648 | SDKROOT = iphoneos; 649 | TARGETED_DEVICE_FAMILY = "1,2"; 650 | }; 651 | name = Debug; 652 | }; 653 | B6152BA61DBDDACB00254FC8 /* Release */ = { 654 | isa = XCBuildConfiguration; 655 | buildSettings = { 656 | ALWAYS_SEARCH_USER_PATHS = NO; 657 | CLANG_ANALYZER_NONNULL = YES; 658 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 659 | CLANG_CXX_LIBRARY = "libc++"; 660 | CLANG_ENABLE_MODULES = YES; 661 | CLANG_ENABLE_OBJC_ARC = YES; 662 | CLANG_WARN_BOOL_CONVERSION = YES; 663 | CLANG_WARN_CONSTANT_CONVERSION = YES; 664 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 665 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 666 | CLANG_WARN_EMPTY_BODY = YES; 667 | CLANG_WARN_ENUM_CONVERSION = YES; 668 | CLANG_WARN_INFINITE_RECURSION = YES; 669 | CLANG_WARN_INT_CONVERSION = YES; 670 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 671 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 672 | CLANG_WARN_UNREACHABLE_CODE = YES; 673 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 674 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 675 | COPY_PHASE_STRIP = NO; 676 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 677 | ENABLE_NS_ASSERTIONS = NO; 678 | ENABLE_STRICT_OBJC_MSGSEND = YES; 679 | GCC_C_LANGUAGE_STANDARD = gnu99; 680 | GCC_NO_COMMON_BLOCKS = YES; 681 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 682 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 683 | GCC_WARN_UNDECLARED_SELECTOR = YES; 684 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 685 | GCC_WARN_UNUSED_FUNCTION = YES; 686 | GCC_WARN_UNUSED_VARIABLE = YES; 687 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 688 | MTL_ENABLE_DEBUG_INFO = NO; 689 | SDKROOT = iphoneos; 690 | TARGETED_DEVICE_FAMILY = "1,2"; 691 | VALIDATE_PRODUCT = YES; 692 | }; 693 | name = Release; 694 | }; 695 | B6152BA81DBDDACB00254FC8 /* Debug */ = { 696 | isa = XCBuildConfiguration; 697 | baseConfigurationReference = F7794DD1F93D43E5E79573BB /* Pods-iOS_movingAnnotation.debug.xcconfig */; 698 | buildSettings = { 699 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 700 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 701 | DEVELOPMENT_TEAM = YMJ372W38W; 702 | INFOPLIST_FILE = iOS_movingAnnotation/Info.plist; 703 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 704 | PRODUCT_BUNDLE_IDENTIFIER = com.autonavi.MovingAnnotation; 705 | PRODUCT_NAME = "$(TARGET_NAME)"; 706 | PROVISIONING_PROFILE = "48216a7c-4edd-4f5d-9389-95ffbd3ea775"; 707 | PROVISIONING_PROFILE_SPECIFIER = openPlatform_development; 708 | }; 709 | name = Debug; 710 | }; 711 | B6152BA91DBDDACB00254FC8 /* Release */ = { 712 | isa = XCBuildConfiguration; 713 | baseConfigurationReference = CA36FDE9A1B8AC22DE9733C7 /* Pods-iOS_movingAnnotation.release.xcconfig */; 714 | buildSettings = { 715 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 716 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 717 | DEVELOPMENT_TEAM = YMJ372W38W; 718 | INFOPLIST_FILE = iOS_movingAnnotation/Info.plist; 719 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 720 | PRODUCT_BUNDLE_IDENTIFIER = com.autonavi.MovingAnnotation; 721 | PRODUCT_NAME = "$(TARGET_NAME)"; 722 | PROVISIONING_PROFILE = "48216a7c-4edd-4f5d-9389-95ffbd3ea775"; 723 | PROVISIONING_PROFILE_SPECIFIER = openPlatform_development; 724 | }; 725 | name = Release; 726 | }; 727 | B6F63E051E2C6AA400741516 /* Debug */ = { 728 | isa = XCBuildConfiguration; 729 | baseConfigurationReference = BC461A132E17123A57D98B80 /* Pods-iOS_movingAnnotation_swift.debug.xcconfig */; 730 | buildSettings = { 731 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 732 | INFOPLIST_FILE = iOS_movingAnnotation_swift/Info.plist; 733 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 734 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 735 | PRODUCT_BUNDLE_IDENTIFIER = "com.autonavi.iOS-movingAnnotation-swift"; 736 | PRODUCT_NAME = "$(TARGET_NAME)"; 737 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 738 | SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/iOS_movingAnnotation_swift/Swift_Bridging_Header.h"; 739 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 740 | SWIFT_VERSION = 4.0; 741 | }; 742 | name = Debug; 743 | }; 744 | B6F63E061E2C6AA400741516 /* Release */ = { 745 | isa = XCBuildConfiguration; 746 | baseConfigurationReference = 8809FE9AFB976292E0BBCEF2 /* Pods-iOS_movingAnnotation_swift.release.xcconfig */; 747 | buildSettings = { 748 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 749 | INFOPLIST_FILE = iOS_movingAnnotation_swift/Info.plist; 750 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 751 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 752 | PRODUCT_BUNDLE_IDENTIFIER = "com.autonavi.iOS-movingAnnotation-swift"; 753 | PRODUCT_NAME = "$(TARGET_NAME)"; 754 | SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/iOS_movingAnnotation_swift/Swift_Bridging_Header.h"; 755 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 756 | SWIFT_VERSION = 4.0; 757 | }; 758 | name = Release; 759 | }; 760 | /* End XCBuildConfiguration section */ 761 | 762 | /* Begin XCConfigurationList section */ 763 | 6A2D0F761E1E59220036ACED /* Build configuration list for PBXNativeTarget "iOS_movingAnnotationUITests" */ = { 764 | isa = XCConfigurationList; 765 | buildConfigurations = ( 766 | 6A2D0F771E1E59220036ACED /* Debug */, 767 | 6A2D0F781E1E59220036ACED /* Release */, 768 | ); 769 | defaultConfigurationIsVisible = 0; 770 | defaultConfigurationName = Release; 771 | }; 772 | B6152B8B1DBDDACB00254FC8 /* Build configuration list for PBXProject "iOS_movingAnnotation" */ = { 773 | isa = XCConfigurationList; 774 | buildConfigurations = ( 775 | B6152BA51DBDDACB00254FC8 /* Debug */, 776 | B6152BA61DBDDACB00254FC8 /* Release */, 777 | ); 778 | defaultConfigurationIsVisible = 0; 779 | defaultConfigurationName = Release; 780 | }; 781 | B6152BA71DBDDACB00254FC8 /* Build configuration list for PBXNativeTarget "iOS_movingAnnotation" */ = { 782 | isa = XCConfigurationList; 783 | buildConfigurations = ( 784 | B6152BA81DBDDACB00254FC8 /* Debug */, 785 | B6152BA91DBDDACB00254FC8 /* Release */, 786 | ); 787 | defaultConfigurationIsVisible = 0; 788 | defaultConfigurationName = Release; 789 | }; 790 | B6F63E071E2C6AA400741516 /* Build configuration list for PBXNativeTarget "iOS_movingAnnotation_swift" */ = { 791 | isa = XCConfigurationList; 792 | buildConfigurations = ( 793 | B6F63E051E2C6AA400741516 /* Debug */, 794 | B6F63E061E2C6AA400741516 /* Release */, 795 | ); 796 | defaultConfigurationIsVisible = 0; 797 | defaultConfigurationName = Release; 798 | }; 799 | /* End XCConfigurationList section */ 800 | }; 801 | rootObject = B6152B881DBDDACB00254FC8 /* Project object */; 802 | } 803 | --------------------------------------------------------------------------------