├── .gitignore ├── LICENSE ├── NKWatchChart.podspec ├── NKWatchChartDemo.xcodeproj └── project.pbxproj ├── NKWatchChartDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── README.md ├── WatchChart Extension ├── Assets.xcassets │ └── README__ignoredByTemplate__ ├── ChartInterfaceController.h ├── ChartInterfaceController.m ├── ChartTableRowController.h ├── ChartTableRowController.m ├── ExtensionDelegate.h ├── ExtensionDelegate.m ├── Info.plist ├── InterfaceController.h ├── InterfaceController.m └── NKWatchChart │ ├── NKBarChart.h │ ├── NKBarChart.m │ ├── NKCircleChart.h │ ├── NKCircleChart.m │ ├── NKColor.h │ ├── NKColor.m │ ├── NKLineChart.h │ ├── NKLineChart.m │ ├── NKLineChartData.h │ ├── NKLineChartData.m │ ├── NKLineChartDataItem.h │ ├── NKLineChartDataItem.m │ ├── NKPieChart.h │ ├── NKPieChart.m │ ├── NKPieChartDataItem.h │ ├── NKPieChartDataItem.m │ ├── NKRadarChart.h │ ├── NKRadarChart.m │ ├── NKRadarChartDataItem.h │ ├── NKRadarChartDataItem.m │ └── NKWatchChart.h └── WatchChart ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj └── Interface.storyboard └── Info.plist /.gitignore: -------------------------------------------------------------------------------- 1 | #Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.moved-aside 14 | DerivedData 15 | .idea/ 16 | *.hmap 17 | *.xccheckout 18 | 19 | #CocoaPods 20 | Pods 21 | Podfile.lock 22 | *.xcworkspace -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Peng Guo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /NKWatchChart.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = "NKWatchChart" 5 | s.version = "0.1.0" 6 | s.summary = "A chart library for Apple Watch based on PNChart." 7 | 8 | s.description = <<-DESC 9 | A chart library for Apple Watch based on PNChart. We support line, bar, pie, circle and radar charts. 10 | 11 | DESC 12 | 13 | s.homepage = "https://github.com/NilStack/NKWatchChart" 14 | s.screenshots = "https://db.tt/d7pJD84m" 15 | s.license = "MIT" 16 | s.author = { "Peng Guo" => "guoleii@gmail.com" } 17 | s.social_media_url = "http://twitter.com/NilStack" 18 | s.watchos.deployment_target = "2.0" 19 | s.source = { :git => "https://github.com/NilStack/NKWatchChart.git", :tag => s.version.to_s } 20 | s.watchos.source_files = "WatchChart Extension/NKWatchChart/*.{h,m}" 21 | s.frameworks = "UIKit", "WatchKit" 22 | s.requires_arc = true 23 | 24 | end 25 | -------------------------------------------------------------------------------- /NKWatchChartDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B82FF2C71B74F87600C25D26 /* NKLineChart.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2C61B74F87600C25D26 /* NKLineChart.m */; }; 11 | B82FF2CA1B74F94B00C25D26 /* NKLineChartData.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2C91B74F94B00C25D26 /* NKLineChartData.m */; }; 12 | B82FF2CD1B74F96400C25D26 /* NKLineChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2CC1B74F96400C25D26 /* NKLineChartDataItem.m */; }; 13 | B82FF2D01B75953B00C25D26 /* NKPieChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2CF1B75953B00C25D26 /* NKPieChartDataItem.m */; }; 14 | B82FF2D31B75959400C25D26 /* NKPieChart.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2D21B75959400C25D26 /* NKPieChart.m */; }; 15 | B82FF2D61B759CD200C25D26 /* NKCircleChart.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2D51B759CD200C25D26 /* NKCircleChart.m */; }; 16 | B82FF2D91B75B69800C25D26 /* NKRadarChartDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2D81B75B69800C25D26 /* NKRadarChartDataItem.m */; }; 17 | B82FF2DC1B75B72000C25D26 /* NKRadarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = B82FF2DB1B75B72000C25D26 /* NKRadarChart.m */; }; 18 | B875FD4D1B735C1100B9EA93 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD4C1B735C1100B9EA93 /* main.m */; }; 19 | B875FD501B735C1100B9EA93 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD4F1B735C1100B9EA93 /* AppDelegate.m */; }; 20 | B875FD531B735C1100B9EA93 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD521B735C1100B9EA93 /* ViewController.m */; }; 21 | B875FD561B735C1100B9EA93 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B875FD541B735C1100B9EA93 /* Main.storyboard */; }; 22 | B875FD581B735C1100B9EA93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B875FD571B735C1100B9EA93 /* Assets.xcassets */; }; 23 | B875FD5B1B735C1100B9EA93 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B875FD591B735C1100B9EA93 /* LaunchScreen.storyboard */; }; 24 | B875FD681B735C7200B9EA93 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B875FD661B735C7200B9EA93 /* Interface.storyboard */; }; 25 | B875FD6A1B735C7200B9EA93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B875FD691B735C7200B9EA93 /* Assets.xcassets */; }; 26 | B875FD711B735C7200B9EA93 /* WatchChart Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = B875FD701B735C7200B9EA93 /* WatchChart Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 27 | B875FD771B735C7200B9EA93 /* InterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD761B735C7200B9EA93 /* InterfaceController.m */; }; 28 | B875FD7A1B735C7200B9EA93 /* ExtensionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD791B735C7200B9EA93 /* ExtensionDelegate.m */; }; 29 | B875FD7C1B735C7200B9EA93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B875FD7B1B735C7200B9EA93 /* Assets.xcassets */; }; 30 | B875FD801B735C7200B9EA93 /* WatchChart.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = B875FD641B735C7200B9EA93 /* WatchChart.app */; }; 31 | B875FD8C1B735CDF00B9EA93 /* NKColor.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD8B1B735CDF00B9EA93 /* NKColor.m */; }; 32 | B875FD931B735EA100B9EA93 /* NKBarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = B875FD921B735EA100B9EA93 /* NKBarChart.m */; }; 33 | B8D5E22F1B747C6F005C3A88 /* ChartTableRowController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8D5E22E1B747C6F005C3A88 /* ChartTableRowController.m */; }; 34 | B8D5E2321B748522005C3A88 /* ChartInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8D5E2311B748522005C3A88 /* ChartInterfaceController.m */; }; 35 | /* End PBXBuildFile section */ 36 | 37 | /* Begin PBXContainerItemProxy section */ 38 | B875FD721B735C7200B9EA93 /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = B875FD401B735C1100B9EA93 /* Project object */; 41 | proxyType = 1; 42 | remoteGlobalIDString = B875FD6F1B735C7200B9EA93; 43 | remoteInfo = "WatchChart Extension"; 44 | }; 45 | B875FD7E1B735C7200B9EA93 /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = B875FD401B735C1100B9EA93 /* Project object */; 48 | proxyType = 1; 49 | remoteGlobalIDString = B875FD631B735C7200B9EA93; 50 | remoteInfo = WatchChart; 51 | }; 52 | /* End PBXContainerItemProxy section */ 53 | 54 | /* Begin PBXCopyFilesBuildPhase section */ 55 | B875FD841B735C7200B9EA93 /* Embed App Extensions */ = { 56 | isa = PBXCopyFilesBuildPhase; 57 | buildActionMask = 2147483647; 58 | dstPath = ""; 59 | dstSubfolderSpec = 13; 60 | files = ( 61 | B875FD711B735C7200B9EA93 /* WatchChart Extension.appex in Embed App Extensions */, 62 | ); 63 | name = "Embed App Extensions"; 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | B875FD881B735C7200B9EA93 /* Embed Watch Content */ = { 67 | isa = PBXCopyFilesBuildPhase; 68 | buildActionMask = 2147483647; 69 | dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; 70 | dstSubfolderSpec = 16; 71 | files = ( 72 | B875FD801B735C7200B9EA93 /* WatchChart.app in Embed Watch Content */, 73 | ); 74 | name = "Embed Watch Content"; 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXCopyFilesBuildPhase section */ 78 | 79 | /* Begin PBXFileReference section */ 80 | B82FF2C51B74F87600C25D26 /* NKLineChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKLineChart.h; sourceTree = ""; }; 81 | B82FF2C61B74F87600C25D26 /* NKLineChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKLineChart.m; sourceTree = ""; }; 82 | B82FF2C81B74F94B00C25D26 /* NKLineChartData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKLineChartData.h; sourceTree = ""; }; 83 | B82FF2C91B74F94B00C25D26 /* NKLineChartData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKLineChartData.m; sourceTree = ""; }; 84 | B82FF2CB1B74F96400C25D26 /* NKLineChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKLineChartDataItem.h; sourceTree = ""; }; 85 | B82FF2CC1B74F96400C25D26 /* NKLineChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKLineChartDataItem.m; sourceTree = ""; }; 86 | B82FF2CE1B75953B00C25D26 /* NKPieChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKPieChartDataItem.h; sourceTree = ""; }; 87 | B82FF2CF1B75953B00C25D26 /* NKPieChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKPieChartDataItem.m; sourceTree = ""; }; 88 | B82FF2D11B75959400C25D26 /* NKPieChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKPieChart.h; sourceTree = ""; }; 89 | B82FF2D21B75959400C25D26 /* NKPieChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKPieChart.m; sourceTree = ""; }; 90 | B82FF2D41B759CD200C25D26 /* NKCircleChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKCircleChart.h; sourceTree = ""; }; 91 | B82FF2D51B759CD200C25D26 /* NKCircleChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKCircleChart.m; sourceTree = ""; }; 92 | B82FF2D71B75B69800C25D26 /* NKRadarChartDataItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKRadarChartDataItem.h; sourceTree = ""; }; 93 | B82FF2D81B75B69800C25D26 /* NKRadarChartDataItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKRadarChartDataItem.m; sourceTree = ""; }; 94 | B82FF2DA1B75B72000C25D26 /* NKRadarChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKRadarChart.h; sourceTree = ""; }; 95 | B82FF2DB1B75B72000C25D26 /* NKRadarChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKRadarChart.m; sourceTree = ""; }; 96 | B875FD481B735C1100B9EA93 /* NKWatchChartDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NKWatchChartDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97 | B875FD4C1B735C1100B9EA93 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 98 | B875FD4E1B735C1100B9EA93 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 99 | B875FD4F1B735C1100B9EA93 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 100 | B875FD511B735C1100B9EA93 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 101 | B875FD521B735C1100B9EA93 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 102 | B875FD551B735C1100B9EA93 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 103 | B875FD571B735C1100B9EA93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 104 | B875FD5A1B735C1100B9EA93 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 105 | B875FD5C1B735C1100B9EA93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 106 | B875FD641B735C7200B9EA93 /* WatchChart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WatchChart.app; sourceTree = BUILT_PRODUCTS_DIR; }; 107 | B875FD671B735C7200B9EA93 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; 108 | B875FD691B735C7200B9EA93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 109 | B875FD6B1B735C7200B9EA93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 110 | B875FD701B735C7200B9EA93 /* WatchChart Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "WatchChart Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 111 | B875FD751B735C7200B9EA93 /* InterfaceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InterfaceController.h; sourceTree = ""; }; 112 | B875FD761B735C7200B9EA93 /* InterfaceController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InterfaceController.m; sourceTree = ""; }; 113 | B875FD781B735C7200B9EA93 /* ExtensionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtensionDelegate.h; sourceTree = ""; }; 114 | B875FD791B735C7200B9EA93 /* ExtensionDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExtensionDelegate.m; sourceTree = ""; }; 115 | B875FD7B1B735C7200B9EA93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 116 | B875FD7D1B735C7200B9EA93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 117 | B875FD8A1B735CDF00B9EA93 /* NKColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKColor.h; sourceTree = ""; }; 118 | B875FD8B1B735CDF00B9EA93 /* NKColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKColor.m; sourceTree = ""; }; 119 | B875FD8E1B735E2900B9EA93 /* NKWatchChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKWatchChart.h; sourceTree = ""; }; 120 | B875FD911B735EA100B9EA93 /* NKBarChart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NKBarChart.h; sourceTree = ""; }; 121 | B875FD921B735EA100B9EA93 /* NKBarChart.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NKBarChart.m; sourceTree = ""; }; 122 | B8D5E22D1B747C6F005C3A88 /* ChartTableRowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChartTableRowController.h; sourceTree = ""; }; 123 | B8D5E22E1B747C6F005C3A88 /* ChartTableRowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChartTableRowController.m; sourceTree = ""; }; 124 | B8D5E2301B748522005C3A88 /* ChartInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChartInterfaceController.h; sourceTree = ""; }; 125 | B8D5E2311B748522005C3A88 /* ChartInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChartInterfaceController.m; sourceTree = ""; }; 126 | /* End PBXFileReference section */ 127 | 128 | /* Begin PBXFrameworksBuildPhase section */ 129 | B875FD451B735C1100B9EA93 /* Frameworks */ = { 130 | isa = PBXFrameworksBuildPhase; 131 | buildActionMask = 2147483647; 132 | files = ( 133 | ); 134 | runOnlyForDeploymentPostprocessing = 0; 135 | }; 136 | B875FD6D1B735C7200B9EA93 /* Frameworks */ = { 137 | isa = PBXFrameworksBuildPhase; 138 | buildActionMask = 2147483647; 139 | files = ( 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXFrameworksBuildPhase section */ 144 | 145 | /* Begin PBXGroup section */ 146 | B875FD3F1B735C1100B9EA93 = { 147 | isa = PBXGroup; 148 | children = ( 149 | B875FD4A1B735C1100B9EA93 /* NKWatchChartDemo */, 150 | B875FD651B735C7200B9EA93 /* WatchChart */, 151 | B875FD741B735C7200B9EA93 /* WatchChart Extension */, 152 | B875FD491B735C1100B9EA93 /* Products */, 153 | ); 154 | sourceTree = ""; 155 | }; 156 | B875FD491B735C1100B9EA93 /* Products */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | B875FD481B735C1100B9EA93 /* NKWatchChartDemo.app */, 160 | B875FD641B735C7200B9EA93 /* WatchChart.app */, 161 | B875FD701B735C7200B9EA93 /* WatchChart Extension.appex */, 162 | ); 163 | name = Products; 164 | sourceTree = ""; 165 | }; 166 | B875FD4A1B735C1100B9EA93 /* NKWatchChartDemo */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | B875FD4E1B735C1100B9EA93 /* AppDelegate.h */, 170 | B875FD4F1B735C1100B9EA93 /* AppDelegate.m */, 171 | B875FD511B735C1100B9EA93 /* ViewController.h */, 172 | B875FD521B735C1100B9EA93 /* ViewController.m */, 173 | B875FD541B735C1100B9EA93 /* Main.storyboard */, 174 | B875FD571B735C1100B9EA93 /* Assets.xcassets */, 175 | B875FD591B735C1100B9EA93 /* LaunchScreen.storyboard */, 176 | B875FD5C1B735C1100B9EA93 /* Info.plist */, 177 | B875FD4B1B735C1100B9EA93 /* Supporting Files */, 178 | ); 179 | path = NKWatchChartDemo; 180 | sourceTree = ""; 181 | }; 182 | B875FD4B1B735C1100B9EA93 /* Supporting Files */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | B875FD4C1B735C1100B9EA93 /* main.m */, 186 | ); 187 | name = "Supporting Files"; 188 | sourceTree = ""; 189 | }; 190 | B875FD651B735C7200B9EA93 /* WatchChart */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | B875FD661B735C7200B9EA93 /* Interface.storyboard */, 194 | B875FD691B735C7200B9EA93 /* Assets.xcassets */, 195 | B875FD6B1B735C7200B9EA93 /* Info.plist */, 196 | ); 197 | path = WatchChart; 198 | sourceTree = ""; 199 | }; 200 | B875FD741B735C7200B9EA93 /* WatchChart Extension */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | B875FD891B735CC600B9EA93 /* NKWatchChart */, 204 | B875FD751B735C7200B9EA93 /* InterfaceController.h */, 205 | B875FD761B735C7200B9EA93 /* InterfaceController.m */, 206 | B8D5E22D1B747C6F005C3A88 /* ChartTableRowController.h */, 207 | B8D5E22E1B747C6F005C3A88 /* ChartTableRowController.m */, 208 | B8D5E2301B748522005C3A88 /* ChartInterfaceController.h */, 209 | B8D5E2311B748522005C3A88 /* ChartInterfaceController.m */, 210 | B875FD781B735C7200B9EA93 /* ExtensionDelegate.h */, 211 | B875FD791B735C7200B9EA93 /* ExtensionDelegate.m */, 212 | B875FD7B1B735C7200B9EA93 /* Assets.xcassets */, 213 | B875FD7D1B735C7200B9EA93 /* Info.plist */, 214 | ); 215 | path = "WatchChart Extension"; 216 | sourceTree = ""; 217 | }; 218 | B875FD891B735CC600B9EA93 /* NKWatchChart */ = { 219 | isa = PBXGroup; 220 | children = ( 221 | B875FD8E1B735E2900B9EA93 /* NKWatchChart.h */, 222 | B875FD8A1B735CDF00B9EA93 /* NKColor.h */, 223 | B875FD8B1B735CDF00B9EA93 /* NKColor.m */, 224 | B82FF2C51B74F87600C25D26 /* NKLineChart.h */, 225 | B82FF2C61B74F87600C25D26 /* NKLineChart.m */, 226 | B82FF2C81B74F94B00C25D26 /* NKLineChartData.h */, 227 | B82FF2C91B74F94B00C25D26 /* NKLineChartData.m */, 228 | B82FF2CB1B74F96400C25D26 /* NKLineChartDataItem.h */, 229 | B82FF2CC1B74F96400C25D26 /* NKLineChartDataItem.m */, 230 | B875FD911B735EA100B9EA93 /* NKBarChart.h */, 231 | B875FD921B735EA100B9EA93 /* NKBarChart.m */, 232 | B82FF2D11B75959400C25D26 /* NKPieChart.h */, 233 | B82FF2D21B75959400C25D26 /* NKPieChart.m */, 234 | B82FF2CE1B75953B00C25D26 /* NKPieChartDataItem.h */, 235 | B82FF2CF1B75953B00C25D26 /* NKPieChartDataItem.m */, 236 | B82FF2D41B759CD200C25D26 /* NKCircleChart.h */, 237 | B82FF2D51B759CD200C25D26 /* NKCircleChart.m */, 238 | B82FF2DA1B75B72000C25D26 /* NKRadarChart.h */, 239 | B82FF2DB1B75B72000C25D26 /* NKRadarChart.m */, 240 | B82FF2D71B75B69800C25D26 /* NKRadarChartDataItem.h */, 241 | B82FF2D81B75B69800C25D26 /* NKRadarChartDataItem.m */, 242 | ); 243 | path = NKWatchChart; 244 | sourceTree = ""; 245 | }; 246 | /* End PBXGroup section */ 247 | 248 | /* Begin PBXNativeTarget section */ 249 | B875FD471B735C1100B9EA93 /* NKWatchChartDemo */ = { 250 | isa = PBXNativeTarget; 251 | buildConfigurationList = B875FD5F1B735C1100B9EA93 /* Build configuration list for PBXNativeTarget "NKWatchChartDemo" */; 252 | buildPhases = ( 253 | B875FD441B735C1100B9EA93 /* Sources */, 254 | B875FD451B735C1100B9EA93 /* Frameworks */, 255 | B875FD461B735C1100B9EA93 /* Resources */, 256 | B875FD881B735C7200B9EA93 /* Embed Watch Content */, 257 | ); 258 | buildRules = ( 259 | ); 260 | dependencies = ( 261 | B875FD7F1B735C7200B9EA93 /* PBXTargetDependency */, 262 | ); 263 | name = NKWatchChartDemo; 264 | productName = NKWatchChartDemo; 265 | productReference = B875FD481B735C1100B9EA93 /* NKWatchChartDemo.app */; 266 | productType = "com.apple.product-type.application"; 267 | }; 268 | B875FD631B735C7200B9EA93 /* WatchChart */ = { 269 | isa = PBXNativeTarget; 270 | buildConfigurationList = B875FD851B735C7200B9EA93 /* Build configuration list for PBXNativeTarget "WatchChart" */; 271 | buildPhases = ( 272 | B875FD621B735C7200B9EA93 /* Resources */, 273 | B875FD841B735C7200B9EA93 /* Embed App Extensions */, 274 | ); 275 | buildRules = ( 276 | ); 277 | dependencies = ( 278 | B875FD731B735C7200B9EA93 /* PBXTargetDependency */, 279 | ); 280 | name = WatchChart; 281 | productName = WatchChart; 282 | productReference = B875FD641B735C7200B9EA93 /* WatchChart.app */; 283 | productType = "com.apple.product-type.application.watchapp2"; 284 | }; 285 | B875FD6F1B735C7200B9EA93 /* WatchChart Extension */ = { 286 | isa = PBXNativeTarget; 287 | buildConfigurationList = B875FD811B735C7200B9EA93 /* Build configuration list for PBXNativeTarget "WatchChart Extension" */; 288 | buildPhases = ( 289 | B875FD6C1B735C7200B9EA93 /* Sources */, 290 | B875FD6D1B735C7200B9EA93 /* Frameworks */, 291 | B875FD6E1B735C7200B9EA93 /* Resources */, 292 | ); 293 | buildRules = ( 294 | ); 295 | dependencies = ( 296 | ); 297 | name = "WatchChart Extension"; 298 | productName = "WatchChart Extension"; 299 | productReference = B875FD701B735C7200B9EA93 /* WatchChart Extension.appex */; 300 | productType = "com.apple.product-type.watchkit2-extension"; 301 | }; 302 | /* End PBXNativeTarget section */ 303 | 304 | /* Begin PBXProject section */ 305 | B875FD401B735C1100B9EA93 /* Project object */ = { 306 | isa = PBXProject; 307 | attributes = { 308 | LastUpgradeCheck = 0700; 309 | ORGANIZATIONNAME = Peng; 310 | TargetAttributes = { 311 | B875FD471B735C1100B9EA93 = { 312 | CreatedOnToolsVersion = 7.0; 313 | }; 314 | B875FD631B735C7200B9EA93 = { 315 | CreatedOnToolsVersion = 7.0; 316 | }; 317 | B875FD6F1B735C7200B9EA93 = { 318 | CreatedOnToolsVersion = 7.0; 319 | }; 320 | }; 321 | }; 322 | buildConfigurationList = B875FD431B735C1100B9EA93 /* Build configuration list for PBXProject "NKWatchChartDemo" */; 323 | compatibilityVersion = "Xcode 3.2"; 324 | developmentRegion = English; 325 | hasScannedForEncodings = 0; 326 | knownRegions = ( 327 | en, 328 | Base, 329 | ); 330 | mainGroup = B875FD3F1B735C1100B9EA93; 331 | productRefGroup = B875FD491B735C1100B9EA93 /* Products */; 332 | projectDirPath = ""; 333 | projectRoot = ""; 334 | targets = ( 335 | B875FD471B735C1100B9EA93 /* NKWatchChartDemo */, 336 | B875FD631B735C7200B9EA93 /* WatchChart */, 337 | B875FD6F1B735C7200B9EA93 /* WatchChart Extension */, 338 | ); 339 | }; 340 | /* End PBXProject section */ 341 | 342 | /* Begin PBXResourcesBuildPhase section */ 343 | B875FD461B735C1100B9EA93 /* Resources */ = { 344 | isa = PBXResourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | B875FD5B1B735C1100B9EA93 /* LaunchScreen.storyboard in Resources */, 348 | B875FD581B735C1100B9EA93 /* Assets.xcassets in Resources */, 349 | B875FD561B735C1100B9EA93 /* Main.storyboard in Resources */, 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | }; 353 | B875FD621B735C7200B9EA93 /* Resources */ = { 354 | isa = PBXResourcesBuildPhase; 355 | buildActionMask = 2147483647; 356 | files = ( 357 | B875FD6A1B735C7200B9EA93 /* Assets.xcassets in Resources */, 358 | B875FD681B735C7200B9EA93 /* Interface.storyboard in Resources */, 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | }; 362 | B875FD6E1B735C7200B9EA93 /* Resources */ = { 363 | isa = PBXResourcesBuildPhase; 364 | buildActionMask = 2147483647; 365 | files = ( 366 | B875FD7C1B735C7200B9EA93 /* Assets.xcassets in Resources */, 367 | ); 368 | runOnlyForDeploymentPostprocessing = 0; 369 | }; 370 | /* End PBXResourcesBuildPhase section */ 371 | 372 | /* Begin PBXSourcesBuildPhase section */ 373 | B875FD441B735C1100B9EA93 /* Sources */ = { 374 | isa = PBXSourcesBuildPhase; 375 | buildActionMask = 2147483647; 376 | files = ( 377 | B875FD531B735C1100B9EA93 /* ViewController.m in Sources */, 378 | B875FD501B735C1100B9EA93 /* AppDelegate.m in Sources */, 379 | B875FD4D1B735C1100B9EA93 /* main.m in Sources */, 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | }; 383 | B875FD6C1B735C7200B9EA93 /* Sources */ = { 384 | isa = PBXSourcesBuildPhase; 385 | buildActionMask = 2147483647; 386 | files = ( 387 | B82FF2C71B74F87600C25D26 /* NKLineChart.m in Sources */, 388 | B82FF2D01B75953B00C25D26 /* NKPieChartDataItem.m in Sources */, 389 | B82FF2CA1B74F94B00C25D26 /* NKLineChartData.m in Sources */, 390 | B8D5E2321B748522005C3A88 /* ChartInterfaceController.m in Sources */, 391 | B875FD7A1B735C7200B9EA93 /* ExtensionDelegate.m in Sources */, 392 | B82FF2D31B75959400C25D26 /* NKPieChart.m in Sources */, 393 | B875FD771B735C7200B9EA93 /* InterfaceController.m in Sources */, 394 | B82FF2D91B75B69800C25D26 /* NKRadarChartDataItem.m in Sources */, 395 | B82FF2CD1B74F96400C25D26 /* NKLineChartDataItem.m in Sources */, 396 | B875FD8C1B735CDF00B9EA93 /* NKColor.m in Sources */, 397 | B8D5E22F1B747C6F005C3A88 /* ChartTableRowController.m in Sources */, 398 | B875FD931B735EA100B9EA93 /* NKBarChart.m in Sources */, 399 | B82FF2DC1B75B72000C25D26 /* NKRadarChart.m in Sources */, 400 | B82FF2D61B759CD200C25D26 /* NKCircleChart.m in Sources */, 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | /* End PBXSourcesBuildPhase section */ 405 | 406 | /* Begin PBXTargetDependency section */ 407 | B875FD731B735C7200B9EA93 /* PBXTargetDependency */ = { 408 | isa = PBXTargetDependency; 409 | target = B875FD6F1B735C7200B9EA93 /* WatchChart Extension */; 410 | targetProxy = B875FD721B735C7200B9EA93 /* PBXContainerItemProxy */; 411 | }; 412 | B875FD7F1B735C7200B9EA93 /* PBXTargetDependency */ = { 413 | isa = PBXTargetDependency; 414 | target = B875FD631B735C7200B9EA93 /* WatchChart */; 415 | targetProxy = B875FD7E1B735C7200B9EA93 /* PBXContainerItemProxy */; 416 | }; 417 | /* End PBXTargetDependency section */ 418 | 419 | /* Begin PBXVariantGroup section */ 420 | B875FD541B735C1100B9EA93 /* Main.storyboard */ = { 421 | isa = PBXVariantGroup; 422 | children = ( 423 | B875FD551B735C1100B9EA93 /* Base */, 424 | ); 425 | name = Main.storyboard; 426 | sourceTree = ""; 427 | }; 428 | B875FD591B735C1100B9EA93 /* LaunchScreen.storyboard */ = { 429 | isa = PBXVariantGroup; 430 | children = ( 431 | B875FD5A1B735C1100B9EA93 /* Base */, 432 | ); 433 | name = LaunchScreen.storyboard; 434 | sourceTree = ""; 435 | }; 436 | B875FD661B735C7200B9EA93 /* Interface.storyboard */ = { 437 | isa = PBXVariantGroup; 438 | children = ( 439 | B875FD671B735C7200B9EA93 /* Base */, 440 | ); 441 | name = Interface.storyboard; 442 | sourceTree = ""; 443 | }; 444 | /* End PBXVariantGroup section */ 445 | 446 | /* Begin XCBuildConfiguration section */ 447 | B875FD5D1B735C1100B9EA93 /* Debug */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | ALWAYS_SEARCH_USER_PATHS = NO; 451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 452 | CLANG_CXX_LIBRARY = "libc++"; 453 | CLANG_ENABLE_MODULES = YES; 454 | CLANG_ENABLE_OBJC_ARC = YES; 455 | CLANG_WARN_BOOL_CONVERSION = YES; 456 | CLANG_WARN_CONSTANT_CONVERSION = YES; 457 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 458 | CLANG_WARN_EMPTY_BODY = YES; 459 | CLANG_WARN_ENUM_CONVERSION = YES; 460 | CLANG_WARN_INT_CONVERSION = YES; 461 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 462 | CLANG_WARN_UNREACHABLE_CODE = YES; 463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 464 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 465 | COPY_PHASE_STRIP = NO; 466 | DEBUG_INFORMATION_FORMAT = dwarf; 467 | ENABLE_STRICT_OBJC_MSGSEND = YES; 468 | ENABLE_TESTABILITY = YES; 469 | GCC_C_LANGUAGE_STANDARD = gnu99; 470 | GCC_DYNAMIC_NO_PIC = NO; 471 | GCC_NO_COMMON_BLOCKS = YES; 472 | GCC_OPTIMIZATION_LEVEL = 0; 473 | GCC_PREPROCESSOR_DEFINITIONS = ( 474 | "DEBUG=1", 475 | "$(inherited)", 476 | ); 477 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 478 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 479 | GCC_WARN_UNDECLARED_SELECTOR = YES; 480 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 481 | GCC_WARN_UNUSED_FUNCTION = YES; 482 | GCC_WARN_UNUSED_VARIABLE = YES; 483 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 484 | MTL_ENABLE_DEBUG_INFO = YES; 485 | ONLY_ACTIVE_ARCH = YES; 486 | SDKROOT = iphoneos; 487 | }; 488 | name = Debug; 489 | }; 490 | B875FD5E1B735C1100B9EA93 /* Release */ = { 491 | isa = XCBuildConfiguration; 492 | buildSettings = { 493 | ALWAYS_SEARCH_USER_PATHS = NO; 494 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 495 | CLANG_CXX_LIBRARY = "libc++"; 496 | CLANG_ENABLE_MODULES = YES; 497 | CLANG_ENABLE_OBJC_ARC = YES; 498 | CLANG_WARN_BOOL_CONVERSION = YES; 499 | CLANG_WARN_CONSTANT_CONVERSION = YES; 500 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 501 | CLANG_WARN_EMPTY_BODY = YES; 502 | CLANG_WARN_ENUM_CONVERSION = YES; 503 | CLANG_WARN_INT_CONVERSION = YES; 504 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 505 | CLANG_WARN_UNREACHABLE_CODE = YES; 506 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 507 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 508 | COPY_PHASE_STRIP = NO; 509 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 510 | ENABLE_NS_ASSERTIONS = NO; 511 | ENABLE_STRICT_OBJC_MSGSEND = YES; 512 | GCC_C_LANGUAGE_STANDARD = gnu99; 513 | GCC_NO_COMMON_BLOCKS = YES; 514 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 515 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 516 | GCC_WARN_UNDECLARED_SELECTOR = YES; 517 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 518 | GCC_WARN_UNUSED_FUNCTION = YES; 519 | GCC_WARN_UNUSED_VARIABLE = YES; 520 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 521 | MTL_ENABLE_DEBUG_INFO = NO; 522 | SDKROOT = iphoneos; 523 | VALIDATE_PRODUCT = YES; 524 | }; 525 | name = Release; 526 | }; 527 | B875FD601B735C1100B9EA93 /* Debug */ = { 528 | isa = XCBuildConfiguration; 529 | buildSettings = { 530 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 531 | INFOPLIST_FILE = NKWatchChartDemo/Info.plist; 532 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 533 | PRODUCT_BUNDLE_IDENTIFIER = watch.develop.NKWatchChartDemo; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | }; 536 | name = Debug; 537 | }; 538 | B875FD611B735C1100B9EA93 /* Release */ = { 539 | isa = XCBuildConfiguration; 540 | buildSettings = { 541 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 542 | INFOPLIST_FILE = NKWatchChartDemo/Info.plist; 543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 544 | PRODUCT_BUNDLE_IDENTIFIER = watch.develop.NKWatchChartDemo; 545 | PRODUCT_NAME = "$(TARGET_NAME)"; 546 | }; 547 | name = Release; 548 | }; 549 | B875FD821B735C7200B9EA93 /* Debug */ = { 550 | isa = XCBuildConfiguration; 551 | buildSettings = { 552 | INFOPLIST_FILE = "WatchChart Extension/Info.plist"; 553 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 554 | PRODUCT_BUNDLE_IDENTIFIER = watch.develop.NKWatchChartDemo.watchkitapp.watchkitextension; 555 | PRODUCT_NAME = "${TARGET_NAME}"; 556 | SDKROOT = watchos; 557 | SKIP_INSTALL = YES; 558 | TARGETED_DEVICE_FAMILY = 4; 559 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 560 | }; 561 | name = Debug; 562 | }; 563 | B875FD831B735C7200B9EA93 /* Release */ = { 564 | isa = XCBuildConfiguration; 565 | buildSettings = { 566 | INFOPLIST_FILE = "WatchChart Extension/Info.plist"; 567 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 568 | PRODUCT_BUNDLE_IDENTIFIER = watch.develop.NKWatchChartDemo.watchkitapp.watchkitextension; 569 | PRODUCT_NAME = "${TARGET_NAME}"; 570 | SDKROOT = watchos; 571 | SKIP_INSTALL = YES; 572 | TARGETED_DEVICE_FAMILY = 4; 573 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 574 | }; 575 | name = Release; 576 | }; 577 | B875FD861B735C7200B9EA93 /* Debug */ = { 578 | isa = XCBuildConfiguration; 579 | buildSettings = { 580 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 581 | IBSC_MODULE = WatchChart_Extension; 582 | INFOPLIST_FILE = WatchChart/Info.plist; 583 | PRODUCT_BUNDLE_IDENTIFIER = watch.develop.NKWatchChartDemo.watchkitapp; 584 | PRODUCT_NAME = "$(TARGET_NAME)"; 585 | SDKROOT = watchos; 586 | SKIP_INSTALL = YES; 587 | TARGETED_DEVICE_FAMILY = 4; 588 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 589 | }; 590 | name = Debug; 591 | }; 592 | B875FD871B735C7200B9EA93 /* Release */ = { 593 | isa = XCBuildConfiguration; 594 | buildSettings = { 595 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 596 | IBSC_MODULE = WatchChart_Extension; 597 | INFOPLIST_FILE = WatchChart/Info.plist; 598 | PRODUCT_BUNDLE_IDENTIFIER = watch.develop.NKWatchChartDemo.watchkitapp; 599 | PRODUCT_NAME = "$(TARGET_NAME)"; 600 | SDKROOT = watchos; 601 | SKIP_INSTALL = YES; 602 | TARGETED_DEVICE_FAMILY = 4; 603 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 604 | }; 605 | name = Release; 606 | }; 607 | /* End XCBuildConfiguration section */ 608 | 609 | /* Begin XCConfigurationList section */ 610 | B875FD431B735C1100B9EA93 /* Build configuration list for PBXProject "NKWatchChartDemo" */ = { 611 | isa = XCConfigurationList; 612 | buildConfigurations = ( 613 | B875FD5D1B735C1100B9EA93 /* Debug */, 614 | B875FD5E1B735C1100B9EA93 /* Release */, 615 | ); 616 | defaultConfigurationIsVisible = 0; 617 | defaultConfigurationName = Release; 618 | }; 619 | B875FD5F1B735C1100B9EA93 /* Build configuration list for PBXNativeTarget "NKWatchChartDemo" */ = { 620 | isa = XCConfigurationList; 621 | buildConfigurations = ( 622 | B875FD601B735C1100B9EA93 /* Debug */, 623 | B875FD611B735C1100B9EA93 /* Release */, 624 | ); 625 | defaultConfigurationIsVisible = 0; 626 | defaultConfigurationName = Release; 627 | }; 628 | B875FD811B735C7200B9EA93 /* Build configuration list for PBXNativeTarget "WatchChart Extension" */ = { 629 | isa = XCConfigurationList; 630 | buildConfigurations = ( 631 | B875FD821B735C7200B9EA93 /* Debug */, 632 | B875FD831B735C7200B9EA93 /* Release */, 633 | ); 634 | defaultConfigurationIsVisible = 0; 635 | defaultConfigurationName = Release; 636 | }; 637 | B875FD851B735C7200B9EA93 /* Build configuration list for PBXNativeTarget "WatchChart" */ = { 638 | isa = XCConfigurationList; 639 | buildConfigurations = ( 640 | B875FD861B735C7200B9EA93 /* Debug */, 641 | B875FD871B735C7200B9EA93 /* Release */, 642 | ); 643 | defaultConfigurationIsVisible = 0; 644 | defaultConfigurationName = Release; 645 | }; 646 | /* End XCConfigurationList section */ 647 | }; 648 | rootObject = B875FD401B735C1100B9EA93 /* Project object */; 649 | } 650 | -------------------------------------------------------------------------------- /NKWatchChartDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /NKWatchChartDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /NKWatchChartDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /NKWatchChartDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /NKWatchChartDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /NKWatchChartDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /NKWatchChartDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /NKWatchChartDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /NKWatchChartDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #NKWatchChart# 2 | 3 | ![Verision](https://img.shields.io/badge/pod-v0.1.0-blue.svg) 4 | ![Platform](https://img.shields.io/badge/platform-watchOS-ff69b4.svg) 5 | ![License](https://img.shields.io/badge/license-MIT-blue.svg) 6 | 7 | A chart library for Apple Watch based on [PNChart](https://github.com/kevinzhow/PNChart). We support line, bar, pie, circle and radar charts now and will integrate more chart types from [ios-charts](https://github.com/danielgindi/ios-charts). 8 | 9 | ![gif](https://db.tt/d7pJD84m) 10 | 11 | ##Usage## 12 | 13 | ###Cocoapods### 14 | In your watchOS target 15 | 16 | pod 'NKWatchChart' 17 | 18 | Then 19 | 20 | pod install 21 | 22 | And 23 | 24 | #import "NKWatchChart.h" 25 | 26 | [Using Cocoapods with watchOS 2](https://medium.com/@JTEhlert/using-cocoapods-with-watchos-2-723b92eae04f) by Justin Ehlert 27 | 28 | ###Copy NKWatchChart folder to watch app extension ### 29 | 30 | ##Requirements## 31 | * watchOS ~> 2.0 32 | * Xcode >= 7.0 33 | 34 | ##Examples## 35 | 36 | ####Line Chart#### 37 | 38 | ![Line Chart](https://db.tt/XjrGEkMM) 39 | 40 | ```objective-c 41 | 42 | NKLineChart *chart = [[NKLineChart alloc] initWithFrame:frame]; 43 | chart.yLabelFormat = @"%1.1f"; 44 | [chart setXLabels:@[@"SEP 1",@"SEP 2",@"SEP 3",@"SEP 4",@"SEP 5",@"SEP 6",@"SEP 7"]]; 45 | chart.showCoordinateAxis = YES; 46 | 47 | //Use yFixedValueMax and yFixedValueMin to Fix the Max and Min Y Value 48 | //Only if you needed 49 | chart.yFixedValueMax = 300.0; 50 | chart.yFixedValueMin = 0.0; 51 | 52 | [chart setYLabels:@[ 53 | @"0", 54 | @"50", 55 | @"100", 56 | @"150", 57 | @"200", 58 | @"250", 59 | @"300", 60 | ] 61 | ]; 62 | 63 | chart.yLabelFont = [UIFont systemFontOfSize:6.f]; 64 | chart.xLabelFont = [UIFont systemFontOfSize:6.f]; 65 | chart.xLabelWidth = 10.f; 66 | chart.yLabelColor = NKGreen; 67 | chart.xLabelColor = NKGreen; 68 | 69 | chart.axisColor = NKLightGrey; 70 | chart.axisWidth = 1.f; 71 | 72 | chart.xUnit = @"Day"; 73 | chart.yUnit = @"Min"; 74 | 75 | // Line Chart #1 76 | NSArray * data01Array = @[@60.1, @160.1, @126.4, @0.0, @186.2, @127.2, @176.2]; 77 | NKLineChartData *data01 = [NKLineChartData new]; 78 | data01.color = NKGreen; 79 | data01.alpha = 0.9f; 80 | data01.itemCount = data01Array.count; 81 | data01.inflexionPointStyle = NKLineChartPointStyleTriangle; 82 | data01.getData = ^(NSUInteger index) { 83 | CGFloat yValue = [data01Array[index] floatValue]; 84 | return [NKLineChartDataItem dataItemWithY:yValue]; 85 | }; 86 | 87 | // Line Chart #2 88 | NSArray * data02Array = @[@0.0, @180.1, @26.4, @202.2, @126.2, @167.2, @276.2]; 89 | NKLineChartData *data02 = [NKLineChartData new]; 90 | data02.color = NKTwitterColor; 91 | data02.alpha = 0.5f; 92 | data02.itemCount = data02Array.count; 93 | data02.inflexionPointStyle = NKLineChartPointStyleCircle; 94 | data02.getData = ^(NSUInteger index) { 95 | CGFloat yValue = [data02Array[index] floatValue]; 96 | return [NKLineChartDataItem dataItemWithY:yValue]; 97 | }; 98 | 99 | 100 | chart.chartData = @[data01,data02]; 101 | 102 | image = [chart drawImage]; 103 | [self.chartImage setImage:image]; 104 | 105 | ``` 106 | 107 | ####Bar Chart#### 108 | 109 | ![Bar Chart](https://db.tt/MfvNnpOp) 110 | 111 | ```objective-c 112 | 113 | NKBarChart *chart = [[NKBarChart alloc] initWithFrame:frame]; 114 | chart.yLabelFormatter = ^(CGFloat yValue){ 115 | CGFloat yValueParsed = yValue; 116 | NSString * labelText = [NSString stringWithFormat:@"%0.f",yValueParsed]; 117 | return labelText; 118 | }; 119 | chart.labelMarginTop = 5.0; 120 | chart.showChartBorder = YES; 121 | [chart setXLabels:@[@"2",@"3",@"4",@"5",@"2",@"3",@"4",@"5"]]; 122 | // self.barChart.yLabels = @[@-10,@0,@10]; 123 | [chart setYValues:@[@10.82,@1.88,@6.96,@33.93,@10.82,@1.88,@6.96,@33.93]]; 124 | [chart setStrokeColors:@[NKGreen,NKGreen,NKRed,NKGreen,NKGreen,NKGreen,NKRed,NKGreen]]; 125 | 126 | image = [chart drawImage]; 127 | [self.chartImage setImage:image]; 128 | 129 | ``` 130 | 131 | ####Pie Chart#### 132 | 133 | ![Pie Chart](https://db.tt/hs3MwXxW) 134 | 135 | ```objective-c 136 | 137 | NSArray *items = @[[NKPieChartDataItem dataItemWithValue:10 color:NKLightGreen], 138 | [NKPieChartDataItem dataItemWithValue:20 color:NKFreshGreen description:@"WWDC"], 139 | [NKPieChartDataItem dataItemWithValue:40 color:NKDeepGreen description:@"GOOG I/O"], 140 | ]; 141 | 142 | NKPieChart *chart = [[NKPieChart alloc] initWithFrame:frame items:items]; 143 | chart.descriptionTextColor = [UIColor whiteColor]; 144 | chart.descriptionTextFont = [UIFont systemFontOfSize:12.0]; 145 | chart.showAbsoluteValues = NO; 146 | chart.showOnlyValues = NO; 147 | 148 | image = [chart drawImage]; 149 | [self.chartImage setImage:image]; 150 | 151 | ``` 152 | 153 | ####Circle Chart#### 154 | 155 | ![Circle Chart](https://db.tt/bmRpg3ep) 156 | 157 | ```objective-c 158 | 159 | UIColor *shadowColor = [UIColor colorWithRed:225.0 / 255.0 green:225.0 / 255.0 blue:225.0 / 255.0 alpha:0.5f]; 160 | NKCircleChart *chart = [[NKCircleChart alloc] initWithFrame:frame total:@100 current:@60 clockwise:YES shadow:YES shadowColor:shadowColor displayCountingLabel:YES overrideLineWidth:@5]; 161 | chart.strokeColor = NKGreen; 162 | chart.strokeColorGradientStart = NKLightGreen; 163 | image = [chart drawImage]; 164 | [self.chartImage setImage:image]; 165 | 166 | ``` 167 | 168 | ####Radar Chart#### 169 | 170 | ![Radar Chart](https://db.tt/FgQer9TW) 171 | 172 | ```objective-c 173 | 174 | NSArray *items = @[[NKRadarChartDataItem dataItemWithValue:3 description:@"Art"], 175 | [NKRadarChartDataItem dataItemWithValue:2 description:@"Math"], 176 | [NKRadarChartDataItem dataItemWithValue:8 description:@"Sports"], 177 | [NKRadarChartDataItem dataItemWithValue:5 description:@"Liter"], 178 | [NKRadarChartDataItem dataItemWithValue:4 description:@"Other"], 179 | ]; 180 | NKRadarChart *chart = [[NKRadarChart alloc] initWithFrame:frame items:items valueDivider:1]; 181 | 182 | image = [chart drawImage]; 183 | [self.chartImage setImage:image]; 184 | 185 | ``` 186 | ##TODO## 187 | * more testing 188 | * refactoring 189 | * add bubble chart from [ios-charts](https://github.com/danielgindi/ios-charts) 190 | * add scatter chart 191 | * more chart types 192 | 193 | ##Apps using NKWatchChart## 194 | 195 | Please Let me know at guoleii@gmail.com if you use NKWatchChart in your apps. 196 | 197 | ##NKWatchChart on medias## 198 | 199 | * maniacdev.com 200 | 201 | [https://maniacdev.com/2015/08/open-source-library-for-drawing-charts-on-the-apple-watch](https://maniacdev.com/2015/08/open-source-library-for-drawing-charts-on-the-apple-watch) 202 | 203 | * watchkitresources.com 204 | 205 | [http://watchkitresources.com/issues/9](http://watchkitresources.com/issues/9) 206 | 207 | * iphonedev.co.kr in Korean 208 | 209 | [http://iphonedev.co.kr/sampleSource/24204](http://iphonedev.co.kr/sampleSource/24204) 210 | 211 | * toutiao.io in Chinese 212 | 213 | [http://toutiao.io/posts/qga8e](http://toutiao.io/posts/qga8e) 214 | 215 | ##License## 216 | This code is distributed under the terms and conditions of the MIT license. 217 | 218 | ##Thanks## 219 | Awesome chart library [PNChart](https://github.com/kevinzhow/PNChart) by @kevinzhow 220 | -------------------------------------------------------------------------------- /WatchChart Extension/Assets.xcassets/README__ignoredByTemplate__: -------------------------------------------------------------------------------- 1 | Did you know that git does not support storing empty directories? 2 | -------------------------------------------------------------------------------- /WatchChart Extension/ChartInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChartInterfaceController.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ChartInterfaceController : WKInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /WatchChart Extension/ChartInterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChartInterfaceController.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "ChartInterfaceController.h" 10 | #import "NKWatchChart/NKWatchChart.h" 11 | 12 | @interface ChartInterfaceController () 13 | 14 | @property (weak, nonatomic) IBOutlet WKInterfaceImage *chartImage; 15 | 16 | @property (strong, nonatomic) NSString *chartType; 17 | 18 | @end 19 | 20 | @implementation ChartInterfaceController 21 | 22 | - (void)awakeWithContext:(id)context { 23 | [super awakeWithContext:context]; 24 | 25 | // Configure interface objects here. 26 | self.chartType = (NSString*)context; 27 | } 28 | 29 | - (void)willActivate { 30 | // This method is called when watch view controller is about to be visible to user 31 | [super willActivate]; 32 | 33 | UIImage *image; 34 | CGRect frame = CGRectMake(0, 0, self.contentFrame.size.width, self.contentFrame.size.height); 35 | 36 | if ([self.chartType isEqualToString: @"Line Chart"]) 37 | { 38 | NKLineChart *chart = [[NKLineChart alloc] initWithFrame:frame]; 39 | chart.yLabelFormat = @"%1.1f"; 40 | [chart setXLabels:@[@"SEP 1",@"SEP 2",@"SEP 3",@"SEP 4",@"SEP 5",@"SEP 6",@"SEP 7"]]; 41 | chart.showCoordinateAxis = YES; 42 | 43 | //Use yFixedValueMax and yFixedValueMin to Fix the Max and Min Y Value 44 | //Only if you needed 45 | chart.yFixedValueMax = 300.0; 46 | chart.yFixedValueMin = 0.0; 47 | 48 | [chart setYLabels:@[ 49 | @"0", 50 | @"50", 51 | @"100", 52 | @"150", 53 | @"200", 54 | @"250", 55 | @"300", 56 | ] 57 | ]; 58 | 59 | chart.yLabelFont = [UIFont systemFontOfSize:6.f]; 60 | chart.xLabelFont = [UIFont systemFontOfSize:6.f]; 61 | chart.xLabelWidth = 10.f; 62 | chart.yLabelColor = NKGreen; 63 | chart.xLabelColor = NKGreen; 64 | 65 | chart.axisColor = NKLightGrey; 66 | chart.axisWidth = 1.f; 67 | 68 | chart.xUnit = @"Day"; 69 | chart.yUnit = @"Min"; 70 | 71 | // Line Chart #1 72 | NSArray * data01Array = @[@60.1, @160.1, @126.4, @0.0, @186.2, @127.2, @176.2]; 73 | NKLineChartData *data01 = [NKLineChartData new]; 74 | data01.color = NKGreen; 75 | data01.alpha = 0.9f; 76 | data01.itemCount = data01Array.count; 77 | data01.inflexionPointStyle = NKLineChartPointStyleTriangle; 78 | data01.getData = ^(NSUInteger index) { 79 | CGFloat yValue = [data01Array[index] floatValue]; 80 | return [NKLineChartDataItem dataItemWithY:yValue]; 81 | }; 82 | 83 | // Line Chart #2 84 | NSArray * data02Array = @[@0.0, @180.1, @26.4, @202.2, @126.2, @167.2, @276.2]; 85 | NKLineChartData *data02 = [NKLineChartData new]; 86 | data02.color = NKTwitterColor; 87 | data02.alpha = 0.5f; 88 | data02.itemCount = data02Array.count; 89 | data02.inflexionPointStyle = NKLineChartPointStyleCircle; 90 | data02.getData = ^(NSUInteger index) { 91 | CGFloat yValue = [data02Array[index] floatValue]; 92 | return [NKLineChartDataItem dataItemWithY:yValue]; 93 | }; 94 | 95 | 96 | chart.chartData = @[data01,data02]; 97 | 98 | image = [chart drawImage]; 99 | 100 | 101 | } else if([self.chartType isEqualToString: @"Bar Chart"]) 102 | { 103 | NKBarChart *chart = [[NKBarChart alloc] initWithFrame:frame]; 104 | chart.yLabelFormatter = ^(CGFloat yValue){ 105 | CGFloat yValueParsed = yValue; 106 | NSString * labelText = [NSString stringWithFormat:@"%0.f",yValueParsed]; 107 | return labelText; 108 | }; 109 | chart.labelMarginTop = 5.0; 110 | chart.showChartBorder = YES; 111 | [chart setXLabels:@[@"2",@"3",@"4",@"5",@"2",@"3",@"4",@"5"]]; 112 | // self.barChart.yLabels = @[@-10,@0,@10]; 113 | [chart setYValues:@[@10.82,@1.88,@6.96,@33.93,@10.82,@1.88,@6.96,@33.93]]; 114 | [chart setStrokeColors:@[NKGreen,NKGreen,NKRed,NKGreen,NKGreen,NKGreen,NKRed,NKGreen]]; 115 | 116 | image = [chart drawImage]; 117 | 118 | } else if ([self.chartType isEqualToString: @"Pie Chart"]) 119 | { 120 | NSArray *items = @[[NKPieChartDataItem dataItemWithValue:10 color:NKLightGreen], 121 | [NKPieChartDataItem dataItemWithValue:20 color:NKFreshGreen description:@"WWDC"], 122 | [NKPieChartDataItem dataItemWithValue:40 color:NKDeepGreen description:@"GOOG I/O"], 123 | ]; 124 | 125 | 126 | NKPieChart *chart = [[NKPieChart alloc] initWithFrame:frame items:items]; 127 | chart.descriptionTextColor = [UIColor whiteColor]; 128 | chart.descriptionTextFont = [UIFont systemFontOfSize:12.0]; 129 | chart.showAbsoluteValues = NO; 130 | chart.showOnlyValues = NO; 131 | 132 | image = [chart drawImage]; 133 | 134 | } else if ([self.chartType isEqualToString: @"Circle Chart"]) 135 | { 136 | UIColor *shadowColor = [UIColor colorWithRed:225.0 / 255.0 green:225.0 / 255.0 blue:225.0 / 255.0 alpha:0.5f]; 137 | NKCircleChart *chart = [[NKCircleChart alloc] initWithFrame:frame total:@100 current:@60 clockwise:YES shadow:YES shadowColor:shadowColor displayCountingLabel:YES overrideLineWidth:@5]; 138 | chart.strokeColor = NKGreen; 139 | chart.strokeColorGradientStart = NKLightGreen; 140 | image = [chart drawImage]; 141 | 142 | } else if ([self.chartType isEqualToString: @"Radar Chart"]) 143 | { 144 | NSArray *items = @[[NKRadarChartDataItem dataItemWithValue:3 description:@"Art"], 145 | [NKRadarChartDataItem dataItemWithValue:2 description:@"Math"], 146 | [NKRadarChartDataItem dataItemWithValue:8 description:@"Sports"], 147 | [NKRadarChartDataItem dataItemWithValue:5 description:@"Liter"], 148 | [NKRadarChartDataItem dataItemWithValue:4 description:@"Other"], 149 | ]; 150 | NKRadarChart *chart = [[NKRadarChart alloc] initWithFrame:frame items:items valueDivider:1]; 151 | 152 | image = [chart drawImage]; 153 | 154 | } else 155 | { 156 | NSLog(@"don't support now."); 157 | } 158 | 159 | [self.chartImage setImage:image]; 160 | } 161 | 162 | - (void)didDeactivate { 163 | // This method is called when watch view controller is no longer visible 164 | [super didDeactivate]; 165 | } 166 | 167 | @end 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /WatchChart Extension/ChartTableRowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChartTableRowController.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ChartTableRowController : NSObject 13 | 14 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *chartType; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /WatchChart Extension/ChartTableRowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChartTableRowController.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "ChartTableRowController.h" 10 | 11 | @implementation ChartTableRowController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WatchChart Extension/ExtensionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionDelegate.h 3 | // WatchChart Extension 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ExtensionDelegate : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /WatchChart Extension/ExtensionDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionDelegate.m 3 | // WatchChart Extension 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "ExtensionDelegate.h" 10 | 11 | @implementation ExtensionDelegate 12 | 13 | - (void)applicationDidFinishLaunching { 14 | // Perform any final initialization of your application. 15 | } 16 | 17 | - (void)applicationDidBecomeActive { 18 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 19 | } 20 | 21 | - (void)applicationWillResignActive { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, etc. 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /WatchChart Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | WatchChart Extension 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSExtension 26 | 27 | NSExtensionAttributes 28 | 29 | WKAppBundleIdentifier 30 | watch.develop.NKWatchChartDemo.watchkitapp 31 | 32 | NSExtensionPointIdentifier 33 | com.apple.watchkit 34 | 35 | RemoteInterfacePrincipalClass 36 | InterfaceController 37 | WKExtensionDelegateClassName 38 | ExtensionDelegate 39 | 40 | 41 | -------------------------------------------------------------------------------- /WatchChart Extension/InterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.h 3 | // WatchChart Extension 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface InterfaceController : WKInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /WatchChart Extension/InterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.m 3 | // WatchChart Extension 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "InterfaceController.h" 10 | #import "ChartTableRowController.h" 11 | 12 | @interface InterfaceController() 13 | 14 | @property (weak, nonatomic) IBOutlet WKInterfaceTable *chartTable; 15 | @property (strong, nonatomic) NSArray *chartTypes; 16 | 17 | @end 18 | 19 | 20 | @implementation InterfaceController 21 | 22 | - (void)awakeWithContext:(id)context { 23 | [super awakeWithContext:context]; 24 | 25 | // Configure interface objects here. 26 | } 27 | 28 | - (void)willActivate { 29 | // This method is called when watch view controller is about to be visible to user 30 | [super willActivate]; 31 | 32 | self.chartTypes = @[@"Line Chart", @"Bar Chart", @"Pie Chart", @"Circle Chart", @"Radar Chart"]; 33 | [self.chartTable setNumberOfRows:self.chartTypes.count withRowType:@"ChartTableRowController"]; 34 | 35 | [self.chartTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 36 | 37 | ChartTableRowController* row = [self.chartTable rowControllerAtIndex:idx]; 38 | 39 | [row.chartType setText: (NSString*)obj]; 40 | 41 | }]; 42 | } 43 | 44 | - (void)didDeactivate { 45 | // This method is called when watch view controller is no longer visible 46 | [super didDeactivate]; 47 | } 48 | 49 | - (instancetype)contextForSegueWithIdentifier:(NSString *)segueIdentifier inTable:(WKInterfaceTable *)table rowIndex:(NSInteger)rowIndex 50 | { 51 | return [self.chartTypes objectAtIndex:rowIndex]; 52 | } 53 | 54 | @end 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKBarChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKBarChart.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | #define kXLabelMargin 8 14 | #define kYLabelMargin 8 15 | #define kYLabelHeight 8 16 | #define kXLabelHeight 8 17 | 18 | typedef NSString *(^NKYLabelFormatter)(CGFloat yLabelValue); 19 | 20 | @interface NKBarChart : NSObject 21 | 22 | - (id)initWithFrame:(CGRect)frame; 23 | - (UIImage *)drawImage; 24 | 25 | @property (nonatomic) BOOL showLabel; 26 | @property (nonatomic) UIColor *labelTextColor; 27 | @property (nonatomic) UIFont *labelFont; 28 | @property (nonatomic) CGFloat labelMarginTop; 29 | 30 | @property (nonatomic) NSArray *xLabels; 31 | @property (nonatomic) NSInteger xLabelSkip; 32 | 33 | @property (nonatomic) NSArray *yLabels; 34 | @property (nonatomic) NSArray *yValues; 35 | /** How many labels on the y-axis to skip in between displaying labels. */ 36 | @property (nonatomic) NSInteger yLabelSum; 37 | /** Formats the ylabel text. */ 38 | @property (copy) NKYLabelFormatter yLabelFormatter; 39 | 40 | /** Prefix to y label values, none if unset. */ 41 | @property (nonatomic) NSString *yLabelPrefix; 42 | 43 | /** Suffix to y label values, none if unset. */ 44 | @property (nonatomic) NSString *yLabelSuffix; 45 | 46 | /** The maximum for the range of values to display on the y-axis. */ 47 | @property (nonatomic) CGFloat yMaxValue; 48 | 49 | /** The minimum for the range of values to display on the y-axis. */ 50 | @property (nonatomic) CGFloat yMinValue; 51 | 52 | /** Changes chart margin. */ 53 | @property (nonatomic) CGFloat yChartLabelWidth; 54 | 55 | @property (nonatomic) UIColor *chartBackgroundColor; 56 | @property (nonatomic) UIColor *barBackgroundColor; 57 | @property (nonatomic) UIColor *barColor; 58 | 59 | @property (nonatomic) CGFloat chartMargin; 60 | 61 | /** Corner radius for all bars in the chart. */ 62 | @property (nonatomic) CGFloat barRadius; 63 | 64 | /** Width of all bars in the chart. */ 65 | @property (nonatomic) CGFloat barWidth; 66 | 67 | /** Controls whether the chart border line should be displayed. */ 68 | @property (nonatomic) BOOL showChartBorder; 69 | 70 | @property (nonatomic) UIColor *chartBorderColor; 71 | 72 | @property (nonatomic) UIColor *strokeColor; 73 | @property (nonatomic) NSArray *strokeColors; 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKBarChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKBarChart.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "NKBarChart.h" 10 | #import "NKColor.h" 11 | 12 | @interface NKBarChart () 13 | 14 | @property (nonatomic) CGRect frame; 15 | 16 | - (UIColor *)barColorAtIndex:(NSUInteger)index; 17 | 18 | @property (nonatomic) CGFloat xLabelWidth; 19 | @property (nonatomic) float yValueMax; 20 | 21 | @end 22 | 23 | @implementation NKBarChart 24 | 25 | - (id)initWithFrame:(CGRect)frame 26 | { 27 | self = [super init]; 28 | 29 | if (self) { 30 | _frame = frame; 31 | [self setupDefaultValues]; 32 | 33 | } 34 | 35 | return self; 36 | } 37 | 38 | - (void)setupDefaultValues 39 | { 40 | _showLabel = YES; 41 | _labelTextColor = NKGreen; 42 | _labelFont = [UIFont systemFontOfSize:8.0f]; 43 | _chartMargin = 12.0; 44 | _labelMarginTop = 0; 45 | _yLabelSum = 4; 46 | _xLabelSkip = 1; 47 | 48 | _yLabelFormatter = ^(CGFloat yValue){ 49 | return [NSString stringWithFormat:@"%1.f",yValue]; 50 | }; 51 | 52 | _yChartLabelWidth = 10; 53 | _barRadius = 2.0; 54 | _showChartBorder = NO; 55 | _chartBorderColor = NKLightGrey; 56 | _barBackgroundColor = NKLightGrey; 57 | 58 | } 59 | 60 | - (void)drawXLabels 61 | { 62 | _xLabelWidth = (_frame.size.width - _chartMargin * 2) / [_xLabels count]; 63 | int labelAddCount = 0; 64 | for (int index = 0; index < _xLabels.count; index++) { 65 | labelAddCount += 1; 66 | 67 | if (labelAddCount == _xLabelSkip) { 68 | NSString *labelText = [_xLabels[index] description]; 69 | 70 | NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 71 | priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 72 | priceParagraphStyle.alignment = NSTextAlignmentLeft; 73 | 74 | NSMutableDictionary *attributesDictionary = [NSMutableDictionary dictionary]; 75 | [attributesDictionary setObject:_labelFont forKey:NSFontAttributeName]; 76 | [attributesDictionary setObject:_labelTextColor forKey:NSForegroundColorAttributeName]; 77 | [attributesDictionary setObject:priceParagraphStyle forKey:NSParagraphStyleAttributeName]; 78 | 79 | CGFloat labelXPosition = (index * _xLabelWidth + _chartMargin + _xLabelWidth /2.0 ); 80 | 81 | CGRect labelRect = CGRectMake(labelXPosition, 82 | _frame.size.height - kXLabelHeight - _chartMargin + _labelMarginTop, 83 | _xLabelWidth, 84 | kXLabelHeight); 85 | [labelText drawInRect:labelRect withAttributes:attributesDictionary]; 86 | 87 | labelAddCount = 0; 88 | 89 | } 90 | } 91 | 92 | } 93 | 94 | - (void)drawYLabels 95 | { 96 | [self processYMaxValue]; 97 | 98 | float sectionHeight = (_frame.size.height - _chartMargin * 2 - kXLabelHeight) / _yLabelSum; 99 | for (int i = 0; i <= _yLabelSum; i++) 100 | { 101 | 102 | CGRect frame = (CGRect){0, sectionHeight * i + _chartMargin - kYLabelHeight/2.0, _yChartLabelWidth, kYLabelHeight}; 103 | 104 | NSMutableString *yLabelText; 105 | if (_yLabels) 106 | { 107 | float yAsixValue = [_yLabels[_yLabels.count - i - 1] floatValue]; 108 | yLabelText = [_yLabelFormatter(yAsixValue) mutableCopy]; 109 | } else 110 | { 111 | yLabelText = [_yLabelFormatter((float)_yValueMax * ( (_yLabelSum - i) / (float)_yLabelSum )) mutableCopy]; 112 | } 113 | 114 | if (_yLabelPrefix) 115 | { 116 | yLabelText = [NSMutableString stringWithFormat:@"%@%@", _yLabelPrefix, yLabelText]; 117 | } 118 | if (_yLabelSuffix) 119 | { 120 | yLabelText = [NSMutableString stringWithFormat:@"%@%@", yLabelText, _yLabelSuffix]; 121 | } 122 | 123 | NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 124 | priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 125 | priceParagraphStyle.alignment = NSTextAlignmentRight; 126 | 127 | NSMutableDictionary *attributesDictionary = [NSMutableDictionary dictionary]; 128 | [attributesDictionary setObject:_labelFont forKey:NSFontAttributeName]; 129 | [attributesDictionary setObject:_labelTextColor forKey:NSForegroundColorAttributeName]; 130 | [attributesDictionary setObject:priceParagraphStyle forKey:NSParagraphStyleAttributeName]; 131 | 132 | [yLabelText drawInRect:frame withAttributes:attributesDictionary]; 133 | 134 | } 135 | 136 | } 137 | 138 | - (void)drawBorderLines 139 | { 140 | //Add chart border bottom line 141 | UIBezierPath *bottomLineLine = [UIBezierPath bezierPath]; 142 | [bottomLineLine moveToPoint:CGPointMake(_chartMargin, _frame.size.height - kXLabelHeight - _chartMargin)]; 143 | [bottomLineLine addLineToPoint:CGPointMake(_frame.size.width - _chartMargin, _frame.size.height - kXLabelHeight - _chartMargin)]; 144 | [bottomLineLine setLineWidth:1.0]; 145 | [bottomLineLine setLineCapStyle:kCGLineCapSquare]; 146 | [_chartBorderColor setStroke]; 147 | [bottomLineLine stroke]; 148 | 149 | //Add left Chart Line 150 | UIBezierPath *leftLine = [UIBezierPath bezierPath]; 151 | [leftLine moveToPoint:CGPointMake(_chartMargin, self.frame.size.height - kXLabelHeight - _chartMargin)]; 152 | [leftLine addLineToPoint:CGPointMake(_chartMargin, _chartMargin)]; 153 | [leftLine setLineWidth:1.0]; 154 | [leftLine setLineCapStyle:kCGLineCapSquare]; 155 | [_chartBorderColor setStroke]; 156 | [leftLine stroke]; 157 | } 158 | 159 | - (UIImage *)drawImage 160 | { 161 | CGFloat scale = [WKInterfaceDevice currentDevice].screenScale; 162 | UIGraphicsBeginImageContextWithOptions(_frame.size, false, scale); 163 | 164 | if (_chartBackgroundColor) { 165 | UIBezierPath *chartRect = [UIBezierPath bezierPathWithRect:_frame]; 166 | [_chartBackgroundColor setFill]; 167 | [chartRect fill]; 168 | } 169 | 170 | if (_showLabel) 171 | { 172 | 173 | [self drawXLabels]; 174 | [self drawYLabels]; 175 | 176 | } else { 177 | [self processYMaxValue]; 178 | } 179 | 180 | if (_showChartBorder) 181 | { 182 | [self drawBorderLines]; 183 | } 184 | // draw bars 185 | CGFloat chartCavanHeight = self.frame.size.height - _chartMargin * 2 - kXLabelHeight; 186 | NSInteger index = 0; 187 | 188 | for (NSNumber *valueString in _yValues) 189 | { 190 | CGFloat barWidth; 191 | CGFloat barHeight; 192 | CGFloat barXPosition; 193 | CGFloat barYPosition; 194 | 195 | UIColor *barBackgroundColor; 196 | UIColor *barColor; 197 | 198 | if (_barWidth) { 199 | barWidth = _barWidth; 200 | barXPosition = index * _xLabelWidth + _chartMargin + _xLabelWidth /2.0 - _barWidth /2.0; 201 | }else{ 202 | barXPosition = index * _xLabelWidth + _chartMargin + _xLabelWidth * 0.25; 203 | if (_showLabel) { 204 | barWidth = _xLabelWidth * 0.5; 205 | 206 | } 207 | else { 208 | barWidth = _xLabelWidth * 0.6; 209 | 210 | } 211 | }// if _barWidth 212 | 213 | barYPosition = _frame.size.height - chartCavanHeight - kXLabelHeight - _chartMargin; 214 | barHeight = chartCavanHeight; 215 | 216 | CGRect barBackgroundRect = CGRectMake(barXPosition, barYPosition, barWidth, barHeight); 217 | barBackgroundColor = _barBackgroundColor; 218 | UIBezierPath* barBackgroundRectPath = [UIBezierPath 219 | bezierPathWithRoundedRect: barBackgroundRect 220 | cornerRadius: 2]; 221 | [barBackgroundColor setFill]; 222 | [barBackgroundRectPath fill]; 223 | 224 | if (self.strokeColor) { 225 | barColor = self.strokeColor; 226 | }else{ 227 | barColor = [self barColorAtIndex:index]; 228 | } 229 | 230 | float value = [valueString floatValue]; 231 | float grade =fabsf((float)value / (float)_yValueMax); 232 | if (isnan(grade)) { 233 | grade = 0; 234 | } 235 | CGRect barRect = CGRectMake(barXPosition, barYPosition + (1-grade)*barHeight, barWidth, grade*barHeight); 236 | UIBezierPath* barRectPath = [UIBezierPath 237 | bezierPathWithRoundedRect: barRect 238 | cornerRadius: 2]; 239 | [barColor setFill]; 240 | [barRectPath fill]; 241 | 242 | index += 1; 243 | 244 | } 245 | 246 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 247 | UIGraphicsEndImageContext(); 248 | return image; 249 | } 250 | 251 | - (void)processYMaxValue { 252 | NSArray *yAxisValues = _yLabels ? _yLabels : _yValues; 253 | _yLabelSum = _yLabels ? _yLabels.count - 1 :_yLabelSum; 254 | if (_yMaxValue) { 255 | _yValueMax = _yMaxValue; 256 | } else { 257 | [self getYValueMax:yAxisValues]; 258 | } 259 | 260 | if (_yLabelSum==4) { 261 | _yLabelSum = yAxisValues.count; 262 | (_yLabelSum % 2 == 0) ? _yLabelSum : _yLabelSum++; 263 | } 264 | } 265 | 266 | - (void)getYValueMax:(NSArray *)yLabels 267 | { 268 | CGFloat max = [[yLabels valueForKeyPath:@"@max.floatValue"] floatValue]; 269 | 270 | //ensure max is even 271 | _yValueMax = max ; 272 | 273 | if (_yValueMax == 0) { 274 | _yValueMax = _yMinValue; 275 | } 276 | } 277 | 278 | 279 | #pragma mark - Class extension methods 280 | 281 | - (UIColor *)barColorAtIndex:(NSUInteger)index 282 | { 283 | if ([self.strokeColors count] == [self.yValues count]) { 284 | return self.strokeColors[index]; 285 | } 286 | else { 287 | return self.strokeColor; 288 | } 289 | } 290 | 291 | @end 292 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKCircleChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKCircleChart.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef NS_ENUM (NSUInteger, NKChartFormatType) { 13 | NKChartFormatTypePercent, 14 | NKChartFormatTypeDollar, 15 | NKChartFormatTypeNone 16 | }; 17 | 18 | #define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI) 19 | 20 | @interface NKCircleChart : NSObject 21 | 22 | - (id)initWithFrame:(CGRect)frame 23 | total:(NSNumber *)total 24 | current:(NSNumber *)current 25 | clockwise:(BOOL)clockwise; 26 | 27 | - (id)initWithFrame:(CGRect)frame 28 | total:(NSNumber *)total 29 | current:(NSNumber *)current 30 | clockwise:(BOOL)clockwise 31 | shadow:(BOOL)hasBackgroundShadow 32 | shadowColor:(UIColor *)backgroundShadowColor; 33 | 34 | - (id)initWithFrame:(CGRect)frame 35 | total:(NSNumber *)total 36 | current:(NSNumber *)current 37 | clockwise:(BOOL)clockwise 38 | shadow:(BOOL)hasBackgroundShadow 39 | shadowColor:(UIColor *)backgroundShadowColor 40 | displayCountingLabel:(BOOL)displayCountingLabel; 41 | 42 | - (id)initWithFrame:(CGRect)frame 43 | total:(NSNumber *)total 44 | current:(NSNumber *)current 45 | clockwise:(BOOL)clockwise 46 | shadow:(BOOL)hasBackgroundShadow 47 | shadowColor:(UIColor *)backgroundShadowColor 48 | displayCountingLabel:(BOOL)displayCountingLabel 49 | overrideLineWidth:(NSNumber *)overrideLineWidth; 50 | 51 | @property (nonatomic) UIColor *chartBackgroundColor; 52 | @property (nonatomic) UIColor *strokeColor; 53 | @property (nonatomic) UIColor *strokeColorGradientStart; 54 | @property (nonatomic) NSNumber *total; 55 | @property (nonatomic) NSNumber *current; 56 | @property (nonatomic) NSNumber *lineWidth; 57 | @property (nonatomic) NKChartFormatType chartType; 58 | @property (nonatomic) BOOL clockwise; 59 | @property (nonatomic) BOOL hasBackgroundShadow; 60 | @property (nonatomic) UIColor *backgroundShadowColor; 61 | @property (nonatomic) BOOL displayCountingLabel; 62 | 63 | - (UIImage *)drawImage; 64 | 65 | @end 66 | 67 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKCircleChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKCircleChart.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NKCircleChart.h" 11 | #import "NKColor.h" 12 | 13 | @interface NKCircleChart () 14 | 15 | @property (nonatomic) CGRect frame; 16 | 17 | @end 18 | 19 | @implementation NKCircleChart 20 | 21 | - (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise { 22 | 23 | return [self initWithFrame:frame 24 | total:total 25 | current:current 26 | clockwise:clockwise 27 | shadow:NO 28 | shadowColor:[UIColor clearColor] 29 | displayCountingLabel:YES 30 | overrideLineWidth:@8.0f]; 31 | 32 | } 33 | 34 | - (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor { 35 | 36 | return [self initWithFrame:frame 37 | total:total 38 | current:current 39 | clockwise:clockwise 40 | shadow:shadow 41 | shadowColor:backgroundShadowColor 42 | displayCountingLabel:YES 43 | overrideLineWidth:@8.0f]; 44 | 45 | } 46 | 47 | - (id)initWithFrame:(CGRect)frame total:(NSNumber *)total current:(NSNumber *)current clockwise:(BOOL)clockwise shadow:(BOOL)hasBackgroundShadow shadowColor:(UIColor *)backgroundShadowColor displayCountingLabel:(BOOL)displayCountingLabel { 48 | 49 | return [self initWithFrame:frame 50 | total:total 51 | current:current 52 | clockwise:clockwise 53 | shadow:shadow 54 | shadowColor:NKGreen 55 | displayCountingLabel:displayCountingLabel 56 | overrideLineWidth:@8.0f]; 57 | 58 | } 59 | 60 | - (id)initWithFrame:(CGRect)frame 61 | total:(NSNumber *)total 62 | current:(NSNumber *)current 63 | clockwise:(BOOL)clockwise 64 | shadow:(BOOL)hasBackgroundShadow 65 | shadowColor:(UIColor *)backgroundShadowColor 66 | displayCountingLabel:(BOOL)displayCountingLabel 67 | overrideLineWidth:(NSNumber *)overrideLineWidth 68 | { 69 | self = [super init]; 70 | 71 | if (self) { 72 | _frame = frame; 73 | _total = total; 74 | _current = current; 75 | _strokeColor = NKFreshGreen; 76 | _chartType = NKChartFormatTypePercent; 77 | _displayCountingLabel = displayCountingLabel; 78 | _clockwise = clockwise; 79 | _lineWidth = overrideLineWidth; 80 | _hasBackgroundShadow = hasBackgroundShadow; 81 | _backgroundShadowColor = backgroundShadowColor; 82 | 83 | } 84 | 85 | return self; 86 | } 87 | 88 | - (UIImage *)drawImage 89 | { 90 | 91 | CGFloat startAngle = 0.f; 92 | CGFloat endAngle = 0.f; 93 | 94 | if (_clockwise) 95 | { 96 | 97 | startAngle = -90.0f; 98 | endAngle = 360.0f*([_current floatValue] / [_total floatValue]) + startAngle + 0.01f; 99 | 100 | } else 101 | { 102 | startAngle = 270.0f; 103 | endAngle = startAngle + 0.01f - 360.0f*([_current floatValue] / [_total floatValue]) ; 104 | 105 | } 106 | 107 | CGFloat scale = [WKInterfaceDevice currentDevice].screenScale; 108 | 109 | UIGraphicsBeginImageContextWithOptions(_frame.size, false, scale); 110 | 111 | if (_chartBackgroundColor) { 112 | UIBezierPath *chartRect = [UIBezierPath bezierPathWithRect:_frame]; 113 | [_chartBackgroundColor setFill]; 114 | [chartRect fill]; 115 | } 116 | 117 | CGPoint arcCenter = CGPointMake(_frame.size.width/2.0f, _frame.size.height/2.0f); 118 | CGFloat radius = (_frame.size.height * 0.4) - ([_lineWidth floatValue]/2.0f); 119 | 120 | if (_hasBackgroundShadow) 121 | { 122 | UIBezierPath *circleBackground = [UIBezierPath bezierPathWithArcCenter: arcCenter radius:radius startAngle:0.0 endAngle:M_PI*2 clockwise:YES]; 123 | circleBackground.lineWidth = [_lineWidth floatValue]; 124 | if (_backgroundShadowColor) { 125 | [_backgroundShadowColor setStroke]; 126 | } else { 127 | [[UIColor clearColor] setStroke]; 128 | } 129 | [circleBackground stroke]; 130 | } 131 | 132 | CGContextRef context = UIGraphicsGetCurrentContext(); 133 | 134 | CGMutablePathRef arc = CGPathCreateMutable(); 135 | CGPathAddArc(arc, NULL, 136 | arcCenter.x, arcCenter.y, 137 | radius, 138 | DEGREES_TO_RADIANS(startAngle), 139 | DEGREES_TO_RADIANS(endAngle), 140 | !_clockwise);// core graphic's coordination is reversed to normal 141 | 142 | CGPathRef strokedArc = 143 | CGPathCreateCopyByStrokingPath(arc, NULL, 144 | [_lineWidth floatValue], 145 | kCGLineCapRound, 146 | kCGLineJoinRound, // the default 147 | 10); // 10 is default miter limit 148 | 149 | CGContextAddPath(context, strokedArc); 150 | CGContextDrawPath(context, kCGPathFillStroke); 151 | 152 | // Adding shadows 153 | CGColorRef shadowColor = [UIColor colorWithWhite:0.0 alpha:0.75].CGColor; 154 | CGContextSaveGState(context); 155 | CGContextSetShadowWithColor(context, 156 | CGSizeMake(0, 2), // Offset 157 | 3.0, // Radius 158 | shadowColor); 159 | CGContextFillPath(context); 160 | CGContextRestoreGState(context); 161 | 162 | // Note that filling the path "consumes it" so we add it again 163 | CGContextAddPath(context, strokedArc); 164 | CGContextStrokePath(context); 165 | 166 | // Drawing the gradient 167 | if (_strokeColorGradientStart) 168 | { 169 | NSArray *colors = @[ 170 | (__bridge id)_strokeColorGradientStart.CGColor, 171 | (__bridge id)_strokeColor.CGColor 172 | ]; 173 | CGFloat locations[] = {0.0, [_current floatValue] / [_total floatValue]}; 174 | 175 | CGGradientRef gradient = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), (__bridge CFArrayRef)colors,locations); 176 | 177 | CGContextSaveGState(context); 178 | CGContextAddPath(context, strokedArc); 179 | CGContextClip(context); 180 | 181 | CGRect boundingBox = CGPathGetBoundingBox(strokedArc); 182 | CGPoint gradientStart = CGPointMake(0, CGRectGetMinY(boundingBox)); 183 | CGPoint gradientEnd = CGPointMake(0, CGRectGetMaxY(boundingBox)); 184 | 185 | CGContextDrawLinearGradient(context, gradient, gradientStart, gradientEnd, 0); 186 | CGGradientRelease(gradient), gradient = NULL; 187 | CGContextRestoreGState(context); 188 | } 189 | //draw text 190 | if (_displayCountingLabel) 191 | { 192 | NSString *format; 193 | switch (_chartType) { 194 | case NKChartFormatTypePercent: 195 | format = @"%d%%"; 196 | break; 197 | case NKChartFormatTypeDollar: 198 | format = @"$%d"; 199 | break; 200 | case NKChartFormatTypeNone: 201 | default: 202 | format = @"%d"; 203 | break; 204 | } 205 | 206 | NSString *text; 207 | 208 | if([format rangeOfString:@"%(.*)d" options:NSRegularExpressionSearch].location != NSNotFound || [format rangeOfString:@"%(.*)i"].location != NSNotFound ) 209 | { 210 | text = [NSString stringWithFormat:format,(int)[_current floatValue]]; 211 | } 212 | else 213 | { 214 | text = [NSString stringWithFormat:format,[_current floatValue]]; 215 | } 216 | 217 | CGRect textRect = CGRectMake(arcCenter.x-20.0, arcCenter.y-10.0, 40.f, 20.f); 218 | [text drawInRect:textRect 219 | withAttributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:15], NSForegroundColorAttributeName:NKGreen}]; 220 | 221 | } 222 | 223 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 224 | UIGraphicsEndImageContext(); 225 | return image; 226 | } 227 | 228 | - (void)drawTextInContext:(CGContextRef )ctx text:(NSString *)text inRect:(CGRect)rect font:(UIFont *)font 229 | { 230 | NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 231 | priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 232 | priceParagraphStyle.alignment = NSTextAlignmentLeft; 233 | 234 | [text drawInRect:rect 235 | withAttributes:@{ NSParagraphStyleAttributeName:priceParagraphStyle, NSFontAttributeName:font, NSForegroundColorAttributeName:NKGreen}]; 236 | } 237 | 238 | 239 | @end 240 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKColor.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKColor.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NKColor : NSObject 13 | 14 | #define NKGrey [UIColor colorWithRed:246.0 / 255.0 green:246.0 / 255.0 blue:246.0 / 255.0 alpha:1.0f] 15 | #define NKLightBlue [UIColor colorWithRed:94.0 / 255.0 green:147.0 / 255.0 blue:196.0 / 255.0 alpha:1.0f] 16 | #define NKGreen [UIColor colorWithRed:77.0 / 255.0 green:186.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f] 17 | #define NKTitleColor [UIColor colorWithRed:0.0 / 255.0 green:189.0 / 255.0 blue:113.0 / 255.0 alpha:1.0f] 18 | #define NKButtonGrey [UIColor colorWithRed:141.0 / 255.0 green:141.0 / 255.0 blue:141.0 / 255.0 alpha:1.0f] 19 | #define NKLightGreen [UIColor colorWithRed:77.0 / 255.0 green:216.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f] 20 | #define NKFreshGreen [UIColor colorWithRed:77.0 / 255.0 green:196.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f] 21 | #define NKDeepGreen [UIColor colorWithRed:77.0 / 255.0 green:176.0 / 255.0 blue:122.0 / 255.0 alpha:1.0f] 22 | #define NKRed [UIColor colorWithRed:245.0 / 255.0 green:94.0 / 255.0 blue:78.0 / 255.0 alpha:1.0f] 23 | #define NKMauve [UIColor colorWithRed:88.0 / 255.0 green:75.0 / 255.0 blue:103.0 / 255.0 alpha:1.0f] 24 | #define NKBrown [UIColor colorWithRed:119.0 / 255.0 green:107.0 / 255.0 blue:95.0 / 255.0 alpha:1.0f] 25 | #define NKBlue [UIColor colorWithRed:82.0 / 255.0 green:116.0 / 255.0 blue:188.0 / 255.0 alpha:1.0f] 26 | #define NKDarkBlue [UIColor colorWithRed:121.0 / 255.0 green:134.0 / 255.0 blue:142.0 / 255.0 alpha:1.0f] 27 | #define NKYellow [UIColor colorWithRed:242.0 / 255.0 green:197.0 / 255.0 blue:117.0 / 255.0 alpha:1.0f] 28 | #define NKWhite [UIColor colorWithRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:1.0f] 29 | #define NKDeepGrey [UIColor colorWithRed:99.0 / 255.0 green:99.0 / 255.0 blue:99.0 / 255.0 alpha:1.0f] 30 | #define NKPinkGrey [UIColor colorWithRed:200.0 / 255.0 green:193.0 / 255.0 blue:193.0 / 255.0 alpha:1.0f] 31 | #define NKHealYellow [UIColor colorWithRed:245.0 / 255.0 green:242.0 / 255.0 blue:238.0 / 255.0 alpha:1.0f] 32 | #define NKLightGrey [UIColor colorWithRed:225.0 / 255.0 green:225.0 / 255.0 blue:225.0 / 255.0 alpha:1.0f] 33 | #define NKCleanGrey [UIColor colorWithRed:251.0 / 255.0 green:251.0 / 255.0 blue:251.0 / 255.0 alpha:1.0f] 34 | #define NKLightYellow [UIColor colorWithRed:241.0 / 255.0 green:240.0 / 255.0 blue:240.0 / 255.0 alpha:1.0f] 35 | #define NKDarkYellow [UIColor colorWithRed:152.0 / 255.0 green:150.0 / 255.0 blue:159.0 / 255.0 alpha:1.0f] 36 | #define NKPinkDark [UIColor colorWithRed:170.0 / 255.0 green:165.0 / 255.0 blue:165.0 / 255.0 alpha:1.0f] 37 | #define NKCloudWhite [UIColor colorWithRed:244.0 / 255.0 green:244.0 / 255.0 blue:244.0 / 255.0 alpha:1.0f] 38 | #define NKBlack [UIColor colorWithRed:45.0 / 255.0 green:45.0 / 255.0 blue:45.0 / 255.0 alpha:1.0f] 39 | #define NKStarYellow [UIColor colorWithRed:252.0 / 255.0 green:223.0 / 255.0 blue:101.0 / 255.0 alpha:1.0f] 40 | #define NKTwitterColor [UIColor colorWithRed:0.0 / 255.0 green:171.0 / 255.0 blue:243.0 / 255.0 alpha:1.0] 41 | #define NKWeiboColor [UIColor colorWithRed:250.0 / 255.0 green:0.0 / 255.0 blue:33.0 / 255.0 alpha:1.0] 42 | #define NKiOSGreenColor [UIColor colorWithRed:98.0 / 255.0 green:247.0 / 255.0 blue:77.0 / 255.0 alpha:1.0] 43 | 44 | - (UIImage *)imageFromColor:(UIColor *)color; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKColor.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKColor.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "NKColor.h" 10 | 11 | @implementation NKColor 12 | 13 | - (UIImage *)imageFromColor:(UIColor *)color 14 | { 15 | CGRect rect = CGRectMake(0, 0, 1, 1); 16 | 17 | UIGraphicsBeginImageContext(rect.size); 18 | CGContextRef context = UIGraphicsGetCurrentContext(); 19 | CGContextSetFillColorWithColor(context, [color CGColor]); 20 | CGContextFillRect(context, rect); 21 | UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 22 | UIGraphicsEndImageContext(); 23 | 24 | return img; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKLineChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKLineChart.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NKLineChart : NSObject 13 | 14 | // Background color of the chart 15 | @property (nonatomic) UIColor *chartBackgroundColor; 16 | // Array of `LineChartData` objects, one for each line. 17 | @property (nonatomic) NSArray *chartData; 18 | @property (nonatomic) CGFloat chartMargin; 19 | 20 | @property (nonatomic) BOOL showLabel; 21 | 22 | @property (nonatomic) NSArray *xLabels; 23 | @property (nonatomic) NSArray *yLabels; 24 | @property (nonatomic) CGFloat xLabelWidth; 25 | @property (nonatomic) UIFont *xLabelFont; 26 | @property (nonatomic) UIColor *xLabelColor; 27 | 28 | @property (nonatomic) UIFont *yLabelFont; 29 | @property (nonatomic) UIColor *yLabelColor; 30 | @property (nonatomic) NSInteger yLabelNum; 31 | @property (nonatomic) CGFloat yLabelHeight; 32 | 33 | @property (nonatomic) CGFloat yValueMax; 34 | @property (nonatomic) CGFloat yValueMin; 35 | @property (nonatomic) CGFloat yFixedValueMax; 36 | @property (nonatomic) CGFloat yFixedValueMin; 37 | 38 | // Controls whether to show the coordinate axis. Default is NO. 39 | @property (nonatomic, getter = isShowCoordinateAxis) BOOL showCoordinateAxis; 40 | @property (nonatomic) UIColor *axisColor; 41 | @property (nonatomic) CGFloat axisWidth; 42 | 43 | @property (nonatomic, strong) NSString *xUnit; 44 | @property (nonatomic, strong) NSString *yUnit; 45 | 46 | // String formatter for float values in y-axis labels. If not set, defaults to @"%1.f" 47 | @property (nonatomic, strong) NSString *yLabelFormat; 48 | 49 | //Block formatter for custom string in y-axis labels. If not set, defaults to yLabelFormat 50 | @property (nonatomic, copy) NSString* (^yLabelBlockFormatter)(CGFloat); 51 | 52 | @property (nonatomic) BOOL thousandsSeparator; 53 | 54 | - (instancetype) initWithFrame:(CGRect)frame; 55 | - (UIImage *)drawImage; 56 | 57 | @end -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKLineChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKLineChart.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NKLineChart.h" 11 | #import "NKLineChartData.h" 12 | #import "NKLineChartDataItem.h" 13 | #import "NKColor.h" 14 | 15 | @interface NKLineChart () 16 | 17 | @property (nonatomic) CGRect frame; 18 | @property (nonatomic) NSMutableArray *chartLineArray; 19 | 20 | // Array of line path, one for each line. 21 | @property (nonatomic) NSMutableArray *chartPath; 22 | 23 | // Array of point path, one for each line 24 | @property (nonatomic) NSMutableArray *pointPath; 25 | 26 | // Array of start and end points of each line path, one for each line 27 | @property (nonatomic) NSMutableArray *endPointsOfPath; 28 | 29 | @property (nonatomic) NSMutableArray *pathPoints; 30 | @property (nonatomic) CGFloat chartCavanHeight; 31 | @property (nonatomic) CGFloat chartCavanWidth; 32 | 33 | // display grade 34 | @property (nonatomic) NSMutableArray *gradeStringPaths; 35 | 36 | @end 37 | 38 | @implementation NKLineChart 39 | 40 | - (instancetype) initWithFrame:(CGRect)frame 41 | { 42 | self = [super init]; 43 | if (self) { 44 | _frame = frame; 45 | [self setupDefaultValues]; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | - (void)setupDefaultValues 52 | { 53 | // Initialization code 54 | _chartLineArray = [NSMutableArray new]; 55 | _showLabel = YES; 56 | _pathPoints = [[NSMutableArray alloc] init]; 57 | _endPointsOfPath = [[NSMutableArray alloc] init]; 58 | 59 | _yFixedValueMin = -FLT_MAX; 60 | _yFixedValueMax = -FLT_MAX; 61 | _yLabelNum = 5.0; 62 | _yLabelHeight = 8; 63 | 64 | _chartMargin = 18; 65 | _chartCavanWidth = _frame.size.width - _chartMargin * 2; 66 | _chartCavanHeight = _frame.size.height - _chartMargin * 2; 67 | 68 | // Coordinate Axis Default Values 69 | _showCoordinateAxis = NO; 70 | _axisColor = [UIColor colorWithRed:0.4f green:0.4f blue:0.4f alpha:1.f]; 71 | _axisWidth = 1.f; 72 | } 73 | 74 | #pragma mark - Draw Chart 75 | 76 | - (UIImage *)drawImage 77 | { 78 | CGFloat scale = [WKInterfaceDevice currentDevice].screenScale; 79 | 80 | UIGraphicsBeginImageContextWithOptions(_frame.size, false, scale); 81 | 82 | if (_chartBackgroundColor) { 83 | UIBezierPath *chartRect = [UIBezierPath bezierPathWithRect:_frame]; 84 | [_chartBackgroundColor setFill]; 85 | [chartRect fill]; 86 | } 87 | 88 | if (self.isShowCoordinateAxis) 89 | { 90 | [self drawCoordinate]; 91 | } 92 | 93 | [self drawYLabels]; 94 | [self drawXLabels]; 95 | [self drawLines]; 96 | 97 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 98 | UIGraphicsEndImageContext(); 99 | return image; 100 | } 101 | 102 | - (void)drawCoordinate 103 | { 104 | CGFloat yAxisOffset = 5.f; 105 | 106 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 107 | CGContextSetLineWidth(ctx, _axisWidth); 108 | CGContextSetStrokeColorWithColor(ctx, [_axisColor CGColor]); 109 | 110 | CGFloat xAxisEndPointX = CGRectGetWidth(_frame) - _chartMargin/2; 111 | CGFloat yAxisCorssPointY = _chartMargin + _chartCavanHeight; 112 | 113 | // draw coordinate axis 114 | CGContextMoveToPoint(ctx, _chartMargin + yAxisOffset, 0); 115 | CGContextAddLineToPoint(ctx, _chartMargin + yAxisOffset, yAxisCorssPointY); 116 | CGContextAddLineToPoint(ctx, xAxisEndPointX, yAxisCorssPointY); 117 | CGContextStrokePath(ctx); 118 | 119 | // draw y axis arrow 120 | CGContextMoveToPoint(ctx, _chartMargin + yAxisOffset - 3, 3); 121 | CGContextAddLineToPoint(ctx, _chartMargin + yAxisOffset, 0); 122 | CGContextAddLineToPoint(ctx, _chartMargin + yAxisOffset + 3, 3); 123 | CGContextStrokePath(ctx); 124 | 125 | // draw x axis arrow 126 | CGContextMoveToPoint(ctx, xAxisEndPointX - 3, yAxisCorssPointY - 3); 127 | CGContextAddLineToPoint(ctx, xAxisEndPointX, yAxisCorssPointY); 128 | CGContextAddLineToPoint(ctx, xAxisEndPointX - 3, yAxisCorssPointY + 3); 129 | CGContextStrokePath(ctx); 130 | 131 | if (_showLabel) 132 | { 133 | _xLabelWidth = (_chartCavanWidth - yAxisOffset) / [_xLabels count]; 134 | // draw x axis separator 135 | CGPoint point; 136 | for (NSUInteger i = 0; i < [_xLabels count]; i++) { 137 | point = CGPointMake(2 * _chartMargin + (i * _xLabelWidth), _chartMargin + _chartCavanHeight); 138 | CGContextMoveToPoint(ctx, point.x, point.y - 2); 139 | CGContextAddLineToPoint(ctx, point.x, point.y); 140 | CGContextStrokePath(ctx); 141 | } 142 | 143 | // draw y axis separator 144 | if (_showLabel) { 145 | _yLabelHeight = _chartCavanHeight / [_yLabels count]; 146 | } else { 147 | _yLabelHeight = (_frame.size.height) / [_yLabels count]; 148 | } 149 | 150 | _yLabelNum = _yLabels.count - 1; 151 | CGFloat yStepHeight = _chartCavanHeight / _yLabelNum; 152 | for (NSUInteger i = 0; i < [_xLabels count]; i++) 153 | { 154 | point = CGPointMake(_chartMargin + yAxisOffset, (_chartCavanHeight - i * yStepHeight + _yLabelHeight / 2)); 155 | CGContextMoveToPoint(ctx, point.x, point.y); 156 | CGContextAddLineToPoint(ctx, point.x + 2, point.y); 157 | CGContextStrokePath(ctx); 158 | } 159 | 160 | UIFont *font = [UIFont systemFontOfSize:10]; 161 | 162 | // draw y unit 163 | if ([_yUnit length]) { 164 | CGFloat height = [NKLineChart sizeOfString:_yUnit withWidth:30.f font:font].height; 165 | CGRect drawRect = CGRectMake(_chartMargin + 10 + 5, 0, 30.f, height); 166 | [self drawTextInContext:ctx text:_yUnit inRect:drawRect font:font]; 167 | } 168 | 169 | // draw x unit 170 | if ([_xUnit length]) { 171 | CGFloat height = [NKLineChart sizeOfString:_xUnit withWidth:30.f font:font].height; 172 | CGRect drawRect = CGRectMake(CGRectGetWidth(_frame) - _chartMargin - 10, _chartMargin + _chartCavanHeight - 2*height, 30.f, height); 173 | [self drawTextInContext:ctx text:_xUnit inRect:drawRect font:font]; 174 | } 175 | 176 | } 177 | 178 | } 179 | 180 | - (void) drawXLabels 181 | { 182 | if (_showLabel) { 183 | _xLabelWidth = _chartCavanWidth / [_xLabels count]; 184 | } else { 185 | _xLabelWidth = (_frame.size.width) / [_xLabels count]; 186 | } 187 | 188 | NSMutableDictionary *attributesDictionary = [NSMutableDictionary dictionary]; 189 | if (_xLabelFont) 190 | { 191 | [attributesDictionary setObject:_xLabelFont forKey:NSFontAttributeName]; 192 | } 193 | if (_xLabelColor) 194 | { 195 | 196 | [attributesDictionary setObject:_xLabelColor forKey:NSForegroundColorAttributeName]; 197 | } 198 | 199 | NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 200 | priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 201 | priceParagraphStyle.alignment = NSTextAlignmentCenter; 202 | [attributesDictionary setObject:priceParagraphStyle forKey:NSParagraphStyleAttributeName]; 203 | 204 | NSString *labelText; 205 | 206 | if (_showLabel) { 207 | 208 | for (int index = 0; index < _xLabels.count; index++) { 209 | labelText = _xLabels[index]; 210 | 211 | NSInteger x = 2 * _chartMargin + (index * _xLabelWidth) - (_xLabelWidth / 2); 212 | NSInteger y = _chartMargin + _chartCavanHeight; 213 | 214 | CGRect labelRect = CGRectMake(x, y, (NSInteger)_xLabelWidth, (NSInteger)_chartMargin); 215 | [labelText drawInRect:labelRect 216 | withAttributes:attributesDictionary]; 217 | } 218 | } 219 | 220 | } 221 | 222 | - (void) drawYLabels 223 | { 224 | [self prepareYLabelsWithData:_chartData]; 225 | //_showGenYLabels = NO; 226 | _yLabelNum = _yLabels.count - 1; 227 | 228 | if (_showLabel) { 229 | _yLabelHeight = _chartCavanHeight / [_yLabels count]; 230 | } else { 231 | _yLabelHeight = (_frame.size.height) / [_yLabels count]; 232 | } 233 | 234 | CGFloat yStep = (_yValueMax - _yValueMin) / _yLabelNum; 235 | CGFloat yStepHeight = _chartCavanHeight / _yLabelNum; 236 | 237 | NSMutableDictionary *attributesDictionary = [NSMutableDictionary dictionary]; 238 | if (_yLabelFont) 239 | { 240 | [attributesDictionary setObject:_yLabelFont forKey:NSFontAttributeName]; 241 | } 242 | if (_yLabelColor) 243 | { 244 | 245 | [attributesDictionary setObject:_yLabelColor forKey:NSForegroundColorAttributeName]; 246 | } 247 | 248 | NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 249 | priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 250 | priceParagraphStyle.alignment = NSTextAlignmentCenter; 251 | [attributesDictionary setObject:priceParagraphStyle forKey:NSParagraphStyleAttributeName]; 252 | 253 | if (yStep == 0.0) 254 | { 255 | CGRect minLabelRect = CGRectMake(0.0, (NSInteger)_chartCavanHeight, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight); 256 | NSString *minLabelText = [self formatYLabel:0.0]; 257 | [minLabelText drawInRect:minLabelRect 258 | withAttributes:attributesDictionary]; 259 | 260 | CGRect midLabelRect = CGRectMake(0.0, (NSInteger)(_chartCavanHeight / 2), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight); 261 | NSString *midLabelText = [self formatYLabel:_yValueMax]; 262 | [midLabelText drawInRect:midLabelRect 263 | withAttributes:attributesDictionary]; 264 | 265 | CGRect maxLabelRect =CGRectMake(0.0, 0.0, (NSInteger)_chartMargin, (NSInteger)_yLabelHeight); 266 | NSString *maxLabelText = [self formatYLabel:_yValueMax * 2]; 267 | [maxLabelText drawInRect:maxLabelRect 268 | withAttributes:attributesDictionary]; 269 | 270 | 271 | } else { 272 | 273 | NSInteger index = 0; 274 | NSInteger num = _yLabelNum + 1; 275 | 276 | while (num > 0) 277 | { 278 | CGRect labelRect = CGRectMake(0.0, (NSInteger)(_chartCavanHeight - index * yStepHeight)+(_yLabelHeight / 4), (NSInteger)_chartMargin, (NSInteger)_yLabelHeight); 279 | NSString *text = [self formatYLabel:_yValueMin + (yStep * index)]; 280 | [text drawInRect:labelRect 281 | withAttributes:attributesDictionary]; 282 | index += 1; 283 | num -= 1; 284 | } 285 | 286 | } 287 | } 288 | 289 | - (void)drawLines 290 | { 291 | _chartPath = [[NSMutableArray alloc] init]; 292 | _pointPath = [[NSMutableArray alloc] init]; 293 | _gradeStringPaths = [NSMutableArray array]; 294 | 295 | [self calculateChartPath:_chartPath andPointsPath:_pointPath andPathKeyPoints:_pathPoints andPathStartEndPoints:_endPointsOfPath]; 296 | 297 | // Draw each line 298 | for (NSUInteger lineIndex = 0; lineIndex < _chartData.count; lineIndex++) 299 | { 300 | NKLineChartData *chartData = _chartData[lineIndex]; 301 | 302 | UIBezierPath *chartLinePath = [_chartPath objectAtIndex:lineIndex]; 303 | UIBezierPath *pointPath = [_pointPath objectAtIndex:lineIndex]; 304 | 305 | if (chartData.color) { 306 | [[chartData.color colorWithAlphaComponent:chartData.alpha] setStroke]; 307 | 308 | } else { 309 | [NKGreen setStroke]; 310 | 311 | } 312 | 313 | [chartLinePath stroke]; 314 | [pointPath stroke]; 315 | } 316 | } 317 | 318 | - (void)calculateChartPath:(NSMutableArray *)chartPath andPointsPath:(NSMutableArray *)pointsPath andPathKeyPoints:(NSMutableArray *)pathPoints andPathStartEndPoints:(NSMutableArray *)pointsOfPath 319 | { 320 | 321 | // Draw each line 322 | for (NSUInteger lineIndex = 0; lineIndex < _chartData.count; lineIndex++) { 323 | NKLineChartData *chartData = _chartData[lineIndex]; 324 | 325 | CGFloat yValue; 326 | CGFloat innerGrade; 327 | 328 | UIBezierPath *progressline = [UIBezierPath bezierPath]; 329 | 330 | UIBezierPath *pointPath = [UIBezierPath bezierPath]; 331 | 332 | 333 | [chartPath insertObject:progressline atIndex:lineIndex]; 334 | [pointsPath insertObject:pointPath atIndex:lineIndex]; 335 | 336 | 337 | NSMutableArray* gradePathArray = [NSMutableArray array]; 338 | [_gradeStringPaths addObject:gradePathArray]; 339 | 340 | if (!_showLabel) { 341 | _chartCavanHeight = _frame.size.height - 2 * _yLabelHeight; 342 | _chartCavanWidth = _frame.size.width; 343 | _chartMargin = chartData.inflexionPointWidth; 344 | _xLabelWidth = (_chartCavanWidth / ([_xLabels count] - 1)); 345 | } 346 | 347 | NSMutableArray *linePointsArray = [[NSMutableArray alloc] init]; 348 | NSMutableArray *lineStartEndPointsArray = [[NSMutableArray alloc] init]; 349 | int last_x = 0; 350 | int last_y = 0; 351 | CGFloat inflexionWidth = chartData.inflexionPointWidth; 352 | 353 | for (NSUInteger i = 0; i < chartData.itemCount; i++) { 354 | 355 | yValue = chartData.getData(i).y; 356 | 357 | if (!(_yValueMax - _yValueMin)) { 358 | innerGrade = 0.5; 359 | } else { 360 | innerGrade = (yValue - _yValueMin) / (_yValueMax - _yValueMin); 361 | } 362 | 363 | CGFloat offSetX = (_chartCavanWidth) / (chartData.itemCount); 364 | 365 | int x = 2 * _chartMargin + (i * offSetX); 366 | int y = _chartCavanHeight - (innerGrade * _chartCavanHeight) + (_yLabelHeight / 2); 367 | 368 | // Circular point 369 | if (chartData.inflexionPointStyle == NKLineChartPointStyleCircle) { 370 | 371 | CGRect circleRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth); 372 | CGPoint circleCenter = CGPointMake(circleRect.origin.x + (circleRect.size.width / 2), circleRect.origin.y + (circleRect.size.height / 2)); 373 | 374 | [pointPath moveToPoint:CGPointMake(circleCenter.x + (inflexionWidth / 2), circleCenter.y)]; 375 | [pointPath addArcWithCenter:circleCenter radius:inflexionWidth / 2 startAngle:0 endAngle:2 * M_PI clockwise:YES]; 376 | 377 | if ( i != 0 ) { 378 | 379 | // calculate the point for line 380 | float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) ); 381 | float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x); 382 | float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y); 383 | float x1 = x - (inflexionWidth / 2) / distance * (x - last_x); 384 | float y1 = y - (inflexionWidth / 2) / distance * (y - last_y); 385 | 386 | [progressline moveToPoint:CGPointMake(last_x1, last_y1)]; 387 | [progressline addLineToPoint:CGPointMake(x1, y1)]; 388 | 389 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)]]; 390 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x1, y1)]]; 391 | } 392 | 393 | last_x = x; 394 | last_y = y; 395 | } 396 | // Square point 397 | else if (chartData.inflexionPointStyle == NKLineChartPointStyleSquare) { 398 | 399 | CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth); 400 | CGPoint squareCenter = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2), squareRect.origin.y + (squareRect.size.height / 2)); 401 | 402 | [pointPath moveToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))]; 403 | [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y - (inflexionWidth / 2))]; 404 | [pointPath addLineToPoint:CGPointMake(squareCenter.x + (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))]; 405 | [pointPath addLineToPoint:CGPointMake(squareCenter.x - (inflexionWidth / 2), squareCenter.y + (inflexionWidth / 2))]; 406 | [pointPath closePath]; 407 | 408 | if ( i != 0 ) { 409 | 410 | // calculate the point for line 411 | float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) ); 412 | float last_x1 = last_x + (inflexionWidth / 2); 413 | float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y); 414 | float x1 = x - (inflexionWidth / 2); 415 | float y1 = y - (inflexionWidth / 2) / distance * (y - last_y); 416 | 417 | [progressline moveToPoint:CGPointMake(last_x1, last_y1)]; 418 | [progressline addLineToPoint:CGPointMake(x1, y1)]; 419 | 420 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)]]; 421 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x1, y1)]]; 422 | } 423 | 424 | last_x = x; 425 | last_y = y; 426 | } 427 | // Triangle point 428 | else if (chartData.inflexionPointStyle == NKLineChartPointStyleTriangle) { 429 | 430 | CGRect squareRect = CGRectMake(x - inflexionWidth / 2, y - inflexionWidth / 2, inflexionWidth, inflexionWidth); 431 | 432 | CGPoint startPoint = CGPointMake(squareRect.origin.x,squareRect.origin.y + squareRect.size.height); 433 | CGPoint endPoint = CGPointMake(squareRect.origin.x + (squareRect.size.width / 2) , squareRect.origin.y); 434 | CGPoint middlePoint = CGPointMake(squareRect.origin.x + (squareRect.size.width) , squareRect.origin.y + squareRect.size.height); 435 | 436 | [pointPath moveToPoint:startPoint]; 437 | [pointPath addLineToPoint:middlePoint]; 438 | [pointPath addLineToPoint:endPoint]; 439 | [pointPath closePath]; 440 | 441 | if ( i != 0 ) { 442 | // calculate the point for triangle 443 | float distance = sqrt(pow(x - last_x, 2) + pow(y - last_y, 2) ) * 1.4 ; 444 | float last_x1 = last_x + (inflexionWidth / 2) / distance * (x - last_x); 445 | float last_y1 = last_y + (inflexionWidth / 2) / distance * (y - last_y); 446 | float x1 = x - (inflexionWidth / 2) / distance * (x - last_x); 447 | float y1 = y - (inflexionWidth / 2) / distance * (y - last_y); 448 | 449 | [progressline moveToPoint:CGPointMake(last_x1, last_y1)]; 450 | [progressline addLineToPoint:CGPointMake(x1, y1)]; 451 | 452 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(last_x1, last_y1)]]; 453 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x1, y1)]]; 454 | } 455 | 456 | last_x = x; 457 | last_y = y; 458 | 459 | } else { 460 | 461 | if ( i != 0 ) { 462 | [progressline addLineToPoint:CGPointMake(x, y)]; 463 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]]; 464 | } 465 | 466 | [progressline moveToPoint:CGPointMake(x, y)]; 467 | if(i != chartData.itemCount - 1){ 468 | [lineStartEndPointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]]; 469 | } 470 | } 471 | 472 | [linePointsArray addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]]; 473 | } 474 | 475 | [pathPoints addObject:[linePointsArray copy]]; 476 | [pointsOfPath addObject:[lineStartEndPointsArray copy]]; 477 | } 478 | } 479 | 480 | #pragma mark - tools 481 | 482 | + (CGSize)sizeOfString:(NSString *)text withWidth:(float)width font:(UIFont *)font 483 | { 484 | NSInteger ch; 485 | CGSize size = CGSizeMake(width, MAXFLOAT); 486 | 487 | NSDictionary *tdic = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]; 488 | size = [text boundingRectWithSize:size 489 | options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading 490 | attributes:tdic 491 | context:nil].size; 492 | 493 | ch = size.height; 494 | 495 | return size; 496 | } 497 | 498 | -(void)prepareYLabelsWithData:(NSArray *)data 499 | { 500 | CGFloat yMax = 0.0f; 501 | CGFloat yMin = MAXFLOAT; 502 | NSMutableArray *yLabelsArray = [NSMutableArray new]; 503 | 504 | for (NKLineChartData *chartData in data) { 505 | // create as many chart line layers as there are data-lines 506 | 507 | for (NSUInteger i = 0; i < chartData.itemCount; i++) { 508 | CGFloat yValue = chartData.getData(i).y; 509 | [yLabelsArray addObject:[NSString stringWithFormat:@"%2f", yValue]]; 510 | yMax = fmaxf(yMax, yValue); 511 | yMin = fminf(yMin, yValue); 512 | } 513 | } 514 | 515 | 516 | // Min value for Y label 517 | if (yMax < 5) { 518 | yMax = 5.0f; 519 | } 520 | 521 | if (yMin < 0) { 522 | yMin = 0.0f; 523 | } 524 | 525 | _yValueMin = (_yFixedValueMin > -FLT_MAX) ? _yFixedValueMin : yMin ; 526 | _yValueMax = (_yFixedValueMax > -FLT_MAX) ? _yFixedValueMax : yMax + yMax / 10.0; 527 | } 528 | 529 | 530 | - (void)drawTextInContext:(CGContextRef )ctx text:(NSString *)text inRect:(CGRect)rect font:(UIFont *)font 531 | { 532 | NSMutableParagraphStyle *priceParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 533 | priceParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 534 | priceParagraphStyle.alignment = NSTextAlignmentLeft; 535 | 536 | [text drawInRect:rect 537 | withAttributes:@{ NSParagraphStyleAttributeName:priceParagraphStyle, NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor whiteColor]}]; 538 | } 539 | 540 | - (NSString*) formatYLabel:(double)value{ 541 | 542 | if (_yLabelBlockFormatter) 543 | { 544 | return _yLabelBlockFormatter(value); 545 | } 546 | else 547 | { 548 | if (!_thousandsSeparator) { 549 | NSString *format = _yLabelFormat ? : @"%1f"; 550 | return [NSString stringWithFormat:format,value]; 551 | } 552 | 553 | NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init]; 554 | [numberFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4]; 555 | [numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle]; 556 | return [numberFormatter stringFromNumber: [NSNumber numberWithDouble:value]]; 557 | } 558 | } 559 | 560 | @end 561 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKLineChartData.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKLineChartData.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef NS_ENUM(NSUInteger, NKLineChartPointStyle) { 13 | NKLineChartPointStyleNone = 0, 14 | NKLineChartPointStyleCircle = 1, 15 | NKLineChartPointStyleSquare = 3, 16 | NKLineChartPointStyleTriangle = 4 17 | }; 18 | 19 | @class NKLineChartDataItem; 20 | 21 | typedef NKLineChartDataItem *(^LCLineChartDataGetter)(NSUInteger item); 22 | 23 | @interface NKLineChartData : NSObject 24 | 25 | @property (strong) UIColor *color; 26 | @property (nonatomic) CGFloat alpha; 27 | @property NSUInteger itemCount; 28 | @property (copy) LCLineChartDataGetter getData; 29 | 30 | @property (nonatomic, assign) NKLineChartPointStyle inflexionPointStyle; 31 | 32 | /** 33 | * If NKLineChartPointStyle is circle, this returns the circle's diameter. 34 | * If NKLineChartPointStyle is square, each point is a square with each side equal in length to this value. 35 | */ 36 | @property (nonatomic, assign) CGFloat inflexionPointWidth; 37 | 38 | @property (nonatomic, assign) CGFloat lineWidth; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKLineChartData.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKLineChartData.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "NKLineChartData.h" 10 | 11 | @implementation NKLineChartData 12 | 13 | - (id)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | [self setupDefaultValues]; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | - (void)setupDefaultValues 24 | { 25 | _inflexionPointStyle = NKLineChartPointStyleNone; 26 | _inflexionPointWidth = 4.f; 27 | _lineWidth = 2.f; 28 | _alpha = 1.f; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKLineChartDataItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKLineChartDataItem.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NKLineChartDataItem : NSObject 13 | 14 | + (NKLineChartDataItem *)dataItemWithY:(CGFloat)y; 15 | 16 | @property (readonly) CGFloat y; // should be within the y range 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKLineChartDataItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKLineChartDataItem.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/7/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "NKLineChartDataItem.h" 10 | 11 | @interface NKLineChartDataItem () 12 | 13 | - (id)initWithY:(CGFloat)y; 14 | 15 | @property (readwrite) CGFloat y; // should be within the y range 16 | 17 | @end 18 | 19 | @implementation NKLineChartDataItem 20 | 21 | + (NKLineChartDataItem *)dataItemWithY:(CGFloat)y 22 | { 23 | return [[NKLineChartDataItem alloc] initWithY:y]; 24 | } 25 | 26 | - (id)initWithY:(CGFloat)y 27 | { 28 | if ((self = [super init])) { 29 | self.y = y; 30 | } 31 | 32 | return self; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKPieChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKPieChart.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NKPieChart : NSObject 13 | 14 | @property (nonatomic, readonly) NSArray *items; 15 | 16 | @property (nonatomic) UIColor *chartBackgroundColor; 17 | 18 | @property (nonatomic) UIFont *descriptionTextFont; 19 | 20 | /** Default is white. */ 21 | @property (nonatomic) UIColor *descriptionTextColor; 22 | 23 | /** Show only values, this is useful when legend is present */ 24 | @property (nonatomic) BOOL showOnlyValues; 25 | 26 | /** Show absolute values not relative i.e. percentages */ 27 | @property (nonatomic) BOOL showAbsoluteValues; 28 | 29 | - (id)initWithFrame:(CGRect)frame items:(NSArray *)items; 30 | 31 | - (UIImage *)drawImage; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKPieChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKPieChart.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NKPieChart.h" 11 | #import "NKPieChartDataItem.h" 12 | 13 | @interface NKPieChart() 14 | 15 | @property (nonatomic) CGRect frame; 16 | 17 | @property (nonatomic) NSArray *items; 18 | @property (nonatomic) NSArray *endPercentages; 19 | @property (nonatomic) CGFloat outerCircleRadius; 20 | @property (nonatomic) CGFloat innerCircleRadius; 21 | 22 | @property (nonatomic) NSMutableArray *descriptionLabels; 23 | 24 | - (NKPieChartDataItem *)dataItemForIndex:(NSUInteger)index; 25 | - (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index; 26 | - (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index; 27 | - (CGFloat)ratioForItemAtIndex:(NSUInteger)index; 28 | 29 | @end 30 | 31 | @implementation NKPieChart 32 | 33 | -(id)initWithFrame:(CGRect)frame items:(NSArray *)items{ 34 | self = [self init]; 35 | if(self){ 36 | 37 | _frame = frame; 38 | _items = [NSArray arrayWithArray:items]; 39 | _outerCircleRadius = CGRectGetWidth(_frame) / 2; 40 | _innerCircleRadius = CGRectGetWidth(_frame) / 6; 41 | 42 | _descriptionTextColor = [UIColor whiteColor]; 43 | _descriptionTextFont = [UIFont systemFontOfSize:10.0]; 44 | 45 | } 46 | return self; 47 | 48 | } 49 | 50 | - (UIImage *)drawImage 51 | { 52 | __block CGFloat currentTotal = 0; 53 | CGFloat total = [[_items valueForKeyPath:@"@sum.value"] floatValue]; 54 | NSMutableArray *endPercentages = [NSMutableArray new]; 55 | [_items enumerateObjectsUsingBlock:^(NKPieChartDataItem *item, NSUInteger idx, BOOL *stop) { 56 | if (total == 0){ 57 | [endPercentages addObject:@(1.0 / _items.count * (idx + 1))]; 58 | }else{ 59 | currentTotal += item.value; 60 | [endPercentages addObject:@(currentTotal / total)]; 61 | } 62 | }]; 63 | _endPercentages = [endPercentages copy]; 64 | 65 | CGFloat scale = [WKInterfaceDevice currentDevice].screenScale; 66 | UIGraphicsBeginImageContextWithOptions(_frame.size, false, scale); 67 | 68 | 69 | if (_chartBackgroundColor) { 70 | UIBezierPath *chartRect = [UIBezierPath bezierPathWithRect:_frame]; 71 | [_chartBackgroundColor setFill]; 72 | [chartRect fill]; 73 | } 74 | 75 | CGPoint center = CGPointMake(CGRectGetMidX(_frame),CGRectGetMidY(_frame)); 76 | NKPieChartDataItem *currentItem; 77 | for (int i = 0; i < _items.count; i++) { 78 | currentItem = [self dataItemForIndex:i]; 79 | 80 | CGFloat startPercnetage = [self startPercentageForItemAtIndex:i]; 81 | CGFloat endPercentage = [self endPercentageForItemAtIndex:i]; 82 | 83 | CGFloat startAngle = -M_PI_2 + 2.0 * M_PI * startPercnetage; 84 | CGFloat endAngle = -M_PI_2 + 2.0 * M_PI * endPercentage; 85 | 86 | CGFloat radius = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2; 87 | CGFloat borderWidth = _outerCircleRadius - _innerCircleRadius; 88 | 89 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center 90 | radius:radius 91 | startAngle:startAngle 92 | endAngle:endAngle 93 | clockwise:YES]; 94 | path.lineWidth = borderWidth; 95 | [currentItem.color setStroke]; 96 | [path stroke]; 97 | 98 | // draw text 99 | NSString *description; 100 | 101 | CGFloat distance = _innerCircleRadius + (_outerCircleRadius - _innerCircleRadius) / 2; 102 | CGFloat centerPercentage = ([self startPercentageForItemAtIndex:i] + [self endPercentageForItemAtIndex:i])/ 2; 103 | CGFloat rad = centerPercentage * 2 * M_PI; 104 | 105 | NSString *titleText = currentItem.textDescription; 106 | NSString *titleValue; 107 | 108 | if (_showAbsoluteValues) { 109 | titleValue = [NSString stringWithFormat:@"%.0f",currentItem.value]; 110 | }else{ 111 | titleValue = [NSString stringWithFormat:@"%.0f%%",[self ratioForItemAtIndex:i] * 100]; 112 | } 113 | if(!titleText || _showOnlyValues){ 114 | description = titleValue; 115 | } 116 | else { 117 | NSString* str = [titleValue stringByAppendingString:[NSString stringWithFormat:@"\n%@",titleText]]; 118 | description = str ; 119 | } 120 | 121 | NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; 122 | [attributes setObject:_descriptionTextFont forKey:NSFontAttributeName]; 123 | [attributes setObject:_descriptionTextColor forKey:NSForegroundColorAttributeName]; 124 | 125 | CGPoint center = CGPointMake(_outerCircleRadius + distance * sin(rad), 126 | _outerCircleRadius - distance * cos(rad)); 127 | 128 | CGSize size = [description boundingRectWithSize:CGSizeMake( (_outerCircleRadius - _innerCircleRadius), 129 | (_outerCircleRadius - _innerCircleRadius)) 130 | options:NSStringDrawingUsesLineFragmentOrigin 131 | attributes:attributes 132 | context:nil].size; 133 | 134 | [description drawInRect:CGRectMake(center.x - size.width/2, center.y - size.height/2, size.width, size.height) withAttributes:attributes]; 135 | } 136 | 137 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 138 | UIGraphicsEndImageContext(); 139 | return image; 140 | } 141 | 142 | - (NKPieChartDataItem *)dataItemForIndex:(NSUInteger)index{ 143 | return _items[index]; 144 | } 145 | 146 | - (CGFloat)startPercentageForItemAtIndex:(NSUInteger)index{ 147 | if(index == 0){ 148 | return 0; 149 | } 150 | 151 | return [_endPercentages[index - 1] floatValue]; 152 | } 153 | 154 | - (CGFloat)endPercentageForItemAtIndex:(NSUInteger)index{ 155 | return [_endPercentages[index] floatValue]; 156 | } 157 | 158 | - (CGFloat)ratioForItemAtIndex:(NSUInteger)index{ 159 | return [self endPercentageForItemAtIndex:index] - [self startPercentageForItemAtIndex:index]; 160 | } 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKPieChartDataItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKPieChartDataItem.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NKPieChartDataItem : NSObject 13 | 14 | + (instancetype)dataItemWithValue:(CGFloat)value 15 | color:(UIColor*)color; 16 | 17 | + (instancetype)dataItemWithValue:(CGFloat)value 18 | color:(UIColor*)color 19 | description:(NSString *)description; 20 | 21 | @property (nonatomic) CGFloat value; 22 | @property (nonatomic) UIColor *color; 23 | @property (nonatomic) NSString *textDescription; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKPieChartDataItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKPieChartDataItem.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "NKPieChartDataItem.h" 10 | 11 | @implementation NKPieChartDataItem 12 | 13 | + (instancetype)dataItemWithValue:(CGFloat)value 14 | color:(UIColor*)color{ 15 | NKPieChartDataItem *item = [NKPieChartDataItem new]; 16 | item.value = value; 17 | item.color = color; 18 | return item; 19 | } 20 | 21 | + (instancetype)dataItemWithValue:(CGFloat)value 22 | color:(UIColor*)color 23 | description:(NSString *)description { 24 | NKPieChartDataItem *item = [NKPieChartDataItem dataItemWithValue:value color:color]; 25 | item.textDescription = description; 26 | return item; 27 | } 28 | 29 | - (void)setValue:(CGFloat)value{ 30 | NSAssert(value >= 0, @"value should >= 0"); 31 | if (value != _value){ 32 | _value = value; 33 | } 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKRadarChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKRadarChart.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #define MAXCIRCLE 30 13 | 14 | typedef NS_ENUM(NSUInteger, NKRadarChartLabelStyle) { 15 | NKRadarChartLabelStyleHorizontal = 0, 16 | NKRadarChartLabelStyleHidden, 17 | }; 18 | 19 | @interface NKRadarChart : NSObject 20 | 21 | @property (nonatomic) UIColor *chartBackgroundColor; 22 | /** Array of `RadarChartDataItem` objects, one for each corner. */ 23 | @property (nonatomic) NSArray *chartData; 24 | /** The unit of this chart ,default is 1 */ 25 | @property (nonatomic) CGFloat valueDivider; 26 | /** The maximum for the range of values to display on the chart */ 27 | @property (nonatomic) CGFloat maxValue; 28 | /** Default is gray. */ 29 | @property (nonatomic) UIColor *webColor; 30 | /** Default is green , with an alpha of 0.7 */ 31 | @property (nonatomic) UIColor *plotColor; 32 | /** Default is black */ 33 | @property (nonatomic) UIColor *fontColor; 34 | /** Default is orange */ 35 | @property (nonatomic) UIColor *graduationColor; 36 | /** Default is 15 */ 37 | @property (nonatomic) CGFloat fontSize; 38 | /** Controls the labels display style that around chart */ 39 | @property (nonatomic, assign) NKRadarChartLabelStyle labelStyle; 40 | /** is show graduation on the chart ,default is NO. */ 41 | @property (nonatomic, assign) BOOL isShowGraduation; 42 | 43 | -(id)initWithFrame:(CGRect)frame items:(NSArray *)items valueDivider:(CGFloat)unitValue; 44 | /** 45 | *Draws the chart in an animated fashion. 46 | */ 47 | -(UIImage *)drawImage; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKRadarChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKRadarChart.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NKRadarChart.h" 11 | #import "NKRadarChartDataItem.h" 12 | #import "NKColor.h" 13 | 14 | @interface NKRadarChart() 15 | 16 | @property (nonatomic) CGRect frame; 17 | @property (nonatomic) CGFloat centerX; 18 | @property (nonatomic) CGFloat centerY; 19 | @property (nonatomic) NSMutableArray *pointsToWebArrayArray; 20 | @property (nonatomic) NSMutableArray *pointsToPlotArray; 21 | @property (nonatomic) CGFloat lengthUnit; 22 | 23 | @end 24 | 25 | @implementation NKRadarChart 26 | 27 | - (id)initWithFrame:(CGRect)frame items:(NSArray *)items valueDivider:(CGFloat)unitValue { 28 | self=[super init]; 29 | if (self) { 30 | 31 | _frame = frame; 32 | if ([items count]< 3)//At least three corners of A polygon ,If the count of items is less than 3 will add 3 default values 33 | { 34 | NSLog( @"At least three items!"); 35 | NSArray *defaultArray = @[[NKRadarChartDataItem dataItemWithValue:0 description:@"Default"], 36 | [NKRadarChartDataItem dataItemWithValue:0 description:@"Default"], 37 | [NKRadarChartDataItem dataItemWithValue:0 description:@"Default"], 38 | ]; 39 | defaultArray = [defaultArray arrayByAddingObjectsFromArray:items]; 40 | _chartData = [NSArray arrayWithArray:defaultArray]; 41 | }else{ 42 | _chartData = [NSArray arrayWithArray:items]; 43 | } 44 | _valueDivider = unitValue; 45 | _maxValue = 1; 46 | _webColor = [UIColor grayColor]; 47 | _plotColor = [UIColor colorWithRed:.4 green:.8 blue:.4 alpha:.7]; 48 | _fontColor = [UIColor blackColor]; 49 | _graduationColor = [UIColor orangeColor]; 50 | _fontSize = 8; 51 | _labelStyle = NKRadarChartLabelStyleHorizontal; 52 | _isShowGraduation = NO; 53 | 54 | //Private iVar 55 | _centerX = _frame.size.width/2; 56 | _centerY = _frame.size.height/2; 57 | _pointsToWebArrayArray = [NSMutableArray array]; 58 | _pointsToPlotArray = [NSMutableArray array]; 59 | _lengthUnit = 0; 60 | } 61 | return self; 62 | } 63 | 64 | #pragma mark - main 65 | 66 | - (UIImage *)drawImage 67 | { 68 | 69 | CGFloat scale = [WKInterfaceDevice currentDevice].screenScale; 70 | UIGraphicsBeginImageContextWithOptions(_frame.size, false, scale); 71 | 72 | if (_chartBackgroundColor) { 73 | UIBezierPath *chartRect = [UIBezierPath bezierPathWithRect:_frame]; 74 | [_chartBackgroundColor setFill]; 75 | [chartRect fill]; 76 | } 77 | 78 | [self calculateChartPoints]; 79 | 80 | // Drawing backgound 81 | int section = 0; 82 | //circles 83 | for(NSArray *pointArray in _pointsToWebArrayArray){ 84 | //plot backgound 85 | CGContextRef graphContext = UIGraphicsGetCurrentContext(); 86 | CGContextBeginPath(graphContext); 87 | CGPoint beginPoint = [[pointArray objectAtIndex:0] CGPointValue]; 88 | CGContextMoveToPoint(graphContext, beginPoint.x, beginPoint.y); 89 | for(NSValue* pointValue in pointArray){ 90 | CGPoint point = [pointValue CGPointValue]; 91 | CGContextAddLineToPoint(graphContext, point.x, point.y); 92 | } 93 | CGContextAddLineToPoint(graphContext, beginPoint.x, beginPoint.y); 94 | CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor); 95 | CGContextStrokePath(graphContext); 96 | 97 | } 98 | //cuts 99 | NSArray *largestPointArray = [_pointsToWebArrayArray lastObject]; 100 | for (NSValue *pointValue in largestPointArray){ 101 | section++; 102 | if (section==1&&_isShowGraduation)continue; 103 | 104 | CGContextRef graphContext = UIGraphicsGetCurrentContext(); 105 | CGContextBeginPath(graphContext); 106 | CGContextMoveToPoint(graphContext, _centerX, _centerY); 107 | CGPoint point = [pointValue CGPointValue]; 108 | CGContextAddLineToPoint(graphContext, point.x, point.y); 109 | CGContextSetStrokeColorWithColor(graphContext, _webColor.CGColor); 110 | CGContextStrokePath(graphContext); 111 | } 112 | 113 | //Draw plot 114 | UIBezierPath *plotline = [UIBezierPath bezierPath]; 115 | CGPoint beginPoint = [[_pointsToPlotArray objectAtIndex:0] CGPointValue]; 116 | [plotline moveToPoint:CGPointMake(beginPoint.x, beginPoint.y)]; 117 | for(NSValue *pointValue in _pointsToPlotArray){ 118 | CGPoint point = [pointValue CGPointValue]; 119 | [plotline addLineToPoint:CGPointMake(point.x ,point.y)]; 120 | 121 | } 122 | [plotline setLineWidth:1]; 123 | [plotline setLineCapStyle:kCGLineCapButt]; 124 | [plotline setLineJoinStyle:kCGLineJoinMiter]; 125 | [plotline closePath]; 126 | [_plotColor setFill]; 127 | [plotline fill]; 128 | 129 | if (_isShowGraduation) { 130 | [self showGraduation]; 131 | } 132 | 133 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 134 | UIGraphicsEndImageContext(); 135 | return image; 136 | } 137 | 138 | - (void)calculateChartPoints { 139 | [_pointsToPlotArray removeAllObjects]; 140 | [_pointsToWebArrayArray removeAllObjects]; 141 | 142 | //init Descriptions , Values and Angles. 143 | NSMutableArray *descriptions = [NSMutableArray array]; 144 | NSMutableArray *values = [NSMutableArray array]; 145 | NSMutableArray *angles = [NSMutableArray array]; 146 | for (int i=0;i<_chartData.count;i++) { 147 | NKRadarChartDataItem *item = (NKRadarChartDataItem *)[_chartData objectAtIndex:i]; 148 | [descriptions addObject:item.textDescription]; 149 | [values addObject:[NSNumber numberWithFloat:item.value]]; 150 | CGFloat angleValue = (float)i/(float)[_chartData count]*2*M_PI; 151 | [angles addObject:[NSNumber numberWithFloat:angleValue]]; 152 | } 153 | 154 | //calculate all the lengths 155 | _maxValue = [self getMaxValueFromArray:values]; 156 | CGFloat margin = 0; 157 | if (_labelStyle==NKRadarChartLabelStyleHorizontal) { 158 | margin = [self getMaxWidthLabelFromArray:descriptions withFontSize:_fontSize]; 159 | } 160 | CGFloat maxLength = ceil(MIN(_centerX, _centerY) - margin); 161 | int plotCircles = (_maxValue/_valueDivider); 162 | if (plotCircles > MAXCIRCLE) { 163 | NSLog(@"Circle number is higher than max"); 164 | plotCircles = MAXCIRCLE; 165 | _valueDivider = _maxValue/plotCircles; 166 | } 167 | _lengthUnit = maxLength/plotCircles; 168 | NSArray *lengthArray = [self getLengthArrayWithCircleNum:(int)plotCircles]; 169 | 170 | //get all the points and plot 171 | for (NSNumber *lengthNumber in lengthArray) { 172 | CGFloat length = [lengthNumber floatValue]; 173 | [_pointsToWebArrayArray addObject:[self getWebPointWithLength:length angleArray:angles]]; 174 | } 175 | int section = 0; 176 | for (id value in values) { 177 | CGFloat valueFloat = [value floatValue]; 178 | if (valueFloat>_maxValue) { 179 | NSString *reason = [NSString stringWithFormat:@"Value number is higher than max -value: %f - maxValue: %f",valueFloat,_maxValue]; 180 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil]; 181 | return; 182 | } 183 | 184 | CGFloat length = valueFloat/_maxValue*maxLength; 185 | CGFloat angle = [[angles objectAtIndex:section] floatValue]; 186 | CGFloat x = _centerX +length*cos(angle); 187 | CGFloat y = _centerY +length*sin(angle); 188 | NSValue* point = [NSValue valueWithCGPoint:CGPointMake(x, y)]; 189 | [_pointsToPlotArray addObject:point]; 190 | section++; 191 | } 192 | //set the labels 193 | [self drawLabelWithMaxLength:maxLength labelArray:descriptions angleArray:angles]; 194 | 195 | } 196 | 197 | #pragma helpers 198 | 199 | - (void)drawLabelWithMaxLength:(CGFloat)maxLength labelArray:(NSArray *)labelArray angleArray:(NSArray *)angleArray 200 | { 201 | int section = 0; 202 | CGFloat labelLength = maxLength + maxLength/10; 203 | 204 | for (NSString *labelString in labelArray) { 205 | CGFloat angle = [[angleArray objectAtIndex:section] floatValue]; 206 | CGFloat x = _centerX + labelLength *cos(angle); 207 | CGFloat y = _centerY + labelLength *sin(angle); 208 | 209 | // label.backgroundColor = [UIColor clearColor]; 210 | UIFont *font = [UIFont systemFontOfSize:_fontSize]; 211 | CGSize detailSize = [labelString sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}]; 212 | CGRect frame = CGRectZero; 213 | 214 | NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; 215 | [attributes setObject:font forKey:NSFontAttributeName]; 216 | [attributes setObject:NKGreen forKey:NSForegroundColorAttributeName]; 217 | 218 | NSMutableParagraphStyle *paragraphStyle =NSMutableParagraphStyle.new; 219 | switch (_labelStyle) { 220 | case NKRadarChartLabelStyleHorizontal: 221 | if (x<_centerX) { 222 | frame = CGRectMake(x-detailSize.width, y-detailSize.height/2, detailSize.width, detailSize.height); 223 | paragraphStyle.alignment = NSTextAlignmentRight; 224 | [attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName]; 225 | [labelString drawInRect:frame withAttributes:attributes]; 226 | 227 | }else{ 228 | frame = CGRectMake(x, y-detailSize.height/2, detailSize.width , detailSize.height); 229 | paragraphStyle.alignment = NSTextAlignmentLeft; 230 | [attributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName]; 231 | [labelString drawInRect:frame withAttributes:attributes]; 232 | 233 | } 234 | break; 235 | case NKRadarChartLabelStyleHidden: 236 | break; 237 | default: 238 | break; 239 | } 240 | 241 | section ++; 242 | } 243 | 244 | } 245 | 246 | - (void)showGraduation 247 | { 248 | int section = 0; 249 | for (NSArray *pointsArray in _pointsToWebArrayArray) { 250 | section++; 251 | CGPoint labelPoint = [[pointsArray objectAtIndex:0] CGPointValue]; 252 | CGRect graduationRect = CGRectMake(labelPoint.x-_lengthUnit, labelPoint.y-_lengthUnit*5/8, _lengthUnit*5/8, _lengthUnit); 253 | CGFloat fontSize; 254 | if (ceil(_lengthUnit-1) < 1) { 255 | fontSize = 1.0; 256 | } else { 257 | fontSize = ceil(_lengthUnit-1); 258 | } 259 | UIFont *font = [UIFont systemFontOfSize:fontSize]; 260 | UIColor *textColor = [UIColor orangeColor]; 261 | NSString *text = [NSString stringWithFormat:@"%.0f",_valueDivider*section]; 262 | 263 | NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; 264 | [attributes setObject:font forKey:NSFontAttributeName]; 265 | [attributes setObject:textColor forKey:NSForegroundColorAttributeName]; 266 | 267 | [text drawInRect:graduationRect withAttributes:attributes]; 268 | } 269 | 270 | } 271 | 272 | - (NSArray *)getWebPointWithLength:(CGFloat)length angleArray:(NSArray *)angleArray { 273 | NSMutableArray *pointArray = [NSMutableArray array]; 274 | for (NSNumber *angleNumber in angleArray) { 275 | CGFloat angle = [angleNumber floatValue]; 276 | CGFloat x = _centerX + length*cos(angle); 277 | CGFloat y = _centerY + length*sin(angle); 278 | [pointArray addObject:[NSValue valueWithCGPoint:CGPointMake(x,y)]]; 279 | } 280 | return pointArray; 281 | 282 | } 283 | 284 | - (NSArray *)getLengthArrayWithCircleNum:(int)plotCircles { 285 | NSMutableArray *lengthArray = [NSMutableArray array]; 286 | CGFloat length = 0; 287 | for (int i = 0; i < plotCircles; i++) { 288 | length += _lengthUnit; 289 | [lengthArray addObject:[NSNumber numberWithFloat:length]]; 290 | } 291 | return lengthArray; 292 | } 293 | 294 | - (CGFloat)getMaxWidthLabelFromArray:(NSArray *)keyArray withFontSize:(CGFloat)size { 295 | CGFloat maxWidth = 0; 296 | for (NSString *str in keyArray) { 297 | CGSize detailSize = [str sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:_fontSize]}]; 298 | maxWidth = MAX(maxWidth, detailSize.width); 299 | } 300 | return maxWidth; 301 | } 302 | 303 | - (CGFloat)getMaxValueFromArray:(NSArray *)valueArray { 304 | CGFloat max = _maxValue; 305 | for (NSNumber *valueNum in valueArray) { 306 | CGFloat valueFloat = [valueNum floatValue]; 307 | max = MAX(valueFloat, max); 308 | } 309 | return ceil(max); 310 | } 311 | 312 | @end -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKRadarChartDataItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKRadarChartDataItem.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NKRadarChartDataItem : NSObject 13 | 14 | + (instancetype)dataItemWithValue:(CGFloat)value 15 | description:(NSString *)description; 16 | 17 | @property (nonatomic) CGFloat value; 18 | @property (nonatomic,copy) NSString *textDescription; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKRadarChartDataItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // NKRadarChartDataItem.m 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/8/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import "NKRadarChartDataItem.h" 10 | 11 | @implementation NKRadarChartDataItem 12 | 13 | + (instancetype)dataItemWithValue:(CGFloat)value 14 | description:(NSString *)description { 15 | NKRadarChartDataItem *item = [NKRadarChartDataItem new]; 16 | item.value = value; 17 | item.textDescription = description; 18 | return item; 19 | } 20 | 21 | - (void)setValue:(CGFloat)value { 22 | if (value<0) { 23 | _value = 0; 24 | NSLog(@"Value value can not be negative"); 25 | } 26 | _value = value; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /WatchChart Extension/NKWatchChart/NKWatchChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // NKWatchChart.h 3 | // NKWatchChartDemo 4 | // 5 | // Created by Peng on 8/6/15. 6 | // Copyright © 2015 Peng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "NKColor.h" 12 | 13 | #import "NKLineChart.h" 14 | #import "NKLineChartData.h" 15 | #import "NKLineChartDataItem.h" 16 | 17 | #import "NKCircleChart.h" 18 | 19 | #import "NKPieChart.h" 20 | #import "NKPieChartDataItem.h" 21 | 22 | #import "NKRadarChartDataItem.h" 23 | #import "NKRadarChart.h" 24 | 25 | #import "NKBarChart.h" 26 | -------------------------------------------------------------------------------- /WatchChart/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "24x24", 5 | "idiom" : "watch", 6 | "scale" : "2x", 7 | "role" : "notificationCenter", 8 | "subtype" : "38mm" 9 | }, 10 | { 11 | "size" : "27.5x27.5", 12 | "idiom" : "watch", 13 | "scale" : "2x", 14 | "role" : "notificationCenter", 15 | "subtype" : "42mm" 16 | }, 17 | { 18 | "size" : "29x29", 19 | "idiom" : "watch", 20 | "role" : "companionSettings", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "size" : "29x29", 25 | "idiom" : "watch", 26 | "role" : "companionSettings", 27 | "scale" : "3x" 28 | }, 29 | { 30 | "size" : "40x40", 31 | "idiom" : "watch", 32 | "scale" : "2x", 33 | "role" : "appLauncher", 34 | "subtype" : "38mm" 35 | }, 36 | { 37 | "size" : "44x44", 38 | "idiom" : "watch", 39 | "scale" : "2x", 40 | "role" : "longLook", 41 | "subtype" : "42mm" 42 | }, 43 | { 44 | "size" : "86x86", 45 | "idiom" : "watch", 46 | "scale" : "2x", 47 | "role" : "quickLook", 48 | "subtype" : "38mm" 49 | }, 50 | { 51 | "size" : "98x98", 52 | "idiom" : "watch", 53 | "scale" : "2x", 54 | "role" : "quickLook", 55 | "subtype" : "42mm" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /WatchChart/Base.lproj/Interface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 |
33 |
34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 |
52 | -------------------------------------------------------------------------------- /WatchChart/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | NKWatchChartDemo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | UISupportedInterfaceOrientations 26 | 27 | UIInterfaceOrientationPortrait 28 | UIInterfaceOrientationPortraitUpsideDown 29 | 30 | WKCompanionAppBundleIdentifier 31 | watch.develop.NKWatchChartDemo 32 | WKWatchKitApp 33 | 34 | 35 | 36 | --------------------------------------------------------------------------------