├── .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 |
13 |
14 | IBProxyObject
15 | IBUIView
16 | IBUIScrollView
17 |
18 |
19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
20 |
21 |
25 |
26 |
30 |
34 |
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 | [](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 | 
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 | 
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 |
--------------------------------------------------------------------------------