├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Demo ├── Demo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── Demo.xccheckout │ └── xcshareddata │ │ └── xcschemes │ │ └── Demo.xcscheme ├── Demo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── Demo.xccheckout │ │ └── Demo.xcscmblueprint ├── Demo │ ├── Demo-Info.plist │ ├── Demo-Prefix.pch │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── NAAnimatedDemoViewController.h │ ├── NAAnimatedDemoViewController.m │ ├── NAAppDelegate.h │ ├── NAAppDelegate.m │ ├── NADotAnnotationDemoViewController.h │ ├── NADotAnnotationDemoViewController.m │ ├── NAInteractiveDemoViewController.h │ ├── NAInteractiveDemoViewController.m │ ├── NAInteractiveDemoViewController.xib │ ├── NALoadViaNIBDemoViewController.h │ ├── NALoadViaNIBDemoViewController.m │ ├── NALoadViaNIBDemoViewController.xib │ ├── NAMasterViewController.h │ ├── NAMasterViewController.m │ ├── NAPinAnnotationPopup.h │ ├── NAPinAnnotationPopup.m │ ├── NAPinAnnotationPopupCircleCallOutView.h │ ├── NAPinAnnotationPopupCircleCallOutView.m │ ├── NAPinAnnotationPopupMapView.h │ ├── NAPinAnnotationPopupMapView.m │ ├── NAPinAnnotationsDemoViewController.h │ ├── NAPinAnnotationsDemoViewController.m │ ├── NAPinAnnotationsPopupMenuDemoViewController.h │ ├── NAPinAnnotationsPopupMenuDemoViewController.m │ ├── NATiledImageDemoViewController.h │ ├── NATiledImageDemoViewController.m │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── NAMasterViewController.xib │ └── main.m ├── DemoTests │ ├── DemoTests-Info.plist │ ├── DemoTests-Prefix.pch │ ├── NAAnnotationDemoViewControllerTests.m │ ├── NAInteractiveDemoViewControllerTests.m │ ├── NALoadViaNIBDemoViewControllerTests.m │ ├── NAMapViewTests.m │ ├── NAMasterViewControllerTests.m │ ├── NAPinAnnotationsDemoViewControllerTests.m │ ├── NATiledImageMapViewControllerTests.m │ ├── ReferenceImages │ │ ├── NAAnnotationDemoViewControllerSpec │ │ │ └── default@2x.png │ │ ├── NAInteractiveDemoViewControllerSpec │ │ │ ├── add@2x.png │ │ │ ├── default@2x.png │ │ │ ├── remove@2x.png │ │ │ └── select@2x.png │ │ ├── NALoadViaNIBDemoViewControllerSpec │ │ │ └── default@2x.png │ │ ├── NAMasterViewControllerSpec │ │ │ └── default@2x.png │ │ ├── NAPinAnnotationsDemoViewControllerSpec │ │ │ └── default@2x.png │ │ └── NATiledImageDemoViewControllerSpec │ │ │ └── default@2x.png │ └── en.lproj │ │ └── InfoPlist.strings ├── Maps │ ├── Armory2014 │ │ ├── large.jpg │ │ ├── original.jpg │ │ └── tiles │ │ │ ├── 11 │ │ │ ├── 0_0.jpg │ │ │ ├── 0_1.jpg │ │ │ ├── 0_2.jpg │ │ │ ├── 1_0.jpg │ │ │ ├── 1_1.jpg │ │ │ ├── 1_2.jpg │ │ │ ├── 2_0.jpg │ │ │ ├── 2_1.jpg │ │ │ └── 2_2.jpg │ │ │ ├── 12 │ │ │ ├── 0_0.jpg │ │ │ ├── 0_1.jpg │ │ │ ├── 0_2.jpg │ │ │ ├── 0_3.jpg │ │ │ ├── 0_4.jpg │ │ │ ├── 0_5.jpg │ │ │ ├── 1_0.jpg │ │ │ ├── 1_1.jpg │ │ │ ├── 1_2.jpg │ │ │ ├── 1_3.jpg │ │ │ ├── 1_4.jpg │ │ │ ├── 1_5.jpg │ │ │ ├── 2_0.jpg │ │ │ ├── 2_1.jpg │ │ │ ├── 2_2.jpg │ │ │ ├── 2_3.jpg │ │ │ ├── 2_4.jpg │ │ │ ├── 2_5.jpg │ │ │ ├── 3_0.jpg │ │ │ ├── 3_1.jpg │ │ │ ├── 3_2.jpg │ │ │ ├── 3_3.jpg │ │ │ ├── 3_4.jpg │ │ │ ├── 3_5.jpg │ │ │ ├── 4_0.jpg │ │ │ ├── 4_1.jpg │ │ │ ├── 4_2.jpg │ │ │ ├── 4_3.jpg │ │ │ ├── 4_4.jpg │ │ │ └── 4_5.jpg │ │ │ └── 13 │ │ │ ├── 0_0.jpg │ │ │ ├── 0_1.jpg │ │ │ ├── 0_10.jpg │ │ │ ├── 0_2.jpg │ │ │ ├── 0_3.jpg │ │ │ ├── 0_4.jpg │ │ │ ├── 0_5.jpg │ │ │ ├── 0_6.jpg │ │ │ ├── 0_7.jpg │ │ │ ├── 0_8.jpg │ │ │ ├── 0_9.jpg │ │ │ ├── 1_0.jpg │ │ │ ├── 1_1.jpg │ │ │ ├── 1_10.jpg │ │ │ ├── 1_2.jpg │ │ │ ├── 1_3.jpg │ │ │ ├── 1_4.jpg │ │ │ ├── 1_5.jpg │ │ │ ├── 1_6.jpg │ │ │ ├── 1_7.jpg │ │ │ ├── 1_8.jpg │ │ │ ├── 1_9.jpg │ │ │ ├── 2_0.jpg │ │ │ ├── 2_1.jpg │ │ │ ├── 2_10.jpg │ │ │ ├── 2_2.jpg │ │ │ ├── 2_3.jpg │ │ │ ├── 2_4.jpg │ │ │ ├── 2_5.jpg │ │ │ ├── 2_6.jpg │ │ │ ├── 2_7.jpg │ │ │ ├── 2_8.jpg │ │ │ ├── 2_9.jpg │ │ │ ├── 3_0.jpg │ │ │ ├── 3_1.jpg │ │ │ ├── 3_10.jpg │ │ │ ├── 3_2.jpg │ │ │ ├── 3_3.jpg │ │ │ ├── 3_4.jpg │ │ │ ├── 3_5.jpg │ │ │ ├── 3_6.jpg │ │ │ ├── 3_7.jpg │ │ │ ├── 3_8.jpg │ │ │ ├── 3_9.jpg │ │ │ ├── 4_0.jpg │ │ │ ├── 4_1.jpg │ │ │ ├── 4_10.jpg │ │ │ ├── 4_2.jpg │ │ │ ├── 4_3.jpg │ │ │ ├── 4_4.jpg │ │ │ ├── 4_5.jpg │ │ │ ├── 4_6.jpg │ │ │ ├── 4_7.jpg │ │ │ ├── 4_8.jpg │ │ │ ├── 4_9.jpg │ │ │ ├── 5_0.jpg │ │ │ ├── 5_1.jpg │ │ │ ├── 5_10.jpg │ │ │ ├── 5_2.jpg │ │ │ ├── 5_3.jpg │ │ │ ├── 5_4.jpg │ │ │ ├── 5_5.jpg │ │ │ ├── 5_6.jpg │ │ │ ├── 5_7.jpg │ │ │ ├── 5_8.jpg │ │ │ ├── 5_9.jpg │ │ │ ├── 6_0.jpg │ │ │ ├── 6_1.jpg │ │ │ ├── 6_10.jpg │ │ │ ├── 6_2.jpg │ │ │ ├── 6_3.jpg │ │ │ ├── 6_4.jpg │ │ │ ├── 6_5.jpg │ │ │ ├── 6_6.jpg │ │ │ ├── 6_7.jpg │ │ │ ├── 6_8.jpg │ │ │ ├── 6_9.jpg │ │ │ ├── 7_0.jpg │ │ │ ├── 7_1.jpg │ │ │ ├── 7_10.jpg │ │ │ ├── 7_2.jpg │ │ │ ├── 7_3.jpg │ │ │ ├── 7_4.jpg │ │ │ ├── 7_5.jpg │ │ │ ├── 7_6.jpg │ │ │ ├── 7_7.jpg │ │ │ ├── 7_8.jpg │ │ │ ├── 7_9.jpg │ │ │ ├── 8_0.jpg │ │ │ ├── 8_1.jpg │ │ │ ├── 8_10.jpg │ │ │ ├── 8_2.jpg │ │ │ ├── 8_3.jpg │ │ │ ├── 8_4.jpg │ │ │ ├── 8_5.jpg │ │ │ ├── 8_6.jpg │ │ │ ├── 8_7.jpg │ │ │ ├── 8_8.jpg │ │ │ ├── 8_9.jpg │ │ │ ├── 9_0.jpg │ │ │ ├── 9_1.jpg │ │ │ ├── 9_10.jpg │ │ │ ├── 9_2.jpg │ │ │ ├── 9_3.jpg │ │ │ ├── 9_4.jpg │ │ │ ├── 9_5.jpg │ │ │ ├── 9_6.jpg │ │ │ ├── 9_7.jpg │ │ │ ├── 9_8.jpg │ │ │ └── 9_9.jpg │ └── australia.png ├── Podfile ├── Podfile.lock └── Screenshots │ ├── namapkit.gif │ └── namapkit2.gif ├── Gemfile ├── LICENSE ├── NAMapKit.podspec ├── NAMapKit ├── NAAnnotation.h ├── NAAnnotation.m ├── NADotAnnotation.h ├── NADotAnnotation.m ├── NAMapView.h ├── NAMapView.m ├── NAMapViewDelegate.h ├── NAPinAnnotation.h ├── NAPinAnnotation.m ├── NAPinAnnotationCallOutView.h ├── NAPinAnnotationCallOutView.m ├── NAPinAnnotationMapView.h ├── NAPinAnnotationMapView.m ├── NAPinAnnotationView.h ├── NAPinAnnotationView.m ├── NATiledImageMapView.h ├── NATiledImageMapView.m ├── callout_anchor.png ├── callout_anchor@2x.png ├── callout_bg.png ├── callout_bg@2x.png ├── callout_left.png ├── callout_left@2x.png ├── callout_right.png ├── callout_right@2x.png ├── pin_green.png ├── pin_green@2x.png ├── pin_green_floating.png ├── pin_green_floating@2x.png ├── pin_purple.png ├── pin_purple@2x.png ├── pin_purple_floating.png ├── pin_purple_floating@2x.png ├── pin_red.png ├── pin_red@2x.png ├── pin_red_floating.png └── pin_red_floating@2x.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.app 2 | *.mode[12]v3 3 | *.[oa] 4 | *.pbxuser 5 | *.perspective 6 | *.perspectivev3 7 | *.swp 8 | *~ 9 | *~.nib 10 | *~.xib 11 | Demo/build 12 | Demo/build/**/* 13 | Demo/Pods 14 | .DS_Store 15 | xcuserdata 16 | Gemfile.lock 17 | .bundle 18 | 19 | 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | before_script: 3 | - export LANG=en_US.UTF-8 4 | - cd Demo ; pod install ; cd .. 5 | xcode_workspace: Demo/Demo.xcworkspace 6 | xcode_scheme: Demo 7 | xcode_sdk: iphonesimulator 8 | xctool_args: -destination "platform=iOS Simulator,name=iPhone 4s" 9 | osx_image: xcode7.2 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #### Next 2 | 3 | * [#67](https://github.com/neilang/NAMapKit/pull/67) - Added circular pop-up menu sample to Demo project - [@troyz](https://github.com/troyz). 4 | * Your contribution here. 5 | 6 | #### [3.2.1](https://github.com/neilang/NAMapKit/tree/v3.2.1) (4/7/2016) 7 | 8 | * [#59](https://github.com/neiland/NAMapKit/issues/59), [#52](https://github.com/neiland/NAMapKit/issues/52) - Fix: `NAPinAnnotationView` pin images fail to load - [@joeshi](https://github.com/joeshi). 9 | 10 | #### [3.2.0](https://github.com/neilang/NAMapKit/tree/v3.2.0) (12/20/2015) 11 | 12 | * [#46](https://github.com/neilang/NAMapKit/pull/46) - Changed to new push pin style - [@neilang](https://github.com/neilang). 13 | * [#44](https://github.com/neiland/NAMapKit/issues/44) - Added `NAMapView#selectAnnotation:animated` implementation - [@frosty](http://github.com/frosty). 14 | * [#43](https://github.com/neilang/NAMapKit/issues/43) - Fix: `NAMapViewDelegate` protocol optional methods were called without checking `respondsToSelector:` - [@frosty](http://github.com/frosty) 15 | * [#39](https://github.com/neilang/NAMapKit/issues/39) - Added `NAMapView#updateContentOffsetToCenterPoint:animated:` to center map on a point without taking into account the map's `zoomScale` - [@ashfurrow](http://github.com/ashfurrow). 16 | * [#37](https://github.com/neilang/NAMapKit/issues/37) - Added assert inside `NAMapView#zoomRelativePoint` when returning `{NaN, NaN}` - [@ashfurrow](http://github.com/ashfurrow). 17 | 18 | #### [3.1.1](https://github.com/neilang/NAMapKit/tree/v3.1.1) (5/12/2014) 19 | 20 | * [#31](https://github.com/neilang/NAMapKit/issues/31) - Fix: `NAPinAnnotation` and `NAPinAnnotationView` retain cycle - [@dblock](https://github.com/dblock). 21 | * [#34](https://github.com/neilang/NAMapKit/issues/34) - Fix: `NAPinAnnotationCallOutView` uses `imageNamed` which retains memory - [@dblock](https://github.com/dblock). 22 | 23 | #### [3.1](https://github.com/neilang/NAMapKit/tree/v3.1) (5/1/2014) 24 | 25 | * Replaced tiled map image implementation with [ARTiledImageView](https://github.com/dblock/ARTiledImageView) - [@dblock](https://github.com/dblock). 26 | * Extracted [NADotAnnotation](NAMapKit/NADotAnnotation.h) out of [NAAnnotation](NAMapKit/NAAnnotation.h), which is now a pure virtual class - [@dblock](https://github.com/dblock). 27 | * Fix: `NADotAnnotation` dots resize proportionally when map zoom level changes - [@dblock](https://github.com/dblock). 28 | * Exposed `NAMapView#doubleTapGesture` and `NAMapView#twoFingerTapGesture` - [@orta](https://github.com/orta). 29 | 30 | #### [3.0](https://github.com/neilang/NAMapKit/tree/v3.0) (3/15/2014) 31 | 32 | * [#16](https://github.com/neilang/NAMapKit/pull/16) - Extracted [NAPinAnnotationMapView](NAMapKit/NAPinAnnotationMapView.h) out of a, now mimimal, `NAMapView` - [@dblock](https://github.com/dblock). 33 | * [#18](https://github.com/neilang/NAMapKit/pull/18) - Added [NAMapViewDelegate](NAMapKit/NAMapViewDelegate.h) for easier handling of taps and zoom events - [@dblock](https://github.com/dblock). 34 | * [#19](https://github.com/neilang/NAMapKit/pull/19) - Added [NATiledImageMapView](NAMapKit/NATiledImageMapView.h) with support for deep-zoom tiled maps - [@dblock](https://github.com/dblock), [@orta](https://github.com/orta). 35 | * [#20](https://github.com/neilang/NAMapKit/pull/20) - Zoom now pans and rests at the point being tapped - [@orta](https://github.com/orta). 36 | * [#14](https://github.com/neilang/NAMapKit/pull/14) - Added tests and [Travis-CI](https://travis-ci.org/neilang/NAMapKit) - [@dblock](https://github.com/dblock). 37 | 38 | #### [2.1](https://github.com/neilang/NAMapKit/tree/v2.1) 39 | 40 | * [#10](https://github.com/neilang/NAMapKit/pull/10) - Added .podspec - [@donny](https://github.com/donny). 41 | * [#6](https://github.com/neilang/NAMapKit/issues/6) - Added the ability to select annotations on the map - [@neilang](https://github.com/neilang). 42 | 43 | #### [2.0](https://github.com/neilang/NAMapKit/tree/v2.0) 44 | 45 | * Partial rewrite - [@neilang](https://github.com/neilang). 46 | 47 | #### [1.0](https://github.com/neilang/NAMapKit/commits/v1.0) 48 | 49 | * Initial public release - [@neilang](https://github.com/neilang). 50 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.xcworkspace/xcshareddata/Demo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | BCB1E07D-E8DD-4C1E-96B9-7685F28B9C83 9 | IDESourceControlProjectName 10 | Demo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 65214000-E629-4F6A-A8EE-C90A8A8CB933 14 | ssh://github.com/dblock/NAMapKit.git 15 | 16 | IDESourceControlProjectPath 17 | Demo/Demo.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 65214000-E629-4F6A-A8EE-C90A8A8CB933 21 | ../../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/dblock/NAMapKit.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 65214000-E629-4F6A-A8EE-C90A8A8CB933 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 65214000-E629-4F6A-A8EE-C90A8A8CB933 36 | IDESourceControlWCCName 37 | dblock 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/xcshareddata/Demo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 91DB7322-98D0-4C11-8B43-AC4544D5A61C 9 | IDESourceControlProjectName 10 | Demo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | E1849B94-A142-4B49-93EB-CE798BC87886 14 | ssh://github.com/dblock/NAMapKit.git 15 | 16 | IDESourceControlProjectPath 17 | Demo/Demo.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | E1849B94-A142-4B49-93EB-CE798BC87886 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/dblock/NAMapKit.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | E1849B94-A142-4B49-93EB-CE798BC87886 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | E1849B94-A142-4B49-93EB-CE798BC87886 36 | IDESourceControlWCCName 37 | dblock 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/xcshareddata/Demo.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "DF84A17CEBC8A9F5FB371ADC46FB541D99429222", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "E1849B94-A142-4B49-93EB-CE798BC87886" : 0, 8 | "DF84A17CEBC8A9F5FB371ADC46FB541D99429222" : 0 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "91DB7322-98D0-4C11-8B43-AC4544D5A61C", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "E1849B94-A142-4B49-93EB-CE798BC87886" : "dblock", 13 | "DF84A17CEBC8A9F5FB371ADC46FB541D99429222" : "NAMapKit\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "Demo", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Demo\/Demo.xcworkspace", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/neilang\/NAMapKit\/", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "DF84A17CEBC8A9F5FB371ADC46FB541D99429222" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "ssh:\/\/github.com\/dblock\/NAMapKit.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "E1849B94-A142-4B49-93EB-CE798BC87886" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Demo/Demo/Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | NAMapKit 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.neilang.${PRODUCT_NAME:rfc1034identifier} 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 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Demo/Demo/Demo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Demo' target in the 'Demo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Demo/Demo/Images.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" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/NAAnimatedDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnimatedDemoViewController.h 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NAAnimatedDemoViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/Demo/NAAnimatedDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnimatedDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAAnimatedDemoViewController.h" 10 | #import "NAMapView.h" 11 | #import "NAPinAnnotationMapView.h" 12 | #import "NAPinAnnotation.h" 13 | 14 | @implementation NAAnimatedDemoViewController 15 | 16 | - (void)viewDidLoad 17 | { 18 | [super viewDidLoad]; 19 | 20 | NAMapView *mapView = [[NAPinAnnotationMapView alloc] initWithFrame:self.view.bounds]; 21 | 22 | mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 23 | mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 24 | 25 | NSString *australia = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/australia.png"]; 26 | [mapView displayMap:[UIImage imageWithContentsOfFile:australia]]; 27 | 28 | mapView.minimumZoomScale = 0.5f; 29 | mapView.maximumZoomScale = 1.5f; 30 | 31 | [self.view addSubview:mapView]; 32 | 33 | NAPinAnnotation *a0 = [NAPinAnnotation annotationWithPoint:CGPointMake(63.0f, 379.0f)]; 34 | NAPinAnnotation *a1 = [NAPinAnnotation annotationWithPoint:CGPointMake(130.0f, 340.0f)]; 35 | NAPinAnnotation *a2 = [NAPinAnnotation annotationWithPoint:CGPointMake(200.0f, 311.0f)]; 36 | NAPinAnnotation *a3 = [NAPinAnnotation annotationWithPoint:CGPointMake(308.0f, 304.0f)]; 37 | NAPinAnnotation *a4 = [NAPinAnnotation annotationWithPoint:CGPointMake(404.0f, 302.0f)]; 38 | NAPinAnnotation *a5 = [NAPinAnnotation annotationWithPoint:CGPointMake(472.0f, 367.0f)]; 39 | NAPinAnnotation *a6 = [NAPinAnnotation annotationWithPoint:CGPointMake(530.0f, 422.0f)]; 40 | NAPinAnnotation *a7 = [NAPinAnnotation annotationWithPoint:CGPointMake(541.0f, 488.0f)]; 41 | 42 | NSArray *annotations = [NSArray arrayWithObjects:a0, a1, a2, a3, a4, a5, a6, a7, nil]; 43 | 44 | for (NAPinAnnotation *annotation in annotations) { 45 | annotation.title = @"Hello World"; 46 | } 47 | 48 | [mapView addAnnotations:annotations animated:YES]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Demo/Demo/NAAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAAppDelegate.h 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NAAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | @property (strong, nonatomic) UINavigationController *navigationController; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Demo/Demo/NAAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAAppDelegate.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAAppDelegate.h" 10 | 11 | #import "NAMasterViewController.h" 12 | 13 | @implementation NAAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | // Override point for customization after application launch. 19 | 20 | NAMasterViewController *masterViewController = [[NAMasterViewController alloc] initWithNibName:@"NAMasterViewController" bundle:nil]; 21 | self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; 22 | self.window.rootViewController = self.navigationController; 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Demo/Demo/NADotAnnotationDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnnotationDemoViewController.h 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAMapViewDelegate.h" 11 | 12 | @interface NADotAnnotationDemoViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Demo/Demo/NADotAnnotationDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NADotAnnotationDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NADotAnnotationDemoViewController.h" 10 | #import "NAMapView.h" 11 | #import "NADotAnnotation.h" 12 | 13 | @implementation NADotAnnotationDemoViewController 14 | 15 | - (void)viewDidLoad 16 | { 17 | [super viewDidLoad]; 18 | 19 | NAMapView *mapView = [[NAMapView alloc] initWithFrame:self.view.bounds]; 20 | 21 | mapView.mapViewDelegate = self; 22 | mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 23 | mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 24 | 25 | mapView.minimumZoomScale = 0.5f; 26 | mapView.maximumZoomScale = 1.5f; 27 | 28 | NSString *australia = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/australia.png"]; 29 | UIImage *image = [UIImage imageWithContentsOfFile:australia]; 30 | [mapView displayMap:image]; 31 | 32 | [self.view addSubview:mapView]; 33 | 34 | NADotAnnotation *melbourne = [NADotAnnotation annotationWithPoint:CGPointMake(543.0f, 489.0f)]; 35 | melbourne.radius = 10.0f; 36 | [mapView addAnnotation:melbourne animated:NO]; 37 | 38 | NADotAnnotation *perth = [NADotAnnotation annotationWithPoint:CGPointMake(63.0f, 379.0f)]; 39 | perth.radius = 10.0f; 40 | perth.color = [UIColor blackColor]; 41 | [mapView addAnnotation:perth animated:YES]; 42 | 43 | NADotAnnotation *brisbane = [NADotAnnotation annotationWithPoint:CGPointMake(679.0f, 302.0f)]; 44 | brisbane.radius = 10.0f; 45 | brisbane.color = [UIColor orangeColor]; 46 | [mapView addAnnotation:brisbane animated:NO]; 47 | } 48 | 49 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 50 | { 51 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 52 | } 53 | 54 | - (void)mapView:(NAMapView *)mapView tappedOnAnnotation:(NADotAnnotation *)annotation 55 | { 56 | NSLog(@"tapped: %@", annotation); 57 | } 58 | 59 | - (void)mapView:(NAMapView *)mapView hasChangedZoomLevel:(CGFloat)level 60 | { 61 | NSLog(@"zoom: %@", @(level)); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Demo/Demo/NAInteractiveDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAInteractiveDemoViewController.h 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAMapView.h" 11 | #import "NAPinAnnotation.h" 12 | 13 | @interface NAInteractiveDemoViewController : UIViewController 14 | 15 | @property (nonatomic, weak) IBOutlet NAMapView *mapView; 16 | 17 | - (IBAction)addPin:(id)sender; 18 | - (IBAction)removePin:(id)sender; 19 | - (IBAction)selectRandom:(id)sender; 20 | 21 | - (void)addPinAt:(CGPoint)point withColor:(NAPinColor)color animated:(BOOL)animated; 22 | - (void)selectPinAt:(NSInteger)index animated:(BOOL)animated; 23 | - (void)removePinAt:(NSInteger)index animated:(BOOL)animated; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Demo/Demo/NAInteractiveDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAInteractiveDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAInteractiveDemoViewController.h" 10 | #import "NAPinAnnotation.h" 11 | 12 | @interface NAInteractiveDemoViewController () 13 | @property (nonatomic, strong) NSMutableArray *annotations; 14 | @property(nonatomic) NAPinAnnotation * lastFocused; 15 | @property (nonatomic, assign) CGSize size; 16 | @property (weak, nonatomic) IBOutlet UILabel *zoomLevelLabel; 17 | @property (weak, nonatomic) IBOutlet UILabel *selectedPinLabel; 18 | @end 19 | 20 | @implementation NAInteractiveDemoViewController 21 | 22 | - (void)viewDidLoad 23 | { 24 | [super viewDidLoad]; 25 | 26 | self.annotations = [[NSMutableArray alloc] init]; 27 | 28 | self.mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 29 | self.mapView.mapViewDelegate = self; 30 | 31 | NSString *australia = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/australia.png"]; 32 | UIImage *image = [UIImage imageWithContentsOfFile:australia]; 33 | 34 | [self.mapView displayMap:image]; 35 | 36 | [self mapView:self.mapView hasChangedZoomLevel:self.mapView.zoomLevel]; 37 | self.selectedPinLabel.text = @""; 38 | 39 | self.size = image.size; 40 | } 41 | 42 | - (IBAction)addPin:(id)sender { 43 | 44 | NSInteger x = (arc4random() % (int)self.size.width); 45 | NSInteger y = (arc4random() % (int)self.size.width); 46 | 47 | CGPoint point = CGPointMake(x, y); 48 | 49 | [self addPinAt:point withColor:arc4random() % 3 animated:YES]; 50 | } 51 | 52 | - (void)addPinAt:(CGPoint)point withColor:(NAPinColor)color animated:(BOOL)animated { 53 | 54 | [self.mapView centerOnPoint:point animated:animated]; 55 | 56 | NAPinAnnotation *annotation = [NAPinAnnotation annotationWithPoint:point]; 57 | annotation.title = [NSString stringWithFormat:@"Pin %@", @(self.annotations.count + 1)]; 58 | annotation.color = color; 59 | 60 | [self.mapView addAnnotation:annotation animated:animated]; 61 | [self.annotations addObject:annotation]; 62 | 63 | _lastFocused = annotation; 64 | } 65 | 66 | - (IBAction)removePin:(id)sender { 67 | if(self.annotations.count <= 0 || self.lastFocused == nil) return; 68 | NSInteger index = [self.annotations indexOfObject:self.lastFocused]; 69 | [self removePinAt:index animated:YES]; 70 | self.lastFocused = self.annotations.lastObject; 71 | } 72 | 73 | - (void)removePinAt:(NSInteger)index animated:(BOOL)animated { 74 | NAPinAnnotation *annotation = [self.annotations objectAtIndex:index]; 75 | [self.mapView centerOnPoint:annotation.point animated:animated]; 76 | [self.mapView removeAnnotation:annotation]; 77 | [self.annotations removeObject:annotation]; 78 | } 79 | 80 | - (IBAction)selectRandom:(id)sender { 81 | if(self.annotations.count <= 0) return; 82 | 83 | NSInteger rand = (arc4random() % (int)self.annotations.count); 84 | 85 | NAPinAnnotation *annotation = [self.annotations objectAtIndex:rand]; 86 | if (annotation == self.lastFocused && self.annotations.count > 1) { 87 | rand = ((rand + 1) % (int)self.annotations.count); 88 | annotation = [self.annotations objectAtIndex:rand]; 89 | } 90 | 91 | [self selectPin:annotation animated:YES]; 92 | } 93 | 94 | - (void)selectPinAt:(NSInteger)index animated:(BOOL)animated 95 | { 96 | [self selectPin:[self.annotations objectAtIndex:index] animated:animated]; 97 | } 98 | 99 | - (void)selectPin:(NAPinAnnotation *)annotation animated:(BOOL)animated 100 | { 101 | self.selectedPinLabel.text = [NSString stringWithFormat:@"%@", annotation.title]; 102 | [self.mapView selectAnnotation:annotation animated:animated]; 103 | _lastFocused = annotation; 104 | } 105 | 106 | - (void)mapView:(NAMapView *)mapView tappedOnAnnotation:(NAPinAnnotation *)annotation 107 | { 108 | self.selectedPinLabel.text = [NSString stringWithFormat:@"%@", annotation.title]; 109 | } 110 | 111 | - (void)mapView:(NAMapView *)mapView hasChangedZoomLevel:(CGFloat)level 112 | { 113 | self.zoomLevelLabel.text = [NSString stringWithFormat:@"%.2f", level]; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /Demo/Demo/NAInteractiveDemoViewController.xib: -------------------------------------------------------------------------------- 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 | 32 | 39 | 50 | 61 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Demo/Demo/NALoadViaNIBDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NALoadViaNIBDemoViewController.h 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAMapView.h" 11 | 12 | @interface NALoadViaNIBDemoViewController : UIViewController 13 | 14 | @property (nonatomic, weak) IBOutlet NAMapView *mapView; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Demo/Demo/NALoadViaNIBDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NALoadViaNIBDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NALoadViaNIBDemoViewController.h" 10 | #import "NAPinAnnotation.h" 11 | 12 | @implementation NALoadViaNIBDemoViewController 13 | 14 | - (void)viewDidLoad 15 | { 16 | [super viewDidLoad]; 17 | 18 | NSString *australia = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/australia.png"]; 19 | UIImage *image = [UIImage imageWithContentsOfFile:australia]; 20 | [self.mapView displayMap:image]; 21 | 22 | self.mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 23 | 24 | NAPinAnnotation *melbourne = [NAPinAnnotation annotationWithPoint:CGPointMake(543.0f, 489.0f)]; 25 | melbourne.title = @"Melbourne"; 26 | melbourne.subtitle = @"I have a subtitle"; 27 | melbourne.color = NAPinColorGreen; 28 | 29 | [self.mapView addAnnotation:melbourne animated:NO]; 30 | 31 | NAPinAnnotation *perth = [NAPinAnnotation annotationWithPoint:CGPointMake(63.0f, 379.0f)]; 32 | perth.title = @"Perth"; 33 | perth.subtitle = @"I have a button"; 34 | perth.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 35 | perth.color = NAPinColorRed; 36 | 37 | [self.mapView addAnnotation:perth animated:NO]; 38 | 39 | NAPinAnnotation *brisbane = [NAPinAnnotation annotationWithPoint:CGPointMake(679.0f, 302.0f)]; 40 | brisbane.title = @"Brisbane"; 41 | brisbane.color = NAPinColorPurple; 42 | 43 | [self.mapView addAnnotation:brisbane animated:NO]; 44 | } 45 | 46 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 47 | { 48 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Demo/Demo/NALoadViaNIBDemoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1296 5 | 11D50 6 | 2182 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1181 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUIScrollView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 274 41 | {320, 416} 42 | 43 | 44 | 45 | _NS:9 46 | 47 | 2 48 | MCAwLjQ3NDUwOTgzNTIgMC43NDkwMTk2MjI4AA 49 | 50 | YES 51 | YES 52 | IBCocoaTouchFramework 53 | YES 54 | YES 55 | NO 56 | NO 57 | 0.5 58 | 1.5 59 | 60 | 61 | {{0, 64}, {320, 416}} 62 | 63 | 64 | 65 | 66 | 3 67 | MQA 68 | 69 | 2 70 | 71 | 72 | 73 | 74 | NO 75 | 76 | IBCocoaTouchFramework 77 | 78 | 79 | 80 | 81 | 82 | 83 | view 84 | 85 | 86 | 87 | 3 88 | 89 | 90 | 91 | mapView 92 | 93 | 94 | 95 | 5 96 | 97 | 98 | 99 | 100 | 101 | 0 102 | 103 | 104 | 105 | 106 | 107 | 1 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -1 116 | 117 | 118 | File's Owner 119 | 120 | 121 | -2 122 | 123 | 124 | 125 | 126 | 4 127 | 128 | 129 | 130 | 131 | 132 | 133 | NALoadViaNIBDemoViewController 134 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 135 | UIResponder 136 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 137 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 138 | NAMapView 139 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 140 | 141 | 142 | 143 | 144 | 145 | 5 146 | 147 | 148 | 149 | 150 | NALoadViaNIBDemoViewController 151 | UIViewController 152 | 153 | mapView 154 | NAMapView 155 | 156 | 157 | mapView 158 | 159 | mapView 160 | NAMapView 161 | 162 | 163 | 164 | IBProjectSource 165 | ./Classes/NALoadViaNIBDemoViewController.h 166 | 167 | 168 | 169 | NAMapView 170 | UIScrollView 171 | 172 | showCallOut: 173 | id 174 | 175 | 176 | showCallOut: 177 | 178 | showCallOut: 179 | id 180 | 181 | 182 | 183 | IBProjectSource 184 | ./Classes/NAMapView.h 185 | 186 | 187 | 188 | 189 | 0 190 | IBCocoaTouchFramework 191 | 192 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 193 | 194 | 195 | YES 196 | 3 197 | 1181 198 | 199 | 200 | -------------------------------------------------------------------------------- /Demo/Demo/NAMasterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAMasterViewController.h 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NADetailViewController; 12 | 13 | @interface NAMasterViewController : UITableViewController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Demo/Demo/NAMasterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAMasterViewController.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAMasterViewController.h" 10 | #import "NADotAnnotationDemoViewController.h" 11 | #import "NAPinAnnotationsDemoViewController.h" 12 | #import "NALoadViaNIBDemoViewController.h" 13 | #import "NAAnimatedDemoViewController.h" 14 | #import "NAInteractiveDemoViewController.h" 15 | #import "NATiledImageDemoViewController.h" 16 | #import "NAPinAnnotationsPopupMenuDemoViewController.h" 17 | 18 | @implementation NAMasterViewController 19 | 20 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 21 | { 22 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 23 | if (self) { 24 | self.title = @"NAMapKit"; 25 | } 26 | return self; 27 | } 28 | 29 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 30 | { 31 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 32 | } 33 | 34 | #pragma mark - Table View 35 | 36 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 37 | { 38 | return 1; 39 | } 40 | 41 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 42 | if([self isRunningTests]) 43 | { 44 | return 6; 45 | } 46 | else 47 | { 48 | return 7; 49 | } 50 | } 51 | 52 | - (BOOL)isRunningTests 53 | { 54 | return NSClassFromString(@"XCTest") != nil; 55 | } 56 | 57 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 58 | { 59 | static NSString *CellIdentifier = @"Cell"; 60 | 61 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 62 | if (cell == nil) { 63 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 64 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 65 | } 66 | 67 | switch (indexPath.row) { 68 | case 0: 69 | cell.textLabel.text = @"Simple Annotations Demo"; 70 | break; 71 | case 1: 72 | cell.textLabel.text = @"Pin Annotations Demo"; 73 | break; 74 | case 2: 75 | cell.textLabel.text = @"Load Via NIB Demo"; 76 | break; 77 | case 3: 78 | cell.textLabel.text = @"Animated Pins Demo"; 79 | break; 80 | case 4: 81 | cell.textLabel.text = @"Interactive Demo"; 82 | break; 83 | case 5: 84 | cell.textLabel.text = @"Tiled Map Demo"; 85 | break; 86 | case 6: 87 | cell.textLabel.text = @"Pin Annotations Popup Menu Demo"; 88 | break; 89 | default: 90 | cell.textLabel.text = @"???"; 91 | break; 92 | } 93 | 94 | return cell; 95 | } 96 | 97 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 98 | 99 | if(indexPath.row == 0){ 100 | NADotAnnotationDemoViewController *vc = [[NADotAnnotationDemoViewController alloc] initWithNibName:nil bundle:nil]; 101 | [self.navigationController pushViewController:vc animated:YES]; 102 | } else if(indexPath.row == 1){ 103 | NAPinAnnotationsDemoViewController *vc = [[NAPinAnnotationsDemoViewController alloc] initWithNibName:nil bundle:nil]; 104 | [self.navigationController pushViewController:vc animated:YES]; 105 | } else if (indexPath.row == 2){ 106 | NALoadViaNIBDemoViewController *vc = [[NALoadViaNIBDemoViewController alloc] initWithNibName:@"NALoadViaNIBDemoViewController" bundle:nil]; 107 | [self.navigationController pushViewController:vc animated:YES]; 108 | } else if (indexPath.row == 3){ 109 | NAAnimatedDemoViewController *vc = [[NAAnimatedDemoViewController alloc] initWithNibName:nil bundle:nil]; 110 | [self.navigationController pushViewController:vc animated:YES]; 111 | } else if (indexPath.row == 4){ 112 | NAInteractiveDemoViewController *vc = [[NAInteractiveDemoViewController alloc] initWithNibName:@"NAInteractiveDemoViewController" bundle:nil]; 113 | [self.navigationController pushViewController:vc animated:YES]; 114 | } else if (indexPath.row == 5){ 115 | NATiledImageDemoViewController *vc = [[NATiledImageDemoViewController alloc] initWithNibName:nil bundle:nil]; 116 | [self.navigationController pushViewController:vc animated:YES]; 117 | } else if(indexPath.row == 6){ 118 | NAPinAnnotationsPopupMenuDemoViewController *vc = [[NAPinAnnotationsPopupMenuDemoViewController alloc] initWithNibName:nil bundle:nil]; 119 | [self.navigationController pushViewController:vc animated:YES]; 120 | } 121 | } 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationPopup.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationPopup.h 3 | // NAMapKit 4 | // 5 | // Created by xdzhangm on 16/5/4. 6 | // 7 | 8 | #import "NAPinAnnotation.h" 9 | 10 | // 弹出菜单样式 11 | typedef NS_ENUM(NSInteger, NAPopupMenuStyle) 12 | { 13 | POP_UP_MENU_STYLE_DEFAULT = 0, 14 | POP_UP_MENU_STYLE_CIRCLE = 1, // 圆形 15 | }; 16 | 17 | /** 18 | * An annotation that looks like a pin. 19 | */ 20 | @interface NAPinAnnotationPopup : NAPinAnnotation 21 | 22 | @property (nonatomic, assign) NAPopupMenuStyle menuStyle; 23 | @property (nonatomic, strong) NSArray *subTitleList; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationPopup.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotation.m 3 | // NAMapKit 4 | // 5 | // Created by xdzhangm on 16/5/4. 6 | // 7 | 8 | #import "NAPinAnnotationPopup.h" 9 | 10 | @implementation NAPinAnnotationPopup 11 | 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationPopupCircleCallOutView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationPopupCircleCallOutView.h 3 | // Pods 4 | // 5 | // Created by xdzhangm on 16/4/29. 6 | // 7 | // 8 | /* 9 | | 10 | | 11 | | 12 | topLine 13 | | 14 | | 15 | | 16 | b1 b0 17 | 18 | 19 | b3 | CenterView | b2 20 | 21 | 22 | b5 b4 23 | | 24 | 25 | b6 26 | */ 27 | #import 28 | 29 | #import "NAMapView.h" 30 | #import "NAPinAnnotation.h" 31 | 32 | @protocol NAPinAnnotationPopupCircleCallOutViewDelegate 33 | @required 34 | - (NSInteger)numbersOfCircleForCallOutView; 35 | @end 36 | 37 | @interface NAPinAnnotationPopupCircleCallOutView : UIView 38 | - (id)initOnMapView:(NAMapView *)mapView; 39 | - (void)showMenuAtPoint:(CGPoint)point; 40 | - (void)hideMenu:(BOOL)animated; 41 | - (void)updatePosition; 42 | - (void)setTitle:(NSString *)title; 43 | 44 | // left side index: 1, 3, 5 45 | // right side index: 0, 2, 4 46 | - (UIButton *)menuAtIndex:(NSInteger)index; 47 | @property (nonatomic, weak) NAMapView *mapView; 48 | @property (nonatomic, weak) id delegate; 49 | @property (readwrite, nonatomic, strong) NAPinAnnotation *annotation; 50 | @end 51 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationPopupCircleCallOutView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationPopupCircleCallOutView.m 3 | // Pods 4 | // 5 | // Created by xdzhangm on 16/4/29. 6 | // 7 | // 8 | 9 | #import "NAPinAnnotationPopupCircleCallOutView.h" 10 | #import 11 | 12 | #define VIEW_W_H 260 13 | #define CENTER_W_H 110 14 | #define BUTTON_W_H 44 15 | // distance between big circle and small circle 16 | #define C_C_LENGTH (VIEW_W_H / 2.0 - BUTTON_W_H / 2.0) 17 | #define C_C_LENGTH_SIN (sin(M_PI / 4.0) * C_C_LENGTH) 18 | #define MAX_SMALL_CIRCLE 7 19 | 20 | @interface NAPinAnnotationPopupCircleCallOutView() 21 | { 22 | UILabel *centerView; 23 | NSMutableDictionary *frameDict; 24 | CGPoint mapAtPoint; 25 | CGPoint atPoint; 26 | BOOL isHiddening; 27 | dispatch_group_t animateGroup; 28 | } 29 | @end 30 | 31 | @implementation NAPinAnnotationPopupCircleCallOutView 32 | - (instancetype)init 33 | { 34 | return [self initOnMapView:nil]; 35 | } 36 | - (id)initOnMapView:(NAMapView *)mapView 37 | { 38 | self = [super init]; 39 | if(self) 40 | { 41 | animateGroup = dispatch_group_create(); 42 | 43 | self.mapView = mapView; 44 | [self initVariables]; 45 | [self initViews]; 46 | 47 | self.hidden = YES; 48 | [self hideMenu:NO]; 49 | } 50 | return self; 51 | } 52 | 53 | - (void)initVariables 54 | { 55 | frameDict = [[NSMutableDictionary alloc] init]; 56 | } 57 | 58 | - (CGFloat)getMenuAngle:(NSInteger)i 59 | { 60 | return M_PI * 0.25 * (i - 1); 61 | } 62 | 63 | - (void)initViews 64 | { 65 | self.frame = CGRectMake(0, 0, VIEW_W_H, VIEW_W_H); 66 | self.layer.anchorPoint = CGPointMake(0.5, 0); 67 | 68 | centerView = [[UILabel alloc] init]; 69 | centerView.font = [UIFont boldSystemFontOfSize:14]; 70 | centerView.numberOfLines = 0; 71 | centerView.textAlignment = NSTextAlignmentCenter; 72 | centerView.textColor = [UIColor orangeColor]; 73 | centerView.backgroundColor = [UIColor whiteColor]; 74 | centerView.frame = CGRectMake((VIEW_W_H - CENTER_W_H) / 2.0, (VIEW_W_H - CENTER_W_H) / 2.0, CENTER_W_H, CENTER_W_H); 75 | centerView.clipsToBounds = YES; 76 | centerView.layer.cornerRadius = CENTER_W_H / 2.0; 77 | [self addSubview:centerView]; 78 | 79 | UIImage *lineImage = [self createImageWithColor:[UIColor whiteColor] withFrame:CGRectMake(0, 0, VIEW_W_H / 2.0 - BUTTON_W_H, 1)]; 80 | 81 | UIImageView *lineView = [[UIImageView alloc] initWithImage:lineImage]; 82 | lineView.frame = CGRectMake(VIEW_W_H / 2.0, 0, lineImage.size.height, VIEW_W_H / 2.0); 83 | lineView.tag = 10; 84 | [self addSubview:lineView]; 85 | [self sendSubviewToBack:lineView]; 86 | 87 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 88 | { 89 | CGFloat angle = [self getMenuAngle:i]; 90 | 91 | UIButton *btnView = [UIButton buttonWithType:UIButtonTypeCustom]; 92 | btnView.tag = (i + 1); 93 | [btnView setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal]; 94 | btnView.titleLabel.font = [UIFont systemFontOfSize:12.0]; 95 | [btnView setTitle:[NSString stringWithFormat:@"b%zd", (i + 1)] forState:UIControlStateNormal]; 96 | btnView.clipsToBounds = YES; 97 | btnView.layer.cornerRadius = BUTTON_W_H / 2.0; 98 | // btnView.layer.borderColor = RGBColor(0, 0, 0).CGColor; 99 | // btnView.layer.borderWidth = 1.0; 100 | btnView.frame = CGRectMake(VIEW_W_H / 2.0 + cos(angle) * C_C_LENGTH - BUTTON_W_H / 2.0, VIEW_W_H / 2.0 + sin(angle) * C_C_LENGTH - BUTTON_W_H / 2.0, BUTTON_W_H, BUTTON_W_H); 101 | [btnView setBackgroundColor:[UIColor whiteColor]]; 102 | [btnView setBackgroundImage:[self createImageWithColor:[UIColor orangeColor]] forState:UIControlStateHighlighted]; 103 | [btnView setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; 104 | [self addSubview:btnView]; 105 | 106 | UIImageView *lineView = [[UIImageView alloc] initWithImage:lineImage]; 107 | lineView.frame = CGRectMake(VIEW_W_H / 2.0, VIEW_W_H / 2.0, lineImage.size.width, lineImage.size.height); 108 | lineView.tag = (10 + btnView.tag); 109 | lineView.transform = [self getTransformWithCenter:lineView.center withPoint:centerView.center withAngle:angle]; 110 | [self addSubview:lineView]; 111 | [self sendSubviewToBack:lineView]; 112 | 113 | [frameDict setObject:[NSValue valueWithCGPoint:btnView.center] forKey:@(btnView.tag)]; 114 | } 115 | 116 | [self bringSubviewToFront:centerView]; 117 | } 118 | 119 | - (CGAffineTransform) getTransformWithCenter:(CGPoint)center 120 | withPoint:(CGPoint)point 121 | withAngle:(CGFloat)angle 122 | { 123 | CGFloat x = point.x - center.x; //计算(x,y)从(0,0)为原点的坐标系变换到(CenterX ,CenterY)为原点的坐标系下的坐标 124 | CGFloat y = point.y - center.y; //(0,0)坐标系的右横轴、下竖轴是正轴,(CenterX,CenterY)坐标系的正轴也一样 125 | 126 | CGAffineTransform trans = CGAffineTransformMakeTranslation(x, y); 127 | trans = CGAffineTransformRotate(trans,angle); 128 | trans = CGAffineTransformTranslate(trans,-x, -y); 129 | return trans; 130 | } 131 | 132 | - (void)updatePosition 133 | { 134 | if(self.mapView) 135 | { 136 | atPoint = [self.mapView zoomRelativePoint:mapAtPoint]; 137 | atPoint.y -= 35; 138 | } 139 | self.layer.position = atPoint; 140 | CGFloat angle = [self getAngleByPoint:atPoint center:[self screenCenterPoint]]; 141 | [UIView animateWithDuration:0.3 animations:^{ 142 | self.transform = CGAffineTransformMakeRotation(angle);//[self getTransformWithCenter:self.center withPoint:atPoint withAngle:angle]; 143 | centerView.transform = CGAffineTransformMakeRotation(-angle); 144 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 145 | { 146 | UIButton *btnView = [self viewWithTag:i + 1]; 147 | btnView.transform = CGAffineTransformMakeRotation(-angle); 148 | } 149 | }]; 150 | } 151 | 152 | - (void)showMenuAtPoint:(CGPoint)point 153 | { 154 | // 有可能当前hideMenu正在执行,需要等待hideMenu执行完毕后,才可执行show 155 | dispatch_group_notify(animateGroup, dispatch_get_main_queue(), ^{ 156 | isHiddening = NO; 157 | mapAtPoint = point; 158 | if(self.mapView) 159 | { 160 | atPoint = [self.mapView zoomRelativePoint:mapAtPoint]; 161 | atPoint.y -= 35; 162 | } 163 | else 164 | { 165 | atPoint = point; 166 | } 167 | self.layer.position = atPoint; 168 | 169 | CGFloat angle = [self getAngleByPoint:atPoint center:[self screenCenterPoint]]; 170 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 171 | { 172 | UIButton *btnView = [self viewWithTag:i + 1]; 173 | btnView.transform = CGAffineTransformIdentity; 174 | btnView.transform = CGAffineTransformMakeRotation(-angle); 175 | } 176 | self.transform = CGAffineTransformMakeRotation(angle);//[self getTransformWithCenter:self.center withPoint:atPoint withAngle:angle]; 177 | centerView.transform = CGAffineTransformMakeRotation(-angle); 178 | self.hidden = NO; 179 | [self showCenterView]; 180 | }); 181 | } 182 | 183 | - (CGPoint)screenCenterPoint 184 | { 185 | CGPoint point = self.mapView.contentOffset; 186 | point.x += self.mapView.bounds.size.width / 2.0; 187 | point.y += self.mapView.bounds.size.height / 2.0; 188 | return point; 189 | } 190 | 191 | -(CGFloat)getAngleByPoint:(CGPoint)nowPoint center:(CGPoint)center 192 | { 193 | if(nowPoint.y == center.y) 194 | { 195 | if(nowPoint.x >= center.x) 196 | { 197 | return M_PI; 198 | } 199 | else 200 | { 201 | return -M_PI; 202 | } 203 | } 204 | if(nowPoint.x >= center.x && nowPoint.y >= center.y) 205 | { 206 | return M_PI - atan((nowPoint.x - center.x) / (nowPoint.y - center.y)); 207 | } 208 | else if(nowPoint.x >= center.x && nowPoint.y <= center.y) 209 | { 210 | return atan((nowPoint.x - center.x) / (center.y - nowPoint.y)); 211 | } 212 | else if(nowPoint.x <= center.x && nowPoint.y >= center.y) 213 | { 214 | return - (M_PI - atan((center.x - nowPoint.x) / (nowPoint.y - center.y))); 215 | } 216 | else 217 | { 218 | return - atan((center.x - nowPoint.x) / (center.y - nowPoint.y)); 219 | } 220 | } 221 | 222 | - (void)showMenu:(NSNumber *)num 223 | { 224 | NSInteger i = [num integerValue]; 225 | if(((i + 1) > (MAX_SMALL_CIRCLE + 1) / 2) || ((i + 1) > (([self menuCount] / 2) + ([self menuCount] % 2 == 0 ? 0 : 1)))) 226 | { 227 | return; 228 | } 229 | for(NSInteger _i = 0; _i < MAX_SMALL_CIRCLE; _i++) 230 | { 231 | if(_i == i || _i + i == MAX_SMALL_CIRCLE - 1) 232 | { 233 | if([self menuCount] % 2 != 0 && (i + 1) * 2 > [self menuCount] && _i != i) 234 | { 235 | continue; 236 | } 237 | POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerSize]; 238 | animation.springSpeed = 8; 239 | 240 | UIView *view = [self viewWithTag:_i + 11]; 241 | animation.toValue = [NSValue valueWithCGSize:CGSizeMake(VIEW_W_H / 2.0 - BUTTON_W_H, 1.0)] ; 242 | if(_i == i) 243 | { 244 | [self performSelector:@selector(showMenu:) withObject:@(i + 1) afterDelay:0.15]; 245 | } 246 | [view.layer pop_addAnimation:animation forKey:@"animation"]; 247 | 248 | [UIView animateWithDuration:0.25 animations:^{ 249 | UIView *view = [self viewWithTag:_i + 1]; 250 | view.center = [((NSValue *)[frameDict objectForKey:@(view.tag)]) CGPointValue]; 251 | }]; 252 | } 253 | } 254 | } 255 | 256 | - (void)hideMenu:(BOOL)animated 257 | { 258 | if(animated) 259 | { 260 | [self hideMenuWithAnimate]; 261 | } 262 | else 263 | { 264 | [self hideMenuImediately]; 265 | } 266 | } 267 | 268 | - (void)hideMenuImediately 269 | { 270 | self.hidden = YES; 271 | isHiddening = NO; 272 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 273 | { 274 | UIView *view = [self viewWithTag:i + 11]; 275 | view.bounds = CGRectMake(view.bounds.origin.x, view.bounds.origin.y, CENTER_W_H / 2.0 - BUTTON_W_H, 1.0); 276 | } 277 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 278 | { 279 | UIView *view = [self viewWithTag:i + 1]; 280 | view.transform = CGAffineTransformIdentity; 281 | view.center = CGPointMake(VIEW_W_H / 2.0 + (CENTER_W_H / 2.0 - BUTTON_W_H / 2.0) * cos([self getMenuAngle:i]), VIEW_W_H / 2.0 + (CENTER_W_H / 2.0 - BUTTON_W_H / 2.0) * sin([self getMenuAngle:i])); 282 | } 283 | [self toggleShowSmallCircle:NO]; 284 | UIView *topLineView = [self viewWithTag:10]; 285 | topLineView.bounds = CGRectMake(VIEW_W_H / 2.0, 0, 0, 0); 286 | topLineView.layer.position = CGPointMake(VIEW_W_H / 2.0, 0); 287 | 288 | centerView.layer.position = CGPointMake(VIEW_W_H / 2.0, 0); 289 | // TODO: How to scale view WITHOUT animation????? 290 | POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 291 | scaleAnimation.duration = 0; 292 | scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeZero]; 293 | [centerView.layer pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"]; 294 | } 295 | 296 | - (void)hideMenuWithAnimate 297 | { 298 | if(isHiddening) 299 | { 300 | return; 301 | } 302 | dispatch_group_enter(animateGroup); 303 | isHiddening = YES; 304 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 305 | { 306 | POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerSize]; 307 | animation.springSpeed = 3; 308 | UIView *view = [self viewWithTag:i + 11]; 309 | animation.toValue = [NSValue valueWithCGSize:CGSizeMake(CENTER_W_H / 2.0 - BUTTON_W_H, 1.0)]; 310 | [view.layer pop_addAnimation:animation forKey:@"animation"]; 311 | } 312 | 313 | [UIView animateWithDuration:0.3 animations:^{ 314 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 315 | { 316 | UIView *view = [self viewWithTag:i + 1]; 317 | view.transform = CGAffineTransformIdentity; 318 | view.center = CGPointMake(VIEW_W_H / 2.0 + (CENTER_W_H / 2.0 - BUTTON_W_H / 2.0) * cos([self getMenuAngle:i]), VIEW_W_H / 2.0 + (CENTER_W_H / 2.0 - BUTTON_W_H / 2.0) * sin([self getMenuAngle:i])); 319 | } 320 | } completion:^(BOOL finished) { 321 | if(isHiddening) 322 | { 323 | [self hideCenterView]; 324 | } 325 | }]; 326 | } 327 | 328 | - (void)hideCenterView 329 | { 330 | [self toggleShowSmallCircle:NO]; 331 | 332 | UIView *topLineView = [self viewWithTag:10]; 333 | 334 | POPSpringAnimation *sizeAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerSize]; 335 | sizeAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(topLineView.frame.size.width, 0)]; 336 | 337 | POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition]; 338 | positionAnimation.toValue = [NSValue valueWithCGPoint:topLineView.frame.origin]; 339 | 340 | [topLineView.layer pop_addAnimation:sizeAnimation forKey:@"sizeAnimation"]; 341 | [topLineView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"]; 342 | 343 | 344 | POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 345 | scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeZero]; 346 | positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition]; 347 | positionAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(VIEW_W_H / 2.0, 0)]; 348 | 349 | [centerView.layer pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"]; 350 | [centerView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"]; 351 | 352 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 353 | self.hidden = YES; 354 | isHiddening = NO; 355 | dispatch_group_leave(animateGroup); 356 | }); 357 | } 358 | 359 | - (void)showCenterView 360 | { 361 | UIView *topLineView = [self viewWithTag:10]; 362 | 363 | POPSpringAnimation *sizeAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerSize]; 364 | sizeAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.0, VIEW_W_H / 2.0)]; 365 | 366 | POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition]; 367 | positionAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(VIEW_W_H / 2.0, VIEW_W_H / 4.0)]; 368 | 369 | [topLineView.layer pop_addAnimation:sizeAnimation forKey:@"sizeAnimation"]; 370 | [topLineView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"]; 371 | 372 | POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 373 | scaleAnimation.springBounciness = 8; 374 | scaleAnimation.springSpeed = 8; 375 | scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.0, 1.0)]; 376 | 377 | positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition]; 378 | positionAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(VIEW_W_H / 2.0, VIEW_W_H / 2.0)]; 379 | 380 | [centerView.layer pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"]; 381 | [centerView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"]; 382 | 383 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 384 | [self toggleShowSmallCircle:YES]; 385 | [self showMenu:@(0)]; 386 | }); 387 | } 388 | 389 | - (void)toggleShowSmallCircle:(BOOL)isShow 390 | { 391 | for(NSInteger i = 0; i < MAX_SMALL_CIRCLE; i++) 392 | { 393 | [self viewWithTag:(i + 1)].hidden = !isShow; 394 | [self viewWithTag:(i + 11)].hidden = !isShow; 395 | } 396 | } 397 | 398 | - (NSInteger)menuCount 399 | { 400 | if(_delegate && [_delegate respondsToSelector:@selector(numbersOfCircleForCallOutView)]) 401 | { 402 | return [_delegate numbersOfCircleForCallOutView]; 403 | } 404 | return 0; 405 | } 406 | 407 | - (UIButton *)menuAtIndex:(NSInteger)index 408 | { 409 | if(index >= MAX_SMALL_CIRCLE) 410 | { 411 | return nil; 412 | } 413 | NSInteger tag = (index % 2 == 0) ? (index / 2 + 1) : (MAX_SMALL_CIRCLE + 1 - ((index - 1) / 2 + 1)); 414 | UIView *view = [self viewWithTag:tag]; 415 | return [view isKindOfClass:[UIButton class]] ? (UIButton *)view : nil; 416 | } 417 | 418 | /** 419 | * 判断点击区域是否属于当前view 420 | */ 421 | - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 422 | { 423 | BOOL isInside = [super pointInside:point withEvent:event]; 424 | if(isInside) 425 | { 426 | isInside = NO; 427 | for(NSInteger i = 0; i < [self menuCount]; i++) 428 | { 429 | UIButton *btnView = [self menuAtIndex:i]; 430 | CGPoint center = btnView.center; 431 | CGFloat xOffset = center.x - point.x; 432 | CGFloat yOffset = center.y - point.y; 433 | if(sqrt(xOffset * xOffset + yOffset * yOffset) < BUTTON_W_H / 2.0) 434 | { 435 | NSLog(@"menu button tapped"); 436 | return YES; 437 | } 438 | } 439 | CGPoint center = centerView.center; 440 | CGFloat xOffset = center.x - point.x; 441 | CGFloat yOffset = center.y - point.y; 442 | if(sqrt(xOffset * xOffset + yOffset * yOffset) < CENTER_W_H / 2.0) 443 | { 444 | NSLog(@"center view tapped"); 445 | return YES; 446 | } 447 | } 448 | return isInside; 449 | } 450 | 451 | - (void)setTitle:(NSString *)title 452 | { 453 | centerView.text = title; 454 | } 455 | 456 | /* 457 | // Only override drawRect: if you perform custom drawing. 458 | // An empty implementation adversely affects performance during animation. 459 | - (void)drawRect:(CGRect)rect { 460 | // Drawing code 461 | } 462 | */ 463 | 464 | - (UIImage *)createImageWithColor:(UIColor *)color 465 | { 466 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 467 | return [self createImageWithColor:color withFrame:rect]; 468 | } 469 | 470 | - (UIImage *)createImageWithColor:(UIColor *)color withFrame:(CGRect)frame 471 | { 472 | UIGraphicsBeginImageContext(frame.size); 473 | CGContextRef context = UIGraphicsGetCurrentContext(); 474 | CGContextSetFillColorWithColor(context, [color CGColor]); 475 | CGContextFillRect(context, frame); 476 | UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); 477 | UIGraphicsEndImageContext(); 478 | 479 | return theImage; 480 | } 481 | 482 | - (void)setAnnotation:(NAPinAnnotation *)annotation 483 | { 484 | _annotation = annotation; 485 | [self showMenuAtPoint:annotation.point]; 486 | [self updatePosition]; 487 | [self setTitle:annotation.title]; 488 | } 489 | @end 490 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationPopupMapView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationPopupMapView.h 3 | // NAMapKit 4 | // 5 | // Created by xdzhangm on 16/5/4. 6 | // 7 | 8 | #import "NAMapView.h" 9 | #import "NAPinAnnotation.h" 10 | #import "NAPinAnnotationPopup.h" 11 | #import "NAPinAnnotationView.h" 12 | #import "NAPinAnnotationCallOutView.h" 13 | 14 | /** 15 | * A map view with pin annotations. 16 | */ 17 | @interface NAPinAnnotationPopupMapView : NAMapView 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationPopupMapView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationPopupMapView.m 3 | // NAMapKit 4 | // 5 | // Created by xdzhangm on 16/5/4. 6 | // 7 | 8 | #import "NAPinAnnotationPopupMapView.h" 9 | #import "NAPinAnnotationPopupCircleCallOutView.h" 10 | #import 11 | 12 | const CGFloat NAMapViewAnnotationCalloutAnimationDemoDuration = 0.1f; 13 | 14 | @interface NAPinAnnotationPopupMapView() 15 | 16 | @property (nonatomic, strong) NAPinAnnotationCallOutView *calloutView; 17 | @property (nonatomic, strong) NAPinAnnotationPopupCircleCallOutView *circleCalloutView; 18 | 19 | - (IBAction)showCallOut:(id)sender; 20 | - (void)hideCallOut; 21 | @end 22 | 23 | @implementation NAPinAnnotationPopupMapView 24 | 25 | - (void)setupMap 26 | { 27 | [super setupMap]; 28 | 29 | _calloutView = [[NAPinAnnotationCallOutView alloc] initOnMapView:self]; 30 | [self addSubview:self.calloutView]; 31 | 32 | _circleCalloutView = [[NAPinAnnotationPopupCircleCallOutView alloc] initOnMapView:self]; 33 | _circleCalloutView.delegate = self; 34 | [self addSubview:_circleCalloutView]; 35 | } 36 | 37 | - (void)addAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate 38 | { 39 | [super addAnnotation:annotation animated:animate]; 40 | if ([annotation.view isKindOfClass:NAPinAnnotationView.class]) { 41 | NAPinAnnotationView *annotationView = (NAPinAnnotationView *) annotation.view; 42 | [annotationView addTarget:self action:@selector(showCallOut:) forControlEvents:UIControlEventTouchDown]; 43 | } 44 | [self bringSubviewToFront:self.calloutView]; 45 | [self bringSubviewToFront:self.circleCalloutView]; 46 | } 47 | 48 | - (void)selectAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate 49 | { 50 | if([annotation isKindOfClass:NAPinAnnotation.class]) { 51 | [self showCalloutForAnnotation:(NAPinAnnotation *)annotation animated:animate]; 52 | } 53 | else{ 54 | [self hideCallOut]; 55 | } 56 | } 57 | 58 | - (void)removeAnnotation:(NAAnnotation *)annotation 59 | { 60 | [self hideCallOut]; 61 | [super removeAnnotation:annotation]; 62 | } 63 | 64 | - (IBAction)showCallOut:(id)sender 65 | { 66 | if([sender isKindOfClass:[NAPinAnnotationView class]]) { 67 | NAPinAnnotationView *annontationView = (NAPinAnnotationView *)sender; 68 | 69 | if ([self.mapViewDelegate respondsToSelector:@selector(mapView:tappedOnAnnotation:)]) { 70 | [self.mapViewDelegate mapView:self tappedOnAnnotation:annontationView.annotation]; 71 | } 72 | 73 | [self showCalloutForAnnotation:annontationView.annotation animated:YES]; 74 | } 75 | } 76 | 77 | - (void)showCalloutForAnnotation:(NAPinAnnotation *)annotation animated:(BOOL)animated 78 | { 79 | NSLog(@"%f, %f", annotation.point.x, annotation.point.y); 80 | 81 | if(!self.circleCalloutView.hidden) 82 | { 83 | [self.circleCalloutView hideMenu:NO]; 84 | } 85 | else 86 | { 87 | [self hideCallOut]; 88 | } 89 | 90 | if([annotation isKindOfClass:[NAPinAnnotationPopup class]] && ((NAPinAnnotationPopup *)annotation).menuStyle == POP_UP_MENU_STYLE_CIRCLE) 91 | { 92 | NAPinAnnotationPopup *annotationPopup = (NAPinAnnotationPopup *)annotation; 93 | [self bringSubviewToFront:self.circleCalloutView]; 94 | for(NSInteger i = 0; i < annotationPopup.subTitleList.count; i++) 95 | { 96 | NSString *title = annotationPopup.subTitleList[i]; 97 | UIButton *btnView = [self.circleCalloutView menuAtIndex:i]; 98 | [btnView setTitle:title forState:UIControlStateNormal]; 99 | } 100 | self.circleCalloutView.annotation = annotation; 101 | } 102 | else 103 | { 104 | self.calloutView.annotation = annotation; 105 | 106 | [self centerOnPoint:annotation.point animated:animated]; 107 | 108 | CGFloat animationDuration = animated ? NAMapViewAnnotationCalloutAnimationDemoDuration : 0.0f; 109 | 110 | self.calloutView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4f, 0.4f); 111 | self.calloutView.hidden = NO; 112 | 113 | __weak typeof(self) weakSelf = self; 114 | [UIView animateWithDuration:animationDuration animations:^{ 115 | weakSelf.calloutView.transform = CGAffineTransformIdentity; 116 | }]; 117 | } 118 | } 119 | 120 | - (void)hideCallOut 121 | { 122 | self.calloutView.hidden = YES; 123 | if(!self.circleCalloutView.hidden) 124 | { 125 | [self.circleCalloutView hideMenu:YES]; 126 | } 127 | } 128 | 129 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 130 | { 131 | if (!self.dragging) { 132 | [self hideCallOut]; 133 | } 134 | 135 | [super touchesEnded:touches withEvent:event]; 136 | } 137 | 138 | - (void)updatePositions 139 | { 140 | [self.calloutView updatePosition]; 141 | [self.circleCalloutView updatePosition]; 142 | [super updatePositions]; 143 | } 144 | 145 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 146 | { 147 | if(!self.circleCalloutView.hidden) 148 | { 149 | [self.circleCalloutView updatePosition]; 150 | } 151 | [self checkAnnotationViewVisible]; 152 | } 153 | 154 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 155 | { 156 | if(!self.circleCalloutView.hidden) 157 | { 158 | [self.circleCalloutView updatePosition]; 159 | } 160 | [self checkAnnotationViewVisible]; 161 | } 162 | 163 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 164 | { 165 | if(!self.circleCalloutView.hidden) 166 | { 167 | [self.circleCalloutView updatePosition]; 168 | } 169 | [self checkAnnotationViewVisible]; 170 | } 171 | 172 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView 173 | { 174 | [super scrollViewDidZoom:scrollView]; 175 | if(!self.circleCalloutView.hidden) 176 | { 177 | [self.circleCalloutView updatePosition]; 178 | } 179 | [self checkAnnotationViewVisible]; 180 | } 181 | 182 | - (void)checkAnnotationViewVisible 183 | { 184 | if(_circleCalloutView.hidden && _calloutView.hidden) 185 | { 186 | return; 187 | } 188 | UIView *view = _circleCalloutView.hidden ? _calloutView.annotation.view : _circleCalloutView.annotation.view; 189 | CGRect screenBounds = [UIScreen mainScreen].bounds; 190 | CGRect viewBounds = [view convertRect:view.bounds toView:nil]; 191 | if(!CGRectIntersectsRect(viewBounds, screenBounds)) 192 | { 193 | [self hideCallOut]; 194 | } 195 | } 196 | 197 | - (NSInteger)numbersOfCircleForCallOutView 198 | { 199 | return ((NAPinAnnotationPopup *)_circleCalloutView.annotation).subTitleList.count; 200 | } 201 | @end 202 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationsDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationsDemoViewController.h 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NAPinAnnotationsDemoViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationsDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationsDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotationsDemoViewController.h" 10 | #import "NAMapView.h" 11 | #import "NAPinAnnotationMapView.h" 12 | #import "NAPinAnnotation.h" 13 | 14 | @implementation NAPinAnnotationsDemoViewController 15 | 16 | - (void)viewDidLoad 17 | { 18 | [super viewDidLoad]; 19 | 20 | NAMapView *mapView = [[NAPinAnnotationMapView alloc] initWithFrame:self.view.bounds]; 21 | 22 | mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 23 | mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 24 | 25 | mapView.minimumZoomScale = 0.5f; 26 | mapView.maximumZoomScale = 1.5f; 27 | 28 | NSString *australia = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/australia.png"]; 29 | [mapView displayMap:[UIImage imageWithContentsOfFile:australia]]; 30 | 31 | [self.view addSubview:mapView]; 32 | 33 | NAPinAnnotation *melbourne = [NAPinAnnotation annotationWithPoint:CGPointMake(543.0f, 489.0f)]; 34 | melbourne.title = @"Melbourne"; 35 | melbourne.subtitle = @"I have a subtitle"; 36 | melbourne.color = NAPinColorGreen; 37 | 38 | [mapView addAnnotation:melbourne animated:NO]; 39 | 40 | NAPinAnnotation * perth = [NAPinAnnotation annotationWithPoint:CGPointMake(63.0f, 379.0f)]; 41 | perth.title = @"Perth"; 42 | perth.subtitle = @"I have a button"; 43 | perth.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 44 | perth.color = NAPinColorRed; 45 | 46 | [mapView addAnnotation:perth animated:NO]; 47 | 48 | NAPinAnnotation * brisbane = [NAPinAnnotation annotationWithPoint:CGPointMake(679.0f, 302.0f)]; 49 | brisbane.title = @"Brisbane"; 50 | brisbane.color = NAPinColorPurple; 51 | 52 | [mapView addAnnotation:brisbane animated:NO]; 53 | } 54 | 55 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 56 | { 57 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationsPopupMenuDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationsPopupMenuDemoViewController.h 3 | // Demo 4 | // 5 | // Created by xdzhangm on 16/5/4. 6 | // Copyright © 2016年 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NAPinAnnotationsPopupMenuDemoViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/Demo/NAPinAnnotationsPopupMenuDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationsPopupMenuDemoViewController.m 3 | // Demo 4 | // 5 | // Created by xdzhangm on 16/5/4. 6 | // Copyright © 2016年 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotationsPopupMenuDemoViewController.h" 10 | #import "NAMapView.h" 11 | #import "NAPinAnnotationPopupMapView.h" 12 | #import "NAPinAnnotationPopup.h" 13 | 14 | @interface NAPinAnnotationsPopupMenuDemoViewController () 15 | 16 | @end 17 | 18 | @implementation NAPinAnnotationsPopupMenuDemoViewController 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | 24 | NAMapView *mapView = [[NAPinAnnotationPopupMapView alloc] initWithFrame:self.view.bounds]; 25 | 26 | mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 27 | mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 28 | 29 | mapView.minimumZoomScale = 0.5f; 30 | mapView.maximumZoomScale = 1.5f; 31 | 32 | NSString *australia = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/australia.png"]; 33 | [mapView displayMap:[UIImage imageWithContentsOfFile:australia]]; 34 | 35 | [self.view addSubview:mapView]; 36 | 37 | NAPinAnnotationPopup *melbourne = [NAPinAnnotationPopup annotationWithPoint:CGPointMake(543.0f, 489.0f)]; 38 | melbourne.title = @"Melbourne"; 39 | melbourne.menuStyle = POP_UP_MENU_STYLE_CIRCLE; 40 | melbourne.subTitleList = @[@"Menu 1", @"Menu 2", @"Menu 3"]; 41 | 42 | [mapView addAnnotation:melbourne animated:NO]; 43 | 44 | NAPinAnnotationPopup * perth = [NAPinAnnotationPopup annotationWithPoint:CGPointMake(63.0f, 379.0f)]; 45 | perth.title = @"Perth"; 46 | perth.menuStyle = POP_UP_MENU_STYLE_CIRCLE; 47 | perth.subTitleList = @[@"Menu 1", @"Menu 2", @"Menu 3", @"Menu 4"]; 48 | 49 | [mapView addAnnotation:perth animated:NO]; 50 | 51 | NAPinAnnotation * brisbane = [NAPinAnnotation annotationWithPoint:CGPointMake(679.0f, 302.0f)]; 52 | brisbane.title = @"Brisbane"; 53 | brisbane.color = NAPinColorPurple; 54 | 55 | [mapView addAnnotation:brisbane animated:NO]; 56 | } 57 | 58 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 59 | { 60 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 61 | } 62 | 63 | - (void)didReceiveMemoryWarning { 64 | [super didReceiveMemoryWarning]; 65 | // Dispose of any resources that can be recreated. 66 | } 67 | 68 | /* 69 | #pragma mark - Navigation 70 | 71 | // In a storyboard-based application, you will often want to do a little preparation before navigation 72 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 73 | // Get the new view controller using [segue destinationViewController]. 74 | // Pass the selected object to the new view controller. 75 | } 76 | */ 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Demo/Demo/NATiledImageDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NATiledImageDemoViewController.h 3 | // 4 | // Created by Daniel Doubrovkine on 3/10/14. 5 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface NATiledImageDemoViewController : UIViewController 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Demo/Demo/NATiledImageDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NATiledImageDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/10/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NATiledImageDemoViewController.h" 10 | #import "NATiledImageMapView.h" 11 | #import 12 | #import "NADotAnnotation.h" 13 | 14 | @interface NATiledImageDemoViewController () 15 | @property(nonatomic, readonly) NATiledImageMapView *mapView; 16 | @property(nonatomic, readonly) ARLocalTiledImageDataSource *dataSource; 17 | @end 18 | 19 | @implementation NATiledImageDemoViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | 25 | ARLocalTiledImageDataSource *dataSource = [[ARLocalTiledImageDataSource alloc] init]; 26 | dataSource.maxTiledHeight = 5389; 27 | dataSource.maxTiledWidth = 5000; 28 | dataSource.minTileLevel = 11; 29 | dataSource.maxTileLevel = 13; 30 | dataSource.tileSize = 512; 31 | dataSource.tileFormat = @"jpg"; 32 | dataSource.tileBasePath = [NSString stringWithFormat:@"%@/Maps/Armory2014/tiles", [NSBundle mainBundle].resourcePath]; 33 | _dataSource = dataSource; 34 | 35 | NATiledImageMapView *mapView = [[NATiledImageMapView alloc] initWithFrame:self.view.bounds tiledImageDataSource:dataSource]; 36 | mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 37 | mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 38 | mapView.displayTileBorders = YES; 39 | 40 | // NSString *background = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Maps/Armory2014/large.jpg"]; 41 | // mapView.backgroundImage = [UIImage imageWithContentsOfFile:background]; 42 | 43 | mapView.zoomStep = 3.0f; 44 | _mapView = mapView; 45 | 46 | [self.view addSubview:mapView]; 47 | 48 | NADotAnnotation *champagneBar = [NADotAnnotation annotationWithPoint:CGPointMake(1500.0f, 4850.1f)]; 49 | champagneBar.radius = 50.0f; 50 | champagneBar.color = [UIColor redColor]; 51 | [mapView addAnnotation:champagneBar animated:NO]; 52 | 53 | NADotAnnotation *artsyBooth = [NADotAnnotation annotationWithPoint:CGPointMake(2650.0f, 916.12f)]; 54 | artsyBooth.radius = 40.0f; 55 | artsyBooth.color = [UIColor greenColor]; 56 | [mapView addAnnotation:artsyBooth animated:NO]; 57 | } 58 | 59 | - (void)viewDidAppear:(BOOL)animated 60 | { 61 | [self.mapView zoomToFit:animated]; 62 | } 63 | 64 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 65 | { 66 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Demo/Demo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Demo/Demo/en.lproj/NAMasterViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11C25 6 | 1919 7 | 1138.11 8 | 566.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 916 12 | 13 | 14 | IBProxyObject 15 | IBUITableView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBCocoaTouchFramework 28 | 29 | 30 | IBFirstResponder 31 | IBCocoaTouchFramework 32 | 33 | 34 | 35 | 274 36 | {{0, 20}, {320, 460}} 37 | 38 | 39 | 40 | 3 41 | MQA 42 | 43 | YES 44 | 45 | IBCocoaTouchFramework 46 | YES 47 | 1 48 | 0 49 | YES 50 | 44 51 | 22 52 | 22 53 | 54 | 55 | 56 | 57 | 58 | 59 | view 60 | 61 | 62 | 63 | 3 64 | 65 | 66 | 67 | dataSource 68 | 69 | 70 | 71 | 4 72 | 73 | 74 | 75 | delegate 76 | 77 | 78 | 79 | 5 80 | 81 | 82 | 83 | 84 | 85 | 0 86 | 87 | 88 | 89 | 90 | 91 | -1 92 | 93 | 94 | File's Owner 95 | 96 | 97 | -2 98 | 99 | 100 | 101 | 102 | 2 103 | 104 | 105 | 106 | 107 | 108 | 109 | NAMasterViewController 110 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 111 | UIResponder 112 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 113 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 114 | 115 | 116 | 117 | 118 | 119 | 5 120 | 121 | 122 | 123 | 124 | NAMasterViewController 125 | UITableViewController 126 | 127 | IBProjectSource 128 | ./Classes/NAMasterViewController.h 129 | 130 | 131 | 132 | 133 | 0 134 | IBCocoaTouchFramework 135 | YES 136 | 3 137 | 916 138 | 139 | 140 | -------------------------------------------------------------------------------- /Demo/Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Demo 4 | // 5 | // Created by Neil Ang on 6/05/12. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "NAAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([NAAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demo/DemoTests/DemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.neilang.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Demo/DemoTests/DemoTests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // DemoTests-Prefix.pch 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/6/14. 6 | // Copyright (c) 2014 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifndef __IPHONE_4_0 12 | #warning "This project uses features only available in iOS SDK 4.0 and later." 13 | #endif 14 | 15 | #ifdef __OBJC__ 16 | 17 | #define EXP_SHORTHAND 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Demo/DemoTests/NAAnnotationDemoViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnnotationDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/8/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NADotAnnotationDemoViewController.h" 10 | 11 | SpecBegin(NAAnnotationDemoViewController) 12 | 13 | it(@"displays map with a pin", ^{ 14 | NADotAnnotationDemoViewController *vc = [[NADotAnnotationDemoViewController alloc] init]; 15 | expect(vc.view).willNot.beNil(); 16 | expect(vc.view).will.haveValidSnapshotNamed(@"default"); 17 | }); 18 | 19 | SpecEnd 20 | -------------------------------------------------------------------------------- /Demo/DemoTests/NAInteractiveDemoViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAInteractiveDemoViewControllerTests.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAInteractiveDemoViewController.h" 10 | 11 | SpecBegin(NAInteractiveDemoViewController) 12 | 13 | __block NAInteractiveDemoViewController *vc = nil; 14 | 15 | beforeEach(^{ 16 | vc = [[NAInteractiveDemoViewController alloc] init]; 17 | expect(vc.view).willNot.beNil(); 18 | }); 19 | 20 | it(@"doesn't display any pins", ^{ 21 | expect(vc.view).will.haveValidSnapshotNamed(@"default"); 22 | }); 23 | 24 | it(@"adds a pin", ^{ 25 | [vc addPinAt:CGPointMake(100, 200) withColor:NAPinColorRed animated:NO]; 26 | expect(vc.view).will.haveValidSnapshotNamed(@"add"); 27 | }); 28 | 29 | it(@"removes a pin", ^{ 30 | [vc addPinAt:CGPointMake(100, 200) withColor:NAPinColorRed animated:NO]; 31 | [vc addPinAt:CGPointMake(200, 300) withColor:NAPinColorGreen animated:NO]; 32 | [vc removePinAt:0 animated:NO]; 33 | expect(vc.view).will.haveValidSnapshotNamed(@"remove"); 34 | }); 35 | 36 | it(@"selects a pin", ^{ 37 | [vc addPinAt:CGPointMake(100, 200) withColor:NAPinColorRed animated:NO]; 38 | [vc addPinAt:CGPointMake(200, 300) withColor:NAPinColorGreen animated:NO]; 39 | [vc selectPinAt:1 animated:NO]; 40 | expect(vc.view).will.haveValidSnapshotNamed(@"select"); 41 | }); 42 | 43 | SpecEnd 44 | -------------------------------------------------------------------------------- /Demo/DemoTests/NALoadViaNIBDemoViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAInteractiveLoadViaNIBDemoViewControllerTests.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NALoadViaNIBDemoViewController.h" 10 | 11 | SpecBegin(NALoadViaNIBDemoViewController) 12 | 13 | it(@"displays a menu", ^{ 14 | NALoadViaNIBDemoViewController *vc = [[NALoadViaNIBDemoViewController alloc] init]; 15 | expect(vc.view).willNot.beNil(); 16 | expect(vc.view).will.haveValidSnapshotNamed(@"default"); 17 | }); 18 | 19 | SpecEnd 20 | -------------------------------------------------------------------------------- /Demo/DemoTests/NAMapViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAMapKitTests 3 | // 4 | // Created by Daniel Doubrovkine on 3/6/14. 5 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 6 | // 7 | 8 | #import "NADotAnnotation.h" 9 | 10 | SpecBegin(NAMapView) 11 | 12 | describe(@"init", ^{ 13 | 14 | __block NAMapView *mapView = nil; 15 | 16 | beforeEach(^{ 17 | mapView = [[NAMapView alloc] init]; 18 | }); 19 | 20 | it(@"creates an instance", ^{ 21 | expect(mapView).toNot.beNil(); 22 | expect(mapView).to.beKindOf([NAMapView class]); 23 | }); 24 | 25 | it(@"asserts on zoomRelativePoint: with a zero content size", ^{ 26 | expect(^{[mapView zoomRelativePoint:CGPointZero];}).to.raise(@"NSInternalInconsistencyException"); 27 | }); 28 | }); 29 | 30 | describe(@"a map view", ^{ 31 | __block NAMapView *mapView = nil; 32 | 33 | beforeEach(^{ 34 | mapView = [[NAMapView alloc] init]; 35 | mapView.bounds = CGRectMake(0, 0, 50, 50); 36 | mapView.contentSize = CGSizeMake(100, 100); 37 | mapView.originalSize = CGSizeMake(100, 100); 38 | }); 39 | 40 | it(@"sets the contentOffset correctly when centering on a point", ^{ 41 | [mapView updateContentOffsetToCenterPoint:CGPointMake(10, 10) animated:NO]; 42 | expect(mapView.contentOffset.x).to.equal(-15); 43 | expect(mapView.contentOffset.y).to.equal(-15); 44 | }); 45 | 46 | it(@"sets the contentOffset correctly when centering on an annotation", ^{ 47 | NADotAnnotation *annotation = [NADotAnnotation annotationWithPoint:CGPointMake(70, 70)]; 48 | [mapView addAnnotation:annotation animated:NO]; 49 | 50 | [mapView selectAnnotation:annotation animated:NO]; 51 | 52 | expect(mapView.contentOffset.x).to.equal(45); 53 | expect(mapView.contentOffset.y).to.equal(45); 54 | }); 55 | }); 56 | 57 | SpecEnd 58 | 59 | -------------------------------------------------------------------------------- /Demo/DemoTests/NAMasterViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoMenuTests.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAMasterViewController.h" 10 | 11 | SpecBegin(NAMasterViewController) 12 | 13 | it(@"displays the master menu", ^{ 14 | NAMasterViewController *vc = [[NAMasterViewController alloc] initWithNibName:@"NAMasterViewController" bundle:nil]; 15 | expect(vc.view).willNot.beNil(); 16 | expect(vc.view).will.haveValidSnapshotNamed(@"default"); 17 | }); 18 | 19 | SpecEnd 20 | -------------------------------------------------------------------------------- /Demo/DemoTests/NAPinAnnotationsDemoViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationsDemoViewController.m 3 | // Demo 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotationsDemoViewController.h" 10 | #import "NAPinAnnotation.h" 11 | 12 | SpecBegin(NAPinAnnotationsDemoViewController) 13 | 14 | __block NAPinAnnotationsDemoViewController *vc = nil; 15 | 16 | beforeEach(^{ 17 | vc = [[NAPinAnnotationsDemoViewController alloc] init]; 18 | expect(vc.view).willNot.beNil(); 19 | }); 20 | 21 | it(@"displays map with a pin", ^{ 22 | expect(vc.view).will.haveValidSnapshotNamed(@"default"); 23 | }); 24 | 25 | SpecEnd 26 | -------------------------------------------------------------------------------- /Demo/DemoTests/NATiledImageMapViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NATiledImageMapViewTests.m 3 | // 4 | // Created by Daniel Doubrovkine on 3/11/14. 5 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 6 | // 7 | 8 | #import "NATiledImageDemoViewController.h" 9 | 10 | SpecBegin(NATiledImageDemoViewController) 11 | 12 | __block NATiledImageDemoViewController *vc = nil; 13 | 14 | beforeEach(^{ 15 | UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 16 | vc = [[NATiledImageDemoViewController alloc] init]; 17 | window.rootViewController = vc; 18 | expect(vc.view).willNot.beNil(); 19 | [window makeKeyAndVisible]; 20 | }); 21 | 22 | it(@"displays map with a pin", ^AsyncBlock { 23 | dispatch_async(dispatch_get_main_queue(), ^{ 24 | [NSThread sleepForTimeInterval:3.0]; 25 | expect(vc.view).will.haveValidSnapshotNamed(@"default"); 26 | done(); 27 | }); 28 | }); 29 | 30 | SpecEnd 31 | -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAAnnotationDemoViewControllerSpec/default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAAnnotationDemoViewControllerSpec/default@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/add@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/default@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/remove@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/remove@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/select@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAInteractiveDemoViewControllerSpec/select@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NALoadViaNIBDemoViewControllerSpec/default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NALoadViaNIBDemoViewControllerSpec/default@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAMasterViewControllerSpec/default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAMasterViewControllerSpec/default@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NAPinAnnotationsDemoViewControllerSpec/default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NAPinAnnotationsDemoViewControllerSpec/default@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/ReferenceImages/NATiledImageDemoViewControllerSpec/default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/DemoTests/ReferenceImages/NATiledImageDemoViewControllerSpec/default@2x.png -------------------------------------------------------------------------------- /Demo/DemoTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/large.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/original.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/0_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/0_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/0_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/0_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/0_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/0_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/1_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/1_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/1_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/1_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/1_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/1_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/2_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/2_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/2_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/2_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/11/2_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/11/2_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/0_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/0_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/0_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/0_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/0_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/0_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/0_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/0_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/0_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/0_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/0_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/0_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/1_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/1_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/1_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/1_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/1_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/1_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/1_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/1_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/1_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/1_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/1_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/1_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/2_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/2_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/2_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/2_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/2_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/2_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/2_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/2_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/2_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/2_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/2_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/2_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/3_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/3_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/3_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/3_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/3_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/3_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/3_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/3_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/3_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/3_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/3_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/3_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/4_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/4_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/4_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/4_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/4_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/4_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/4_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/4_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/4_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/4_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/12/4_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/12/4_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/0_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/0_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/1_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/1_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/2_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/2_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/3_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/3_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/4_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/4_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/5_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/5_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/6_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/6_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/7_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/7_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/8_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/8_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_0.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_1.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_10.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_2.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_3.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_4.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_5.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_6.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_7.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_8.jpg -------------------------------------------------------------------------------- /Demo/Maps/Armory2014/tiles/13/9_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/Armory2014/tiles/13/9_9.jpg -------------------------------------------------------------------------------- /Demo/Maps/australia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Maps/australia.png -------------------------------------------------------------------------------- /Demo/Podfile: -------------------------------------------------------------------------------- 1 | pod "NAMapKit", :path => "../namapkit.podspec" 2 | pod "pop" 3 | 4 | target "DemoTests" do 5 | pod 'Specta', '~> 0.2.1' 6 | pod 'Expecta', '~> 0.2.3' 7 | pod 'FBSnapshotTestCase', '~> 1.1' 8 | pod 'EXPMatchers+FBSnapshotTest', '~> 1.1.0' 9 | end 10 | 11 | -------------------------------------------------------------------------------- /Demo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ARTiledImageView (1.1.1): 3 | - SDWebImage 4 | - Expecta (0.2.4) 5 | - EXPMatchers+FBSnapshotTest (1.1.0): 6 | - Expecta 7 | - FBSnapshotTestCase 8 | - FBSnapshotTestCase (1.8.1) 9 | - NAMapKit (3.2.1): 10 | - ARTiledImageView 11 | - SDWebImage 12 | - pop (1.0.9) 13 | - SDWebImage (3.7.5): 14 | - SDWebImage/Core (= 3.7.5) 15 | - SDWebImage/Core (3.7.5) 16 | - Specta (0.2.1) 17 | 18 | DEPENDENCIES: 19 | - Expecta (~> 0.2.3) 20 | - EXPMatchers+FBSnapshotTest (~> 1.1.0) 21 | - FBSnapshotTestCase (~> 1.1) 22 | - NAMapKit (from `../namapkit.podspec`) 23 | - pop 24 | - Specta (~> 0.2.1) 25 | 26 | EXTERNAL SOURCES: 27 | NAMapKit: 28 | :path: ../namapkit.podspec 29 | 30 | SPEC CHECKSUMS: 31 | ARTiledImageView: 8c6fd11d9e8459a853d94394adea3a5e8c9329ba 32 | Expecta: cfaf1d3e2e194ca704a25e997093d30a1ce70b61 33 | EXPMatchers+FBSnapshotTest: 3c48e8a29a445476fe2d72d7da45dfdd765b5f55 34 | FBSnapshotTestCase: 3dc3899168747a0319c5278f5b3445c13a6532dd 35 | NAMapKit: 43b79013f2003216e0a301168b6b3603ed67687f 36 | pop: f667631a5108a2e60d9e8797c9b32ddaf2080bce 37 | SDWebImage: 69c6303e3348fba97e03f65d65d4fbc26740f461 38 | Specta: 15a276a6343867b426d5ed135d5aa4d04123a573 39 | 40 | COCOAPODS: 0.39.0 41 | -------------------------------------------------------------------------------- /Demo/Screenshots/namapkit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Screenshots/namapkit.gif -------------------------------------------------------------------------------- /Demo/Screenshots/namapkit2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/Demo/Screenshots/namapkit2.gif -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'cocoapods', '0.39.0' 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Neil Ang, Tony Arnold 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /NAMapKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "NAMapKit" 3 | s.version = "3.2.1" 4 | s.summary = "A custom and simple framework for creating custom maps. Not based on MapKit." 5 | s.homepage = "https://github.com/neilang/NAMapKit" 6 | s.license = 'MIT' 7 | s.authors = { "Neil Ang" => "neil@neilang.com", "Tony Arnold" => "tony@thecocoabots.com", "Daniel Doubrovkine" => "dblock@dblock.org", "Orta Therox" => "orta.therox@gmail.com" } 8 | s.source = { :git => "https://github.com/neilang/NAMapKit.git", :tag => "v#{s.version}" } 9 | s.platform = :ios, '6.0' 10 | s.source_files = "NaMapKit/*.{h,m}" 11 | s.resources = "NAMapKit/*.png" 12 | s.frameworks = 'Foundation', 'UIKit', 'CoreGraphics' 13 | s.requires_arc = true 14 | s.dependency 'SDWebImage' 15 | s.dependency 'ARTiledImageView' 16 | end 17 | -------------------------------------------------------------------------------- /NAMapKit/NAAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnnotation.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAMapViewDelegate.h" 11 | 12 | @class NAMapView; 13 | 14 | /** 15 | * An annotation is a point on a map. 16 | */ 17 | @interface NAAnnotation : NSObject 18 | 19 | /// Point on the map. 20 | @property (nonatomic, assign) CGPoint point; 21 | /// Associated view, displayed on an NAMapView. 22 | @property (nonatomic, readonly) UIView *view; 23 | 24 | /// Create an annotation at a given point. 25 | + (id)annotationWithPoint:(CGPoint)point; 26 | /// Create an annotation at a given point. 27 | - (id)initWithPoint:(CGPoint)point; 28 | 29 | /// Callback invoked when adding an annotation to a map view. 30 | - (void)addToMapView:(NAMapView *)mapView animated:(BOOL)animate; 31 | 32 | /// Remove this annotation from its map view. 33 | - (void)removeFromMapView; 34 | /// Update the annotation position when zooming in or out. 35 | - (void)updatePosition; 36 | 37 | /// Override to return a custom view when the annotation is being added to a map view. 38 | - (UIView *)createViewOnMapView:(NAMapView *)mapView; 39 | 40 | /// A delegate to invoke map-specific events. 41 | @property (nonatomic, weak) NSObject *mapViewDelegate; 42 | /// Map view to which the annotation currently belongs. 43 | @property (nonatomic, readonly, weak) NAMapView *mapView; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /NAMapKit/NAAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnnotation.m 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAAnnotation.h" 10 | #import "NAMapView.h" 11 | 12 | const CGFloat NAMapViewAnnotationDotRadius = 20.0f; 13 | const CGFloat NAMapViewAnnotationDotOpacity = 0.5f; 14 | 15 | @implementation NAAnnotation 16 | 17 | + (id)annotationWithPoint:(CGPoint)point 18 | { 19 | return [[[self class] alloc] initWithPoint:point]; 20 | } 21 | 22 | - (id)initWithPoint:(CGPoint)point{ 23 | self = [super init]; 24 | if (self) { 25 | _point = point; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)addToMapView:(NAMapView *)mapView animated:(BOOL)animate 31 | { 32 | NSAssert(!self.mapView, @"Annotation already added to map."); 33 | 34 | if (!self.view) { 35 | _view = [self createViewOnMapView:mapView]; 36 | } 37 | 38 | [mapView addSubview:self.view]; 39 | _mapView = mapView; 40 | 41 | _mapViewDelegate = mapView.mapViewDelegate; 42 | 43 | [self updatePosition]; 44 | } 45 | 46 | - (void)removeFromMapView 47 | { 48 | [self.view removeFromSuperview]; 49 | _mapView = nil; 50 | _view = nil; 51 | } 52 | 53 | - (void)updatePosition 54 | { 55 | if (!self.mapView) { 56 | return; 57 | } 58 | 59 | CGPoint point = [self.mapView zoomRelativePoint:self.point]; 60 | self.view.frame = (CGRect) { 61 | .origin = point, 62 | .size = self.view.bounds.size 63 | }; 64 | } 65 | 66 | - (UIView *)createViewOnMapView:(NAMapView *)mapView 67 | { 68 | [NSException raise:NSInternalInconsistencyException format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]; 69 | return nil; 70 | } 71 | 72 | - (IBAction)tappedOnAnnotation:(id)sender 73 | { 74 | if ([self.mapViewDelegate respondsToSelector:@selector(mapView:tappedOnAnnotation:)]) { 75 | [self.mapViewDelegate mapView:self.mapView tappedOnAnnotation:self]; 76 | } 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /NAMapKit/NADotAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // NADotAnnotation.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAAnnotation.h" 10 | 11 | /** 12 | * An dot annotation. 13 | */ 14 | @interface NADotAnnotation : NAAnnotation 15 | 16 | /// Dot radius. 17 | @property (readwrite, nonatomic, assign) CGFloat radius; 18 | /// Dot color. 19 | @property (readwrite, nonatomic, strong) UIColor *color; 20 | /// Dot opacity. 21 | @property (readwrite, nonatomic, assign) CGFloat opacity; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /NAMapKit/NADotAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAAnnotation.m 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NADotAnnotation.h" 10 | #import "NAMapView.h" 11 | 12 | const CGFloat NAMapViewDotAnnotationDotRadius = 20.0f; 13 | const CGFloat NAMapViewDotAnnotationDotOpacity = 0.5f; 14 | 15 | @implementation NADotAnnotation 16 | 17 | - (void)updatePosition 18 | { 19 | if (!self.mapView) { 20 | return; 21 | } 22 | 23 | CGFloat radius = (self.radius ?: NAMapViewDotAnnotationDotRadius) * self.mapView.zoomScale; 24 | CGPoint point = [self.mapView zoomRelativePoint:self.point]; 25 | point.x -= radius; 26 | point.y -= radius; 27 | self.view.layer.cornerRadius = radius; 28 | self.view.frame = CGRectMake(point.x, point.y, radius*2, radius*2); 29 | } 30 | 31 | - (UIView *)createViewOnMapView:(NAMapView *)mapView 32 | { 33 | UIButton *view = [[UIButton alloc] init]; 34 | view.alpha = self.opacity ?: NAMapViewDotAnnotationDotOpacity; 35 | view.backgroundColor = self.color ?: [UIColor redColor]; 36 | [view addTarget:self action:@selector(tappedOnAnnotation:) forControlEvents:UIControlEventTouchDown]; 37 | return view; 38 | } 39 | 40 | - (IBAction)tappedOnAnnotation:(id)sender 41 | { 42 | if ([self.mapViewDelegate respondsToSelector:@selector(mapView:tappedOnAnnotation:)]) { 43 | [self.mapViewDelegate mapView:self.mapView tappedOnAnnotation:self]; 44 | } 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /NAMapKit/NAMapView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAMapView.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAAnnotation.h" 11 | #import "NAMapViewDelegate.h" 12 | 13 | /// A zoomable, scrollable map with an image in the background. 14 | @interface NAMapView : UIScrollView 15 | 16 | /// Display a map with a background image. 17 | - (void)displayMap:(UIImage *)map; 18 | /// Add an annotation. 19 | - (void)addAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate; 20 | // Add an array of annotations. 21 | - (void)addAnnotations:(NSArray *)annotations animated:(BOOL)animate; 22 | /// Remove an annotation. 23 | - (void)removeAnnotation:(NAAnnotation *)annotation; 24 | /// Calculate the point on the screen from a point on the original image at the current zoom level. 25 | - (CGPoint)zoomRelativePoint:(CGPoint)point; 26 | /// Select a particular annotation, notably centers the map on the annotation point. 27 | - (void)selectAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate; 28 | /// Center map on a given point. 29 | - (void)centerOnPoint:(CGPoint)point animated:(BOOL)animate; 30 | /// Center map on a given point (measured relative to contentSize). 31 | - (void)updateContentOffsetToCenterPoint:(CGPoint)point animated:(BOOL)animate; 32 | /// Callback invoked to setup the map. 33 | - (void)setupMap; 34 | /// Recalculate position of all elements. 35 | - (void)updatePositions; 36 | 37 | /// Current map zoom level. 38 | @property (readonly, nonatomic, assign) CGFloat zoomLevel; 39 | /// Point on which to center the map by default. 40 | @property (readwrite, nonatomic, assign) CGPoint centerPoint; 41 | /// A delegate for receiving map notifications. 42 | @property (readwrite, nonatomic, weak) NSObject *mapViewDelegate; 43 | /// Size of the map, typically the full size of the background image. 44 | @property (readwrite, nonatomic, assign) CGSize originalSize; 45 | /// Amount by which to zoom in or zoom out with every double-tap, default is 1.5f. 46 | @property (readwrite, nonatomic, assign) CGFloat zoomStep; 47 | /// The double tap gesture for zooming in 48 | @property (readwrite, nonatomic, strong) UITapGestureRecognizer *doubleTapGesture; 49 | /// The double tap gesture for zooming out 50 | @property (readwrite, nonatomic, strong) UITapGestureRecognizer *twoFingerTapGesture; 51 | 52 | @end 53 | 54 | 55 | -------------------------------------------------------------------------------- /NAMapKit/NAMapView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAMapView.m 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAMapView.h" 10 | 11 | const CGFloat NAMapViewDefaultZoomStep = 1.5f; 12 | 13 | @interface NAMapView() 14 | 15 | @property (nonatomic, strong) UIImageView *imageView; 16 | @property (nonatomic, readonly) NSMutableArray *annotations; 17 | @property (nonatomic, assign) BOOL contentSizeObserving; 18 | 19 | - (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer; 20 | - (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer; 21 | 22 | @end 23 | 24 | @implementation NAMapView 25 | 26 | - (void)createImageView 27 | { 28 | _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 29 | [self addSubview:self.imageView]; 30 | } 31 | 32 | - (void)setupMap 33 | { 34 | self.delegate = self; 35 | 36 | UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)]; 37 | UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)]; 38 | 39 | [doubleTap setNumberOfTapsRequired:2]; 40 | 41 | [twoFingerTap setNumberOfTouchesRequired:2]; 42 | 43 | [self addGestureRecognizer:doubleTap]; 44 | [self addGestureRecognizer:twoFingerTap]; 45 | 46 | [self createImageView]; 47 | 48 | _annotations = [NSMutableArray array]; 49 | _zoomStep = NAMapViewDefaultZoomStep; 50 | _doubleTapGesture = doubleTap; 51 | _twoFingerTapGesture = twoFingerTap; 52 | 53 | [self.panGestureRecognizer addTarget:self action:@selector(mapPanGestureHandler:)]; 54 | } 55 | 56 | - (void)awakeFromNib 57 | { 58 | [super awakeFromNib]; 59 | [self setupMap]; 60 | } 61 | 62 | - (id)initWithFrame:(CGRect)frame 63 | { 64 | self = [super initWithFrame:frame]; 65 | if (self) { 66 | [self setupMap]; 67 | } 68 | return self; 69 | } 70 | 71 | - (void)mapPanGestureHandler:(UIPanGestureRecognizer *)panGesture 72 | { 73 | if (panGesture.state == UIGestureRecognizerStateBegan){ 74 | _centerPoint = CGPointZero; 75 | } 76 | } 77 | 78 | - (void)registerObservers 79 | { 80 | if (!self.contentSizeObserving) { 81 | [self addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil]; 82 | _contentSizeObserving = YES; 83 | } 84 | } 85 | 86 | - (void)displayMap:(UIImage *)map 87 | { 88 | self.imageView.frame = CGRectMake(0.0f, 0.0f, map.size.width, map.size.height); 89 | self.imageView.image = map; 90 | CGRect imageFrame = self.imageView.frame; 91 | self.originalSize = CGSizeMake(CGRectGetWidth(imageFrame), CGRectGetHeight(imageFrame)); 92 | self.contentSize = self.originalSize; 93 | } 94 | 95 | - (void)addAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate 96 | { 97 | [annotation addToMapView:self animated:animate]; 98 | [self.annotations addObject:annotation]; 99 | } 100 | 101 | - (void)addAnnotations:(NSArray *)annotations animated:(BOOL)animate 102 | { 103 | for (NAAnnotation *annotation in annotations) { 104 | [self addAnnotation:annotation animated:animate]; 105 | } 106 | } 107 | 108 | - (void)removeAnnotation:(NAAnnotation *)annotation 109 | { 110 | [annotation removeFromMapView]; 111 | [self.annotations removeObject:annotation]; 112 | } 113 | 114 | - (void)centerOnPoint:(CGPoint)point animated:(BOOL)animate 115 | { 116 | CGFloat x = (point.x * self.zoomScale) - (self.frame.size.width / 2.0f); 117 | CGFloat y = (point.y * self.zoomScale) - (self.frame.size.height / 2.0f); 118 | [self setContentOffset:CGPointMake(round(x), round(y)) animated:animate]; 119 | _centerPoint = point; 120 | } 121 | 122 | - (void)updateContentOffsetToCenterPoint:(CGPoint)point animated:(BOOL)animate 123 | { 124 | CGFloat x = point.x - (self.frame.size.width / 2.0f); 125 | CGFloat y = point.y - (self.frame.size.height / 2.0f); 126 | [self setContentOffset:CGPointMake(round(x), round(y)) animated:animate]; 127 | } 128 | 129 | - (CGPoint)zoomRelativePoint:(CGPoint)point 130 | { 131 | BOOL hasContentSize = ABS(self.originalSize.width) > 0 && ABS(self.originalSize.height) > 0; 132 | NSAssert(hasContentSize, @"originalSize dimension is zero, will result in NaN in returned value."); 133 | 134 | CGFloat x = (self.contentSize.width / self.originalSize.width) * point.x; 135 | CGFloat y = (self.contentSize.height / self.originalSize.height) * point.y; 136 | return CGPointMake(round(x), round(y)); 137 | } 138 | 139 | - (void)selectAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate 140 | { 141 | [self centerOnPoint:annotation.point animated:animate]; 142 | } 143 | 144 | - (void)setFrame:(CGRect)frame 145 | { 146 | [super setFrame:frame]; 147 | 148 | BOOL zoomedOut = self.zoomScale == self.minimumZoomScale; 149 | if (!CGPointEqualToPoint(self.centerPoint, CGPointZero) && !zoomedOut) { 150 | [self centerOnPoint:self.centerPoint animated:NO]; 151 | } 152 | 153 | if (!CGRectIsEmpty(frame)) { 154 | [self registerObservers]; 155 | } 156 | } 157 | 158 | #pragma mark - UIScrollViewDelegate 159 | 160 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 161 | { 162 | return self.imageView; 163 | } 164 | 165 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView 166 | { 167 | if ([self.mapViewDelegate respondsToSelector:@selector(mapView:hasChangedZoomLevel:)]) { 168 | [self.mapViewDelegate mapView:self hasChangedZoomLevel:self.zoomLevel]; 169 | } 170 | } 171 | 172 | - (CGFloat)zoomLevel 173 | { 174 | return self.zoomScale / self.maximumZoomScale; 175 | } 176 | 177 | #pragma mark - Tap to Zoom 178 | 179 | - (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer 180 | { 181 | // double tap zooms in, but returns to normal zoom level if it reaches max zoom 182 | if (self.zoomScale >= self.maximumZoomScale) { 183 | [self setZoomScale:self.minimumZoomScale animated:YES]; 184 | } else { 185 | // the location tapped becomes the new center 186 | CGPoint tapCenter = [gestureRecognizer locationInView:self.imageView]; 187 | CGFloat newScale = MIN(self.zoomScale * self.zoomStep, self.maximumZoomScale); 188 | CGRect maxZoomRect = [self rectAroundPoint:tapCenter atZoomScale:newScale]; 189 | [self zoomToRect:maxZoomRect animated:YES]; 190 | } 191 | } 192 | 193 | - (CGRect)rectAroundPoint:(CGPoint)point atZoomScale:(CGFloat)zoomScale 194 | { 195 | // define the shape of the zoom rect 196 | CGSize boundsSize = self.bounds.size; 197 | // modify the size according to the requested zoom level 198 | // for example, if we're zooming in to 0.5 zoom, then this will increase the bounds size by a factor of two 199 | CGSize scaledBoundsSize = CGSizeMake(boundsSize.width / zoomScale, boundsSize.height / zoomScale); 200 | 201 | return CGRectMake(point.x - scaledBoundsSize.width / 2, 202 | point.y - scaledBoundsSize.height / 2, 203 | scaledBoundsSize.width, 204 | scaledBoundsSize.height); 205 | } 206 | 207 | - (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer 208 | { 209 | // two-finger tap zooms out, but returns to normal zoom level if it reaches min zoom 210 | CGFloat newScale = self.zoomScale <= self.minimumZoomScale ? self.maximumZoomScale : self.zoomScale / self.zoomStep; 211 | [self setZoomScale:newScale animated:YES]; 212 | } 213 | 214 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 215 | { 216 | if ([keyPath isEqualToString:@"contentSize"]) { 217 | [self updatePositions]; 218 | } 219 | } 220 | 221 | - (void)updatePositions 222 | { 223 | [self.annotations makeObjectsPerformSelector:@selector(updatePosition)]; 224 | } 225 | 226 | - (void)dealloc 227 | { 228 | if (self.contentSizeObserving) { 229 | [self removeObserver:self forKeyPath:@"contentSize"]; 230 | } 231 | } 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /NAMapKit/NAMapViewDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAMapViewDelegate.h 3 | // NAMapKit 4 | // 5 | // Created by Daniel Doubrovkine on 3/10/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | @class NAMapView; 10 | @class NAAnnotation; 11 | 12 | /** 13 | * An NAMapView delegate. 14 | */ 15 | @protocol NAMapViewDelegate 16 | @optional 17 | /** 18 | * An annotation has been tapped. 19 | * 20 | * @param mapView Map view on which the annotation has been tapped. 21 | * @param annotation The annotation that has been tapped. 22 | */ 23 | - (void)mapView:(NAMapView *)mapView tappedOnAnnotation:(NAAnnotation *)annotation; 24 | 25 | /** 26 | * Zoom level has changed. 27 | * 28 | * @param mapView The map view on which the zoom level has changed. 29 | * @param level The new zoom level. 30 | */ 31 | - (void)mapView:(NAMapView *)mapView hasChangedZoomLevel:(CGFloat)level; 32 | @end 33 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotation.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotation.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAAnnotation.h" 10 | 11 | typedef enum { 12 | NAPinColorRed, 13 | NAPinColorGreen, 14 | NAPinColorPurple 15 | } NAPinColor; 16 | 17 | /** 18 | * An annotation that looks like a pin. 19 | */ 20 | @interface NAPinAnnotation : NAAnnotation 21 | 22 | /// Pin color. 23 | @property (nonatomic, assign) NAPinColor color; 24 | /// Pin title. 25 | @property (nonatomic, copy) NSString *title; 26 | /// Pin subtitle. 27 | @property (nonatomic, copy) NSString *subtitle; 28 | /// Callout view that appears when the pin is tapped. 29 | @property (nonatomic, strong) UIButton *rightCalloutAccessoryView; 30 | 31 | /// Create a new pin at a point on a map. 32 | - (id)initWithPoint:(CGPoint)point; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotation.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotation.m 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotation.h" 10 | #import "NAPinAnnotationView.h" 11 | 12 | const CGFloat NAMapViewPinAnimationDuration = 0.5f; 13 | 14 | @interface NAPinAnnotation () 15 | @property (nonatomic, readonly, weak) NAPinAnnotationView *view; 16 | @end 17 | 18 | @implementation NAPinAnnotation 19 | 20 | - (id)initWithPoint:(CGPoint)point 21 | { 22 | self = [super initWithPoint:point]; 23 | if (self) { 24 | self.color = NAPinColorRed; 25 | self.title = nil; 26 | self.subtitle = nil; 27 | self.rightCalloutAccessoryView = nil; 28 | } 29 | return self; 30 | } 31 | 32 | - (UIView *)createViewOnMapView:(NAMapView *)mapView 33 | { 34 | return [[NAPinAnnotationView alloc] initWithAnnotation:self onMapView:mapView]; 35 | } 36 | 37 | - (void)addToMapView:(NAMapView *)mapView animated:(BOOL)animate 38 | { 39 | [super addToMapView:mapView animated:animate]; 40 | 41 | if (animate) { 42 | self.view.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, 0.0f, -self.view.center.y); 43 | } 44 | 45 | [mapView addSubview:self.view]; 46 | 47 | if (animate) { 48 | self.view.animating = YES; 49 | [UIView animateWithDuration:NAMapViewPinAnimationDuration animations:^{ 50 | self.view.transform = CGAffineTransformIdentity; 51 | } completion:^ (BOOL finished) { 52 | self.view.animating = NO; 53 | }]; 54 | } 55 | } 56 | 57 | - (void)updatePosition 58 | { 59 | [self.view updatePosition]; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotationCallOutView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationCallOutView.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 23/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAPinAnnotation.h" 11 | #import "NAMapView.h" 12 | 13 | /** 14 | * A callout view displayed wiht NAPinAnnotation. 15 | */ 16 | @interface NAPinAnnotationCallOutView : UIView 17 | 18 | /// Create a new callout view on a map. 19 | - (id)initOnMapView:(NAMapView *)mapView; 20 | 21 | /// Recalculate position on map according to zoom level. 22 | - (void)updatePosition; 23 | 24 | /// Pin annotation. 25 | @property(readwrite, nonatomic, strong) NAPinAnnotation *annotation; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotationCallOutView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationCallOutView.m 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 23/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotationCallOutView.h" 10 | 11 | const CGFloat NAMapViewAnnotationCalloutTitleStandaloneLabelHeight = 22.0f; 12 | const CGFloat NAMapViewAnnotationCalloutTitleStandaloneFontSize = 18.0f; 13 | const CGFloat NAMapViewAnnotationCalloutTitleStandaloneTopOffset = 12.0f; 14 | const CGFloat NAMapViewAnnotationCalloutTitleTopOffset = 4.0f; 15 | const CGFloat NAMapViewAnnotationCalloutTitleLabelHeight = 20.0f; 16 | const CGFloat NAMapViewAnnotationCalloutTitleFontSize = 17.0f; 17 | const CGFloat NAMapViewAnnotationCalloutSubtitleTopOffset = 0.0f + NAMapViewAnnotationCalloutTitleLabelHeight; 18 | const CGFloat NAMapViewAnnotationCalloutSubtitleFontSize = 11.0f; 19 | const CGFloat NAMapViewAnnotationCalloutSubtitleLabelHeight = 25.0f; 20 | const CGFloat NAMapViewAnnotationCalloutRightAccessoryLeftOffset = 2.0f; 21 | const CGFloat NAMapViewAnnotationCalloutRightAccessoryTopOffset = 9.0f; 22 | const CGFloat NAMapViewAnnotationCalloutAnchorYOffset = 26.0f; 23 | static NSString *NAMapViewAnnotationCalloutImageLeft = @"/callout_left.png"; 24 | static NSString *NAMapViewAnnotationCalloutImageRight = @"/callout_right.png"; 25 | static NSString *NAMapViewAnnotationCalloutImageAnchor = @"/callout_anchor.png"; 26 | static NSString *NAMapViewAnnotationCalloutImageBG = @"/callout_bg.png"; 27 | 28 | @interface NAPinAnnotationCallOutView() 29 | 30 | @property (nonatomic, strong) UIImageView *calloutLeftCapView; 31 | @property (nonatomic, strong) UIImageView *calloutRightCapView; 32 | @property (nonatomic, strong) UIImageView *calloutAnchorView; 33 | @property (nonatomic, strong) UIImageView *calloutLeftCenterView; 34 | @property (nonatomic, strong) UIImageView *calloutRightCenterView; 35 | @property (nonatomic, strong) UILabel *subtitleLabel; 36 | @property (nonatomic, strong) UILabel *titleLabel; 37 | @property (nonatomic, assign) CGPoint point; 38 | @property (nonatomic, assign) CGPoint position; 39 | @property (nonatomic, weak) NAMapView *mapView; 40 | 41 | - (void)positionView:(UIView *)view posX:(float)x; 42 | - (void)positionView:(UIView *)view posX:(float)x width:(float)width; 43 | 44 | @end 45 | 46 | @implementation NAPinAnnotationCallOutView 47 | 48 | - (id)initOnMapView:(NAMapView *)mapView 49 | { 50 | self = [super init]; 51 | if (self) { 52 | UIImage *calloutBG = [[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:NAMapViewAnnotationCalloutImageBG]] stretchableImageWithLeftCapWidth:0 topCapHeight:0]; 53 | self.calloutLeftCapView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:NAMapViewAnnotationCalloutImageLeft]]]; 54 | self.calloutRightCapView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:NAMapViewAnnotationCalloutImageRight]]]; 55 | self.calloutAnchorView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:NAMapViewAnnotationCalloutImageAnchor]]]; 56 | self.calloutLeftCenterView = [[UIImageView alloc] initWithImage:calloutBG]; 57 | self.calloutRightCenterView = [[UIImageView alloc] initWithImage:calloutBG]; 58 | self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 59 | self.subtitleLabel.textColor = [UIColor whiteColor]; 60 | self.subtitleLabel.backgroundColor = [UIColor clearColor]; 61 | self.subtitleLabel.font = [UIFont systemFontOfSize:NAMapViewAnnotationCalloutSubtitleFontSize]; 62 | self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 63 | self.titleLabel.backgroundColor = [UIColor clearColor]; 64 | self.titleLabel.textColor = [UIColor whiteColor]; 65 | self.mapView = mapView; 66 | self.hidden = YES; 67 | } 68 | return self; 69 | } 70 | 71 | - (void)setAnnotation:(NAPinAnnotation *)annotation 72 | { 73 | 74 | // --- RESET --- 75 | 76 | self.titleLabel.text = @""; 77 | self.subtitleLabel.text = @""; 78 | self.point = CGPointZero; 79 | 80 | for (UIView *view in self.subviews) { 81 | [view removeFromSuperview]; 82 | } 83 | 84 | self.position = annotation.point; 85 | 86 | CGFloat leftCapWidth = self.calloutLeftCapView.image.size.width; 87 | CGFloat rightCapWidth = self.calloutRightCapView.image.size.width; 88 | CGFloat anchorWidth = self.calloutAnchorView.image.size.width; 89 | CGFloat anchorHeight = self.calloutAnchorView.image.size.height; 90 | CGFloat maxWidth = self.mapView.frame.size.width; 91 | 92 | // --- FRAME --- 93 | 94 | CGFloat middleWidth = anchorWidth; 95 | 96 | #pragma clang diagnostic push 97 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" 98 | if (annotation.subtitle) { 99 | CGSize subtitleSize = [annotation.subtitle sizeWithFont:[UIFont boldSystemFontOfSize:NAMapViewAnnotationCalloutSubtitleFontSize] constrainedToSize:CGSizeMake(maxWidth, NAMapViewAnnotationCalloutSubtitleLabelHeight) lineBreakMode:NSLineBreakByTruncatingTail]; 100 | 101 | middleWidth = MAX(subtitleSize.width, middleWidth); 102 | 103 | CGSize titleSize = [annotation.title sizeWithFont:[UIFont boldSystemFontOfSize:NAMapViewAnnotationCalloutTitleFontSize] constrainedToSize:CGSizeMake(maxWidth, NAMapViewAnnotationCalloutTitleLabelHeight) lineBreakMode:NSLineBreakByTruncatingTail]; 104 | 105 | middleWidth = MAX(titleSize.width, middleWidth); 106 | } 107 | else{ 108 | CGSize titleSize = [annotation.title sizeWithFont:[UIFont boldSystemFontOfSize:NAMapViewAnnotationCalloutTitleStandaloneFontSize] constrainedToSize:CGSizeMake(maxWidth, NAMapViewAnnotationCalloutTitleStandaloneLabelHeight) lineBreakMode:NSLineBreakByTruncatingTail]; 109 | 110 | middleWidth = MAX(titleSize.width, middleWidth); 111 | } 112 | #pragma clang diagnostic pop 113 | 114 | if (annotation.rightCalloutAccessoryView) { 115 | middleWidth += annotation.rightCalloutAccessoryView.frame.size.width + NAMapViewAnnotationCalloutRightAccessoryLeftOffset; 116 | } 117 | 118 | middleWidth = MIN(maxWidth, middleWidth); 119 | 120 | CGFloat totalWidth = middleWidth + leftCapWidth + rightCapWidth; 121 | 122 | self.point = annotation.point; 123 | 124 | self.frame = CGRectMake(0.0f, 0.0f, totalWidth, anchorHeight); 125 | [self updatePosition]; 126 | 127 | // --- IMAGEVIEWS --- 128 | 129 | CGFloat centreOffsetWidth = (middleWidth - anchorWidth) / 2.0f; 130 | 131 | [self positionView:self.calloutLeftCapView posX:0.0f]; 132 | [self positionView:self.calloutRightCapView posX:(totalWidth - rightCapWidth)]; 133 | [self positionView:self.calloutAnchorView posX:(leftCapWidth + centreOffsetWidth)]; 134 | 135 | [self addSubview:self.calloutLeftCapView]; 136 | [self addSubview:self.calloutRightCapView]; 137 | [self addSubview:self.calloutAnchorView]; 138 | 139 | if (middleWidth > anchorWidth) { 140 | [self positionView:self.calloutLeftCenterView posX:leftCapWidth width:centreOffsetWidth]; 141 | [self positionView:self.calloutRightCenterView posX:(leftCapWidth + middleWidth - centreOffsetWidth) width:centreOffsetWidth]; 142 | 143 | [self addSubview:self.calloutLeftCenterView]; 144 | [self addSubview:self.calloutRightCenterView]; 145 | } 146 | 147 | CGFloat labelWidth = middleWidth; 148 | 149 | // --- RIGHT ACCESSORY VIEW --- 150 | 151 | if (annotation.rightCalloutAccessoryView) { 152 | CGFloat accesoryWidth = annotation.rightCalloutAccessoryView.frame.size.width; 153 | CGFloat x = middleWidth - accesoryWidth + leftCapWidth + NAMapViewAnnotationCalloutRightAccessoryLeftOffset; 154 | 155 | CGRect frame = annotation.rightCalloutAccessoryView.frame; 156 | frame.origin.x = x; 157 | frame.origin.y = NAMapViewAnnotationCalloutRightAccessoryTopOffset; 158 | annotation.rightCalloutAccessoryView.frame = frame; 159 | 160 | [self addSubview:annotation.rightCalloutAccessoryView]; 161 | labelWidth -= accesoryWidth; 162 | } 163 | 164 | 165 | // --- LABELS --- 166 | 167 | CGFloat currentTitleTopOffset = NAMapViewAnnotationCalloutTitleStandaloneTopOffset; 168 | CGFloat currentTitleLabelHeight = NAMapViewAnnotationCalloutTitleStandaloneLabelHeight; 169 | CGFloat currentTitleFontSize = NAMapViewAnnotationCalloutTitleStandaloneFontSize; 170 | 171 | 172 | // --- SUBTITLE --- 173 | 174 | if (annotation.subtitle) { 175 | currentTitleTopOffset = NAMapViewAnnotationCalloutTitleTopOffset; 176 | currentTitleLabelHeight = NAMapViewAnnotationCalloutTitleLabelHeight; 177 | currentTitleFontSize = NAMapViewAnnotationCalloutTitleFontSize; 178 | self.subtitleLabel.text = annotation.subtitle; 179 | self.subtitleLabel.frame = CGRectMake(leftCapWidth, NAMapViewAnnotationCalloutSubtitleTopOffset, labelWidth, NAMapViewAnnotationCalloutSubtitleLabelHeight); 180 | [self addSubview:self.subtitleLabel]; 181 | } 182 | 183 | // --- TITLE --- 184 | 185 | self.titleLabel.text = annotation.title; 186 | self.titleLabel.font = [UIFont boldSystemFontOfSize:currentTitleFontSize]; 187 | self.titleLabel.frame = CGRectMake(leftCapWidth, currentTitleTopOffset, labelWidth, currentTitleLabelHeight); 188 | 189 | [self addSubview:self.titleLabel]; 190 | 191 | } 192 | 193 | #pragma - Private helpers 194 | 195 | - (void)updatePosition 196 | { 197 | CGPoint point = [self.mapView zoomRelativePoint:self.position]; 198 | CGFloat xPos = point.x - (self.frame.size.width / 2.0f); 199 | CGFloat yPos = point.y - (self.frame.size.height) - NAMapViewAnnotationCalloutAnchorYOffset; 200 | self.frame = CGRectMake(floor(xPos), yPos, self.frame.size.width, self.frame.size.height); 201 | } 202 | 203 | - (void)positionView:(UIView *)view posX:(float)x width:(float)width 204 | { 205 | CGRect frame = view.frame; 206 | frame.origin.x = x; 207 | frame.size.width = width; 208 | view.frame = frame; 209 | } 210 | 211 | - (void)positionView:(UIView *)view posX:(float)x 212 | { 213 | [self positionView:view posX:x width:view.frame.size.width]; 214 | } 215 | 216 | @end 217 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotationMapView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationMapView.h 3 | // NAMapKit 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAMapView.h" 10 | #import "NAPinAnnotation.h" 11 | #import "NAPinAnnotationView.h" 12 | #import "NAPinAnnotationCallOutView.h" 13 | 14 | /** 15 | * A map view with pin annotations. 16 | */ 17 | @interface NAPinAnnotationMapView : NAMapView 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotationMapView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationMapView.m 3 | // NAMapKit 4 | // 5 | // Created by Daniel Doubrovkine on 3/7/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotationMapView.h" 10 | 11 | const CGFloat NAMapViewAnnotationCalloutAnimationDuration = 0.1f; 12 | 13 | @interface NAPinAnnotationMapView() 14 | 15 | @property (nonatomic, strong) NAPinAnnotationCallOutView *calloutView; 16 | 17 | - (IBAction)showCallOut:(id)sender; 18 | - (void)hideCallOut; 19 | @end 20 | 21 | @implementation NAPinAnnotationMapView 22 | 23 | - (void)setupMap 24 | { 25 | [super setupMap]; 26 | 27 | _calloutView = [[NAPinAnnotationCallOutView alloc] initOnMapView:self]; 28 | [self addSubview:self.calloutView]; 29 | } 30 | 31 | - (void)addAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate 32 | { 33 | [super addAnnotation:annotation animated:animate]; 34 | if ([annotation.view isKindOfClass:NAPinAnnotationView.class]) { 35 | NAPinAnnotationView *annotationView = (NAPinAnnotationView *) annotation.view; 36 | [annotationView addTarget:self action:@selector(showCallOut:) forControlEvents:UIControlEventTouchDown]; 37 | } 38 | [self bringSubviewToFront:self.calloutView]; 39 | } 40 | 41 | - (void)selectAnnotation:(NAAnnotation *)annotation animated:(BOOL)animate 42 | { 43 | [self hideCallOut]; 44 | if([annotation isKindOfClass:NAPinAnnotation.class]) { 45 | [self showCalloutForAnnotation:(NAPinAnnotation *)annotation animated:animate]; 46 | } 47 | } 48 | 49 | - (void)removeAnnotation:(NAAnnotation *)annotation 50 | { 51 | [self hideCallOut]; 52 | [super removeAnnotation:annotation]; 53 | } 54 | 55 | - (IBAction)showCallOut:(id)sender 56 | { 57 | if([sender isKindOfClass:[NAPinAnnotationView class]]) { 58 | NAPinAnnotationView *annontationView = (NAPinAnnotationView *)sender; 59 | 60 | if ([self.mapViewDelegate respondsToSelector:@selector(mapView:tappedOnAnnotation:)]) { 61 | [self.mapViewDelegate mapView:self tappedOnAnnotation:annontationView.annotation]; 62 | } 63 | 64 | [self showCalloutForAnnotation:annontationView.annotation animated:YES]; 65 | } 66 | } 67 | 68 | - (void)showCalloutForAnnotation:(NAPinAnnotation *)annotation animated:(BOOL)animated 69 | { 70 | [self hideCallOut]; 71 | 72 | self.calloutView.annotation = annotation; 73 | 74 | [self centerOnPoint:annotation.point animated:animated]; 75 | 76 | CGFloat animationDuration = animated ? NAMapViewAnnotationCalloutAnimationDuration : 0.0f; 77 | 78 | self.calloutView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4f, 0.4f); 79 | self.calloutView.hidden = NO; 80 | 81 | __weak typeof(self) weakSelf = self; 82 | [UIView animateWithDuration:animationDuration animations:^{ 83 | weakSelf.calloutView.transform = CGAffineTransformIdentity; 84 | }]; 85 | } 86 | 87 | - (void)hideCallOut 88 | { 89 | self.calloutView.hidden = YES; 90 | } 91 | 92 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 93 | { 94 | if (!self.dragging) { 95 | [self hideCallOut]; 96 | } 97 | 98 | [super touchesEnded:touches withEvent:event]; 99 | } 100 | 101 | - (void)updatePositions 102 | { 103 | [self.calloutView updatePosition]; 104 | [super updatePositions]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationView.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NAPinAnnotation.h" 11 | #import "NAMapView.h" 12 | 13 | /** 14 | * A pin annotation view the behaves like a button. 15 | */ 16 | @interface NAPinAnnotationView : UIButton 17 | 18 | /// Associated NAPinAnnotation. 19 | @property (readwrite, nonatomic, weak) NAPinAnnotation *annotation; 20 | /// Animate the pin. 21 | @property (readwrite, nonatomic, assign) BOOL animating; 22 | 23 | /// Create a view for a pin annotation on a map. 24 | - (id)initWithAnnotation:(NAPinAnnotation *)annotation onMapView:(NAMapView *)mapView; 25 | /// Update the pin position when the map is zoomed in or zoomed out. 26 | - (void)updatePosition; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /NAMapKit/NAPinAnnotationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NAPinAnnotationView.h 3 | // NAMapKit 4 | // 5 | // Created by Neil Ang on 21/07/10. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAPinAnnotationView.h" 10 | 11 | const CGFloat NAMapViewAnnotationPinWidth = 32.0f; 12 | const CGFloat NAMapViewAnnotationPinHeight = 39.0f; 13 | const CGFloat NAMapViewAnnotationPinPointX = 8.0f; 14 | const CGFloat NAMapViewAnnotationPinPointY = 35.0f; 15 | 16 | @interface NAPinAnnotationView() 17 | @property (nonatomic, weak) NAMapView *mapView; 18 | @end 19 | 20 | @implementation NAPinAnnotationView 21 | 22 | - (id)initWithAnnotation:(NAPinAnnotation *)annotation onMapView:(NAMapView *)mapView 23 | { 24 | self = [super initWithFrame:CGRectZero]; 25 | if (self) { 26 | self.mapView = mapView; 27 | self.annotation = annotation; 28 | self.animating = NO; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)setAnimating:(BOOL)animating 34 | { 35 | _animating = animating; 36 | 37 | NSString *pinImageName; 38 | switch (self.annotation.color) { 39 | case NAPinColorGreen: 40 | pinImageName = @"pin_green"; 41 | break; 42 | case NAPinColorPurple: 43 | pinImageName = @"pin_purple"; 44 | break; 45 | case NAPinColorRed: 46 | pinImageName = @"pin_red"; 47 | break; 48 | } 49 | 50 | if (animating) { 51 | pinImageName = [NSString stringWithFormat:@"%@_floating", pinImageName]; 52 | } 53 | 54 | UIImage *pinImage = [UIImage imageWithContentsOfFile:[[NSBundle bundleForClass:NAPinAnnotationView.class] pathForResource:pinImageName ofType:@"png"]]; 55 | 56 | [self setImage:pinImage forState:UIControlStateNormal]; 57 | } 58 | 59 | - (void)updatePosition 60 | { 61 | CGPoint point = [self.mapView zoomRelativePoint:self.annotation.point]; 62 | point.x = point.x - NAMapViewAnnotationPinPointX; 63 | point.y = point.y - NAMapViewAnnotationPinPointY; 64 | self.frame = CGRectMake(point.x, point.y, NAMapViewAnnotationPinWidth, NAMapViewAnnotationPinHeight); 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /NAMapKit/NATiledImageMapView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NATiledImageMapView.h 3 | // NAMapKit 4 | // 5 | // Created by Daniel Doubrovkine on 3/10/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NAMapView.h" 10 | #import 11 | 12 | /** 13 | * A tiled image map. 14 | */ 15 | @interface NATiledImageMapView : NAMapView 16 | 17 | - (id)initWithFrame:(CGRect)frame tiledImageDataSource:(NSObject *)dataSource; 18 | 19 | /// Zoom the map view to fit the current display. 20 | - (void)zoomToFit:(BOOL)animate; 21 | 22 | /// Display tile borders, usually for debugging purposes. 23 | @property (readwrite, nonatomic, assign) BOOL displayTileBorders; 24 | 25 | /// Set a background image, displayed while tiles are being downloaded. 26 | @property (readwrite, nonatomic) NSURL *backgroundImageURL; 27 | 28 | /// Set a background image, displayed while tiles are being downloaded. 29 | @property (readwrite, nonatomic) UIImage *backgroundImage; 30 | 31 | /// The current tile zoom level based on the DeepZoom algorithm. 32 | @property (readonly, nonatomic, assign) NSInteger tileZoomLevel; 33 | 34 | @end -------------------------------------------------------------------------------- /NAMapKit/NATiledImageMapView.m: -------------------------------------------------------------------------------- 1 | // 2 | // NATiledImageMapView.m 3 | // NAMapKit 4 | // 5 | // Created by Daniel Doubrovkine on 3/10/14. 6 | // Copyright (c) 2010-14 neilang.com. All rights reserved. 7 | // 8 | 9 | #import "NATiledImageMapView.h" 10 | #import 11 | #import 12 | #import 13 | 14 | @interface NATiledImageMapView () 15 | @property (nonatomic, weak, readonly) NSObject *dataSource; 16 | @property (nonatomic, readonly) ARTiledImageView *imageView; 17 | @property (nonatomic, readonly) UIImageView *backgroundImageView; 18 | @end 19 | 20 | @implementation NATiledImageMapView 21 | 22 | - (id)initWithFrame:(CGRect)frame tiledImageDataSource:(NSObject *)dataSource 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) { 26 | _dataSource = dataSource; 27 | [self setupMap]; 28 | } 29 | return self; 30 | } 31 | 32 | - (void)createImageView 33 | { 34 | if (self.dataSource) { 35 | _imageView = [[ARTiledImageView alloc] initWithDataSource:self.dataSource]; 36 | self.imageView.displayTileBorders = self.displayTileBorders; 37 | [self addSubview:self.imageView]; 38 | } 39 | } 40 | 41 | - (void)setupMap 42 | { 43 | if (self.dataSource) { 44 | [super setupMap]; 45 | [self setMaxMinZoomScalesForCurrentBounds]; 46 | } 47 | } 48 | 49 | - (void)setDisplayTileBorders:(BOOL)displayTileBorders 50 | { 51 | self.imageView.displayTileBorders = displayTileBorders; 52 | _displayTileBorders = displayTileBorders; 53 | } 54 | 55 | - (void)setMaxMinZoomScalesForCurrentBounds 56 | { 57 | CGSize boundsSize = self.bounds.size; 58 | CGSize imageSize = [self.dataSource imageSizeForImageView:nil]; 59 | 60 | // calculate min/max zoomscale 61 | CGFloat xScale = boundsSize.width / imageSize.width; // the scale needed to perfectly fit the image width-wise 62 | CGFloat yScale = boundsSize.height / imageSize.height; // the scale needed to perfectly fit the image height-wise 63 | CGFloat minScale = MAX(xScale, yScale); // use minimum of these to allow the image to become fully visible 64 | 65 | CGFloat maxScale = 1.0; 66 | 67 | // don't let minScale exceed maxScale 68 | // if the image is smaller than the screen, we don't want to force it to be zoomed 69 | if (minScale > maxScale) { 70 | minScale = maxScale; 71 | } 72 | 73 | self.maximumZoomScale = maxScale * 0.6; 74 | self.minimumZoomScale = minScale; 75 | 76 | self.originalSize = imageSize; 77 | self.contentSize = imageSize; 78 | } 79 | 80 | - (void)zoomToFit:(BOOL)animate 81 | { 82 | [self setZoomScale:self.minimumZoomScale animated:animate]; 83 | } 84 | 85 | - (void)scrollViewDidZoom:(UIScrollView *)scrollView 86 | { 87 | self.backgroundImageView.frame = self.imageView.frame; 88 | [super scrollViewDidZoom:scrollView]; 89 | NSInteger newZoomLevel = self.imageView.currentZoomLevel; 90 | if (newZoomLevel != self.tileZoomLevel) { 91 | // TODO: delegate that zoom level has changed 92 | _tileZoomLevel = self.imageView.currentZoomLevel; 93 | } 94 | } 95 | 96 | - (void)setBackgroundImageURL:(NSURL *)backgroundImageURL 97 | { 98 | UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.imageView.frame]; 99 | [self insertSubview:backgroundImageView belowSubview:self.imageView]; 100 | [backgroundImageView setImageWithURL:backgroundImageURL]; 101 | _backgroundImageView = backgroundImageView; 102 | _backgroundImageURL = backgroundImageURL; 103 | } 104 | 105 | - (void)setBackgroundImage:(UIImage *)backgroundImage 106 | { 107 | UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:self.imageView.frame]; 108 | [self insertSubview:backgroundImageView belowSubview:self.imageView]; 109 | backgroundImageView.image = backgroundImage; 110 | _backgroundImageView = backgroundImageView; 111 | _backgroundImage = backgroundImage; 112 | } 113 | 114 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 115 | { 116 | return self.imageView; 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /NAMapKit/callout_anchor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_anchor.png -------------------------------------------------------------------------------- /NAMapKit/callout_anchor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_anchor@2x.png -------------------------------------------------------------------------------- /NAMapKit/callout_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_bg.png -------------------------------------------------------------------------------- /NAMapKit/callout_bg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_bg@2x.png -------------------------------------------------------------------------------- /NAMapKit/callout_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_left.png -------------------------------------------------------------------------------- /NAMapKit/callout_left@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_left@2x.png -------------------------------------------------------------------------------- /NAMapKit/callout_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_right.png -------------------------------------------------------------------------------- /NAMapKit/callout_right@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/callout_right@2x.png -------------------------------------------------------------------------------- /NAMapKit/pin_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_green.png -------------------------------------------------------------------------------- /NAMapKit/pin_green@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_green@2x.png -------------------------------------------------------------------------------- /NAMapKit/pin_green_floating.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_green_floating.png -------------------------------------------------------------------------------- /NAMapKit/pin_green_floating@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_green_floating@2x.png -------------------------------------------------------------------------------- /NAMapKit/pin_purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_purple.png -------------------------------------------------------------------------------- /NAMapKit/pin_purple@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_purple@2x.png -------------------------------------------------------------------------------- /NAMapKit/pin_purple_floating.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_purple_floating.png -------------------------------------------------------------------------------- /NAMapKit/pin_purple_floating@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_purple_floating@2x.png -------------------------------------------------------------------------------- /NAMapKit/pin_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_red.png -------------------------------------------------------------------------------- /NAMapKit/pin_red@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_red@2x.png -------------------------------------------------------------------------------- /NAMapKit/pin_red_floating.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_red_floating.png -------------------------------------------------------------------------------- /NAMapKit/pin_red_floating@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilang/NAMapKit/b3b7987076373cc1d71be0c003bf495dc4f90420/NAMapKit/pin_red_floating@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NAMapKit 2 | ======== 3 | 4 | [![Build Status](https://travis-ci.org/neilang/NAMapKit.svg)](https://travis-ci.org/neilang/NAMapKit) 5 | 6 | Lets you drop pins or custom annotations onto a standard `UIImage` or a tiled `NATiledImageView`. Includes callouts, multi-colored pins, animation, zoom and gestures support. 7 | 8 | ![Animated Demo](Demo/Screenshots/namapkit.gif) 9 | 10 | Get started by running `pod try NAMapKit` in your terminal. 11 | 12 | Usage 13 | ----- 14 | 15 | #### Default Annotations 16 | 17 | Create a `NAMapView` in a view controller. 18 | 19 | ``` objc 20 | NAMapView *mapView = [[NAMapView alloc] initWithFrame:self.view.bounds]; 21 | 22 | mapView.backgroundColor = [UIColor colorWithRed:0.000f green:0.475f blue:0.761f alpha:1.000f]; 23 | mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 24 | 25 | mapView.minimumZoomScale = 0.5f; 26 | mapView.maximumZoomScale = 1.5f; 27 | 28 | [mapView displayMap:[UIImage imageNamed:@"australia"]]; 29 | 30 | [self.view addSubview:mapView]; 31 | ``` 32 | 33 | Add `NADotAnnotation` annotations. 34 | 35 | ``` 36 | NADotAnnotation *dot = [NADotAnnotation annotationWithPoint:CGPointMake(543.0f, 489.0f)]; 37 | [mapView addAnnotation:dot animated:NO]; 38 | ``` 39 | 40 | #### Custom Annotations 41 | 42 | The implementation of `NADotAnnotation` places a red semi-transparent dot on the map. For custom annotations, subclass [NAAnnotation](NAMapKit/NAAnnotation.h) and implement `createViewOnMapView` that returns a custom annotation view. You could also implement a custom animation to drop an annotation onto the map by implementing `addToMapView`, or center the annotation depending on your custom logic by overriding `updatePosition`. 43 | 44 | You can find a complete custom annotation example of multi-colored pins in [NAPinAnnotation.h](NAMapKit/NAPinAnnotation.h)/[.m](NAMapKit/NAPinAnnotation.m) and a popup menu demo in [NAPinAnnotationsPopupMenuDemoViewController.h](Demo/Demo/NAPinAnnotationsPopupMenuDemoViewController.h)/[.m](Demo/Demo/NAPinAnnotationsPopupMenuDemoViewController.m). 45 | 46 | ![circular pop-up animated demo](Demo/Screenshots/namapkit2.gif) 47 | 48 | #### Delegates 49 | 50 | You can capture finger taps and zoom changes by registering a `mapViewDelegate` with the map. The delegate must implement the [NAMapViewDelegate](NAMapKit/NAMapViewDelegate.h) protocol. 51 | 52 | ```objc 53 | @implementation DemoViewController 54 | 55 | - (void)viewDidLoad 56 | { 57 | // Register the view controller as the map's delegate 58 | self.mapView.mapViewDelegate = self; 59 | } 60 | 61 | - (void)mapView:(NAMapView *)mapView tappedOnAnnotation:(NAPinAnnotation *)annotation 62 | { 63 | // Invoked when a user taps an annotation 64 | } 65 | 66 | - (void)mapView:(NAMapView *)mapView hasChangedZoomLevel:(CGFloat)level 67 | { 68 | // Invoked when the map zoom level changes 69 | } 70 | 71 | @end 72 | ``` 73 | 74 | See [NAAnnotationDemoViewController.m](Demo/Demo/NAAnnotationDemoViewController.m) for a complete example. 75 | 76 | #### Tiled Maps 77 | 78 | NAMapKit comes with [NATiledImageMapView](NAMapKit/NATiledImageMapView.h), which supports tiled maps. A typical organization for deep zoom map tiles consists of a folder for each zoom level and individual JPG files for each tile. You can see an example of such files [here](Demo/Maps/Armory2014/tiles). NAMapKit uses [ARTiledImageView](https://github.com/dblock/ARTiledImageView). You can generate tiles using [dzt](https://github.com/dblock/dzt) or any other tool listed with the [OpenSeadragon](http://openseadragon.github.io/examples/creating-zooming-images) project. 79 | 80 | For a complete example of a tiled map, see [NATiledImageDemoViewController.m](Demo/Demo/NATiledImageDemoViewController.m). 81 | 82 | ### Custom Gestures 83 | 84 | NAMapKit exposes it's two double tap gestures so that you can use `delaysTouchesBegan` to prioritise the double tap over a map point tap. Or to just replace them entirely yourself. 85 | 86 | Notes 87 | ----- 88 | 89 | If you are using Interface Builder, you can add a UIScrollView to your XIB and change the class to `NAMapView` to use the framework. 90 | 91 | License 92 | ------- 93 | 94 | This project is licensed under the [MIT license](LICENSE). 95 | 96 | Attribution 97 | ----------- 98 | 99 | When using this code please include the following attribution: 100 | 101 | **Includes NAMapKit code developed by [Neil Ang](http://neilang.com/), [Tony Arnold](http://thecocoabots.com/), [Daniel Doubrovkine](http://code.dblock.org/) and [Orta Therox](http://orta.github.io/).** 102 | --------------------------------------------------------------------------------