├── .gitignore ├── LICENSE ├── PDChartDemo.xcodeproj └── project.pbxproj ├── PDChartDemo ├── AppDelegate.swift ├── Common │ └── Define.swift ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── Info.plist ├── Launch Screen.storyboard ├── MainViewController │ └── MainViewController.swift └── PDChart │ ├── PDBarChart │ └── PDBarChart.swift │ ├── PDChart.swift │ ├── PDChartComponent │ └── PDChartAxesComponent.swift │ ├── PDLineChart │ └── PDLineChart.swift │ └── PDPieChart │ └── PDPieChart.swift ├── PDChartDemoTests ├── Info.plist └── PDChartDemoTests.swift └── README.md /.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 | *.xccheckout 14 | *.xcworkspace 15 | !default.xcworkspace 16 | *.moved-aside 17 | DerivedData 18 | *.hmap 19 | *.ipa 20 | *.xcuserstate 21 | .idea/ 22 | # CocoaPods 23 | # Pods - for those of you who use CocoaPods 24 | Pods/ 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 HealTheWorld 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. -------------------------------------------------------------------------------- /PDChartDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8427E4D41974C52C006CF8C6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4D31974C52C006CF8C6 /* AppDelegate.swift */; }; 11 | 8427E4DB1974C52C006CF8C6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8427E4DA1974C52C006CF8C6 /* Images.xcassets */; }; 12 | 8427E4E71974C52C006CF8C6 /* PDChartDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4E61974C52C006CF8C6 /* PDChartDemoTests.swift */; }; 13 | 8427E4F21974C588006CF8C6 /* Define.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4F11974C588006CF8C6 /* Define.swift */; }; 14 | 8427E4F61974C5F6006CF8C6 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4F41974C5F6006CF8C6 /* MainViewController.swift */; }; 15 | 8427E5021974C5FD006CF8C6 /* PDBarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4FA1974C5FD006CF8C6 /* PDBarChart.swift */; }; 16 | 8427E5031974C5FD006CF8C6 /* PDChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4FB1974C5FD006CF8C6 /* PDChart.swift */; }; 17 | 8427E5041974C5FD006CF8C6 /* PDChartAxesComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4FD1974C5FD006CF8C6 /* PDChartAxesComponent.swift */; }; 18 | 8427E5051974C5FD006CF8C6 /* PDLineChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E4FF1974C5FD006CF8C6 /* PDLineChart.swift */; }; 19 | 8427E5061974C5FD006CF8C6 /* PDPieChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8427E5011974C5FD006CF8C6 /* PDPieChart.swift */; }; 20 | 983857691D267ABB0008287D /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 983857681D267ABB0008287D /* Launch Screen.storyboard */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 8427E4E11974C52C006CF8C6 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 8427E4C61974C52C006CF8C6 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 8427E4CD1974C52C006CF8C6; 29 | remoteInfo = PDChartDemo; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 8427E4CE1974C52C006CF8C6 /* PDChartDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PDChartDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 8427E4D21974C52C006CF8C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 8427E4D31974C52C006CF8C6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 8427E4DA1974C52C006CF8C6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 38 | 8427E4E01974C52C006CF8C6 /* PDChartDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PDChartDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 8427E4E51974C52C006CF8C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 8427E4E61974C52C006CF8C6 /* PDChartDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDChartDemoTests.swift; sourceTree = ""; }; 41 | 8427E4F11974C588006CF8C6 /* Define.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Define.swift; path = Common/Define.swift; sourceTree = ""; }; 42 | 8427E4F41974C5F6006CF8C6 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MainViewController.swift; path = MainViewController/MainViewController.swift; sourceTree = ""; }; 43 | 8427E4FA1974C5FD006CF8C6 /* PDBarChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PDBarChart.swift; path = PDBarChart/PDBarChart.swift; sourceTree = ""; }; 44 | 8427E4FB1974C5FD006CF8C6 /* PDChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDChart.swift; sourceTree = ""; }; 45 | 8427E4FD1974C5FD006CF8C6 /* PDChartAxesComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDChartAxesComponent.swift; sourceTree = ""; }; 46 | 8427E4FF1974C5FD006CF8C6 /* PDLineChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PDLineChart.swift; path = PDLineChart/PDLineChart.swift; sourceTree = ""; }; 47 | 8427E5011974C5FD006CF8C6 /* PDPieChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PDPieChart.swift; path = PDPieChart/PDPieChart.swift; sourceTree = ""; }; 48 | 983857681D267ABB0008287D /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; 49 | /* End PBXFileReference section */ 50 | 51 | /* Begin PBXFrameworksBuildPhase section */ 52 | 8427E4CB1974C52C006CF8C6 /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | 8427E4DD1974C52C006CF8C6 /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 8427E4C51974C52C006CF8C6 = { 70 | isa = PBXGroup; 71 | children = ( 72 | 8427E4D01974C52C006CF8C6 /* PDChartDemo */, 73 | 8427E4E31974C52C006CF8C6 /* PDChartDemoTests */, 74 | 8427E4CF1974C52C006CF8C6 /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 8427E4CF1974C52C006CF8C6 /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 8427E4CE1974C52C006CF8C6 /* PDChartDemo.app */, 82 | 8427E4E01974C52C006CF8C6 /* PDChartDemoTests.xctest */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 8427E4D01974C52C006CF8C6 /* PDChartDemo */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 983857681D267ABB0008287D /* Launch Screen.storyboard */, 91 | 8427E4F81974C5FD006CF8C6 /* PDChart */, 92 | 8427E4F31974C597006CF8C6 /* MainViewController */, 93 | 8427E4F01974C570006CF8C6 /* Common */, 94 | 8427E4D31974C52C006CF8C6 /* AppDelegate.swift */, 95 | 8427E4DA1974C52C006CF8C6 /* Images.xcassets */, 96 | 8427E4D11974C52C006CF8C6 /* Supporting Files */, 97 | ); 98 | path = PDChartDemo; 99 | sourceTree = ""; 100 | }; 101 | 8427E4D11974C52C006CF8C6 /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 8427E4D21974C52C006CF8C6 /* Info.plist */, 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | 8427E4E31974C52C006CF8C6 /* PDChartDemoTests */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 8427E4E61974C52C006CF8C6 /* PDChartDemoTests.swift */, 113 | 8427E4E41974C52C006CF8C6 /* Supporting Files */, 114 | ); 115 | path = PDChartDemoTests; 116 | sourceTree = ""; 117 | }; 118 | 8427E4E41974C52C006CF8C6 /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 8427E4E51974C52C006CF8C6 /* Info.plist */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | 8427E4F01974C570006CF8C6 /* Common */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 8427E4F11974C588006CF8C6 /* Define.swift */, 130 | ); 131 | name = Common; 132 | sourceTree = ""; 133 | }; 134 | 8427E4F31974C597006CF8C6 /* MainViewController */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 8427E4F41974C5F6006CF8C6 /* MainViewController.swift */, 138 | ); 139 | name = MainViewController; 140 | sourceTree = ""; 141 | }; 142 | 8427E4F81974C5FD006CF8C6 /* PDChart */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 8427E4FC1974C5FD006CF8C6 /* PDChartComponent */, 146 | 8427E5011974C5FD006CF8C6 /* PDPieChart.swift */, 147 | 8427E4FF1974C5FD006CF8C6 /* PDLineChart.swift */, 148 | 8427E4FA1974C5FD006CF8C6 /* PDBarChart.swift */, 149 | 8427E4FB1974C5FD006CF8C6 /* PDChart.swift */, 150 | ); 151 | path = PDChart; 152 | sourceTree = ""; 153 | }; 154 | 8427E4FC1974C5FD006CF8C6 /* PDChartComponent */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 8427E4FD1974C5FD006CF8C6 /* PDChartAxesComponent.swift */, 158 | ); 159 | path = PDChartComponent; 160 | sourceTree = ""; 161 | }; 162 | /* End PBXGroup section */ 163 | 164 | /* Begin PBXNativeTarget section */ 165 | 8427E4CD1974C52C006CF8C6 /* PDChartDemo */ = { 166 | isa = PBXNativeTarget; 167 | buildConfigurationList = 8427E4EA1974C52C006CF8C6 /* Build configuration list for PBXNativeTarget "PDChartDemo" */; 168 | buildPhases = ( 169 | 8427E4CA1974C52C006CF8C6 /* Sources */, 170 | 8427E4CB1974C52C006CF8C6 /* Frameworks */, 171 | 8427E4CC1974C52C006CF8C6 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | ); 177 | name = PDChartDemo; 178 | productName = PDChartDemo; 179 | productReference = 8427E4CE1974C52C006CF8C6 /* PDChartDemo.app */; 180 | productType = "com.apple.product-type.application"; 181 | }; 182 | 8427E4DF1974C52C006CF8C6 /* PDChartDemoTests */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = 8427E4ED1974C52C006CF8C6 /* Build configuration list for PBXNativeTarget "PDChartDemoTests" */; 185 | buildPhases = ( 186 | 8427E4DC1974C52C006CF8C6 /* Sources */, 187 | 8427E4DD1974C52C006CF8C6 /* Frameworks */, 188 | 8427E4DE1974C52C006CF8C6 /* Resources */, 189 | ); 190 | buildRules = ( 191 | ); 192 | dependencies = ( 193 | 8427E4E21974C52C006CF8C6 /* PBXTargetDependency */, 194 | ); 195 | name = PDChartDemoTests; 196 | productName = PDChartDemoTests; 197 | productReference = 8427E4E01974C52C006CF8C6 /* PDChartDemoTests.xctest */; 198 | productType = "com.apple.product-type.bundle.unit-test"; 199 | }; 200 | /* End PBXNativeTarget section */ 201 | 202 | /* Begin PBXProject section */ 203 | 8427E4C61974C52C006CF8C6 /* Project object */ = { 204 | isa = PBXProject; 205 | attributes = { 206 | LastSwiftUpdateCheck = 0730; 207 | LastUpgradeCheck = 0730; 208 | ORGANIZATIONNAME = Pandara; 209 | TargetAttributes = { 210 | 8427E4CD1974C52C006CF8C6 = { 211 | CreatedOnToolsVersion = 6.0; 212 | }; 213 | 8427E4DF1974C52C006CF8C6 = { 214 | CreatedOnToolsVersion = 6.0; 215 | TestTargetID = 8427E4CD1974C52C006CF8C6; 216 | }; 217 | }; 218 | }; 219 | buildConfigurationList = 8427E4C91974C52C006CF8C6 /* Build configuration list for PBXProject "PDChartDemo" */; 220 | compatibilityVersion = "Xcode 3.2"; 221 | developmentRegion = English; 222 | hasScannedForEncodings = 0; 223 | knownRegions = ( 224 | en, 225 | Base, 226 | ); 227 | mainGroup = 8427E4C51974C52C006CF8C6; 228 | productRefGroup = 8427E4CF1974C52C006CF8C6 /* Products */; 229 | projectDirPath = ""; 230 | projectRoot = ""; 231 | targets = ( 232 | 8427E4CD1974C52C006CF8C6 /* PDChartDemo */, 233 | 8427E4DF1974C52C006CF8C6 /* PDChartDemoTests */, 234 | ); 235 | }; 236 | /* End PBXProject section */ 237 | 238 | /* Begin PBXResourcesBuildPhase section */ 239 | 8427E4CC1974C52C006CF8C6 /* Resources */ = { 240 | isa = PBXResourcesBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | 983857691D267ABB0008287D /* Launch Screen.storyboard in Resources */, 244 | 8427E4DB1974C52C006CF8C6 /* Images.xcassets in Resources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | 8427E4DE1974C52C006CF8C6 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | /* End PBXResourcesBuildPhase section */ 256 | 257 | /* Begin PBXSourcesBuildPhase section */ 258 | 8427E4CA1974C52C006CF8C6 /* Sources */ = { 259 | isa = PBXSourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 8427E4F61974C5F6006CF8C6 /* MainViewController.swift in Sources */, 263 | 8427E5041974C5FD006CF8C6 /* PDChartAxesComponent.swift in Sources */, 264 | 8427E4F21974C588006CF8C6 /* Define.swift in Sources */, 265 | 8427E5021974C5FD006CF8C6 /* PDBarChart.swift in Sources */, 266 | 8427E5031974C5FD006CF8C6 /* PDChart.swift in Sources */, 267 | 8427E4D41974C52C006CF8C6 /* AppDelegate.swift in Sources */, 268 | 8427E5051974C5FD006CF8C6 /* PDLineChart.swift in Sources */, 269 | 8427E5061974C5FD006CF8C6 /* PDPieChart.swift in Sources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | 8427E4DC1974C52C006CF8C6 /* Sources */ = { 274 | isa = PBXSourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | 8427E4E71974C52C006CF8C6 /* PDChartDemoTests.swift in Sources */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | /* End PBXSourcesBuildPhase section */ 282 | 283 | /* Begin PBXTargetDependency section */ 284 | 8427E4E21974C52C006CF8C6 /* PBXTargetDependency */ = { 285 | isa = PBXTargetDependency; 286 | target = 8427E4CD1974C52C006CF8C6 /* PDChartDemo */; 287 | targetProxy = 8427E4E11974C52C006CF8C6 /* PBXContainerItemProxy */; 288 | }; 289 | /* End PBXTargetDependency section */ 290 | 291 | /* Begin XCBuildConfiguration section */ 292 | 8427E4E81974C52C006CF8C6 /* Debug */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | ALWAYS_SEARCH_USER_PATHS = NO; 296 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 297 | CLANG_CXX_LIBRARY = "libc++"; 298 | CLANG_ENABLE_MODULES = YES; 299 | CLANG_ENABLE_OBJC_ARC = YES; 300 | CLANG_WARN_BOOL_CONVERSION = YES; 301 | CLANG_WARN_CONSTANT_CONVERSION = YES; 302 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 303 | CLANG_WARN_EMPTY_BODY = YES; 304 | CLANG_WARN_ENUM_CONVERSION = YES; 305 | CLANG_WARN_INT_CONVERSION = YES; 306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 307 | CLANG_WARN_UNREACHABLE_CODE = YES; 308 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 309 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 310 | COPY_PHASE_STRIP = NO; 311 | ENABLE_STRICT_OBJC_MSGSEND = YES; 312 | ENABLE_TESTABILITY = YES; 313 | GCC_C_LANGUAGE_STANDARD = gnu99; 314 | GCC_DYNAMIC_NO_PIC = NO; 315 | GCC_OPTIMIZATION_LEVEL = 0; 316 | GCC_PREPROCESSOR_DEFINITIONS = ( 317 | "DEBUG=1", 318 | "$(inherited)", 319 | ); 320 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 328 | MTL_ENABLE_DEBUG_INFO = YES; 329 | ONLY_ACTIVE_ARCH = YES; 330 | SDKROOT = iphoneos; 331 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 332 | }; 333 | name = Debug; 334 | }; 335 | 8427E4E91974C52C006CF8C6 /* Release */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 340 | CLANG_CXX_LIBRARY = "libc++"; 341 | CLANG_ENABLE_MODULES = YES; 342 | CLANG_ENABLE_OBJC_ARC = YES; 343 | CLANG_WARN_BOOL_CONVERSION = YES; 344 | CLANG_WARN_CONSTANT_CONVERSION = YES; 345 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 346 | CLANG_WARN_EMPTY_BODY = YES; 347 | CLANG_WARN_ENUM_CONVERSION = YES; 348 | CLANG_WARN_INT_CONVERSION = YES; 349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 350 | CLANG_WARN_UNREACHABLE_CODE = YES; 351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 352 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 353 | COPY_PHASE_STRIP = YES; 354 | ENABLE_NS_ASSERTIONS = NO; 355 | ENABLE_STRICT_OBJC_MSGSEND = YES; 356 | GCC_C_LANGUAGE_STANDARD = gnu99; 357 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 358 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 359 | GCC_WARN_UNDECLARED_SELECTOR = YES; 360 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 361 | GCC_WARN_UNUSED_FUNCTION = YES; 362 | GCC_WARN_UNUSED_VARIABLE = YES; 363 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 364 | MTL_ENABLE_DEBUG_INFO = NO; 365 | SDKROOT = iphoneos; 366 | VALIDATE_PRODUCT = YES; 367 | }; 368 | name = Release; 369 | }; 370 | 8427E4EB1974C52C006CF8C6 /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 374 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 375 | INFOPLIST_FILE = PDChartDemo/Info.plist; 376 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 377 | PRODUCT_BUNDLE_IDENTIFIER = "pandara.${PRODUCT_NAME:rfc1034identifier}"; 378 | PRODUCT_NAME = "$(TARGET_NAME)"; 379 | }; 380 | name = Debug; 381 | }; 382 | 8427E4EC1974C52C006CF8C6 /* Release */ = { 383 | isa = XCBuildConfiguration; 384 | buildSettings = { 385 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 386 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 387 | INFOPLIST_FILE = PDChartDemo/Info.plist; 388 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 389 | PRODUCT_BUNDLE_IDENTIFIER = "pandara.${PRODUCT_NAME:rfc1034identifier}"; 390 | PRODUCT_NAME = "$(TARGET_NAME)"; 391 | }; 392 | name = Release; 393 | }; 394 | 8427E4EE1974C52C006CF8C6 /* Debug */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/PDChartDemo.app/PDChartDemo"; 398 | FRAMEWORK_SEARCH_PATHS = ( 399 | "$(SDKROOT)/Developer/Library/Frameworks", 400 | "$(inherited)", 401 | ); 402 | GCC_PREPROCESSOR_DEFINITIONS = ( 403 | "DEBUG=1", 404 | "$(inherited)", 405 | ); 406 | INFOPLIST_FILE = PDChartDemoTests/Info.plist; 407 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 408 | PRODUCT_BUNDLE_IDENTIFIER = "pandara.${PRODUCT_NAME:rfc1034identifier}"; 409 | PRODUCT_NAME = "$(TARGET_NAME)"; 410 | TEST_HOST = "$(BUNDLE_LOADER)"; 411 | }; 412 | name = Debug; 413 | }; 414 | 8427E4EF1974C52C006CF8C6 /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/PDChartDemo.app/PDChartDemo"; 418 | FRAMEWORK_SEARCH_PATHS = ( 419 | "$(SDKROOT)/Developer/Library/Frameworks", 420 | "$(inherited)", 421 | ); 422 | INFOPLIST_FILE = PDChartDemoTests/Info.plist; 423 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 424 | PRODUCT_BUNDLE_IDENTIFIER = "pandara.${PRODUCT_NAME:rfc1034identifier}"; 425 | PRODUCT_NAME = "$(TARGET_NAME)"; 426 | TEST_HOST = "$(BUNDLE_LOADER)"; 427 | }; 428 | name = Release; 429 | }; 430 | /* End XCBuildConfiguration section */ 431 | 432 | /* Begin XCConfigurationList section */ 433 | 8427E4C91974C52C006CF8C6 /* Build configuration list for PBXProject "PDChartDemo" */ = { 434 | isa = XCConfigurationList; 435 | buildConfigurations = ( 436 | 8427E4E81974C52C006CF8C6 /* Debug */, 437 | 8427E4E91974C52C006CF8C6 /* Release */, 438 | ); 439 | defaultConfigurationIsVisible = 0; 440 | defaultConfigurationName = Release; 441 | }; 442 | 8427E4EA1974C52C006CF8C6 /* Build configuration list for PBXNativeTarget "PDChartDemo" */ = { 443 | isa = XCConfigurationList; 444 | buildConfigurations = ( 445 | 8427E4EB1974C52C006CF8C6 /* Debug */, 446 | 8427E4EC1974C52C006CF8C6 /* Release */, 447 | ); 448 | defaultConfigurationIsVisible = 0; 449 | defaultConfigurationName = Release; 450 | }; 451 | 8427E4ED1974C52C006CF8C6 /* Build configuration list for PBXNativeTarget "PDChartDemoTests" */ = { 452 | isa = XCConfigurationList; 453 | buildConfigurations = ( 454 | 8427E4EE1974C52C006CF8C6 /* Debug */, 455 | 8427E4EF1974C52C006CF8C6 /* Release */, 456 | ); 457 | defaultConfigurationIsVisible = 0; 458 | defaultConfigurationName = Release; 459 | }; 460 | /* End XCConfigurationList section */ 461 | }; 462 | rootObject = 8427E4C61974C52C006CF8C6 /* Project object */; 463 | } 464 | -------------------------------------------------------------------------------- /PDChartDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PDChartDemo 4 | // 5 | // Created by Pandara on 14-7-15. 6 | // Copyright (c) 2014年 Pandara. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | var mainViewController: MainViewController! 16 | var navigationController: UINavigationController! 17 | 18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 19 | self.window = UIWindow(frame: UIScreen.mainScreen().bounds) 20 | // Override point for customization after application launch. 21 | self.window!.backgroundColor = UIColor.whiteColor() 22 | 23 | self.navigationController = UINavigationController() 24 | self.mainViewController = MainViewController() 25 | self.navigationController!.pushViewController(self.mainViewController, animated: false) 26 | self.window!.rootViewController = self.navigationController 27 | 28 | self.window!.makeKeyAndVisible() 29 | return true 30 | } 31 | 32 | func applicationWillResignActive(application: UIApplication) { 33 | // 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. 34 | // 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. 35 | } 36 | 37 | func applicationDidEnterBackground(application: UIApplication) { 38 | // 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. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | func applicationWillEnterForeground(application: UIApplication) { 43 | // 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. 44 | } 45 | 46 | func applicationDidBecomeActive(application: UIApplication) { 47 | // 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. 48 | } 49 | 50 | func applicationWillTerminate(application: UIApplication) { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /PDChartDemo/Common/Define.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Define.swift 3 | // PDChartDemo 4 | // 5 | // Created by Pandara on 14-7-15. 6 | // Copyright (c) 2014年 Pandara. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /PDChartDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "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 | } -------------------------------------------------------------------------------- /PDChartDemo/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PDChartDemo/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 | Launch Screen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /PDChartDemo/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /PDChartDemo/MainViewController/MainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.swift 3 | // Swift_iPhone_demo 4 | // 5 | // Created by Pandara on 14-7-2. 6 | // Copyright (c) 2014年 Pandara. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainViewController: UIViewController { 12 | 13 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { 14 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 15 | } 16 | 17 | required init?(coder aDecoder: NSCoder) { 18 | fatalError("init(coder:) has not been implemented") 19 | } 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | let tableView: UITableView = UITableView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)) 25 | tableView.backgroundColor = UIColor.clearColor() 26 | tableView.delegate = self 27 | tableView.dataSource = self 28 | self.view.addSubview(tableView) 29 | } 30 | 31 | override func didReceiveMemoryWarning() { 32 | super.didReceiveMemoryWarning() 33 | } 34 | 35 | 36 | //MARK: Charts 37 | func getLineChart() -> PDLineChart { 38 | let dataItem: PDLineChartDataItem = PDLineChartDataItem() 39 | dataItem.xMax = 7.0 40 | dataItem.xInterval = 1.0 41 | dataItem.yMax = 100.0 42 | dataItem.yInterval = 10.0 43 | dataItem.pointArray = [CGPoint(x: 1.0, y: 95.0), CGPoint(x: 2.0, y: 25.0), CGPoint(x: 3.0, y: 30.0), CGPoint(x: 4.0, y:50.0), CGPoint(x: 5.0, y: 55.0), CGPoint(x: 6.0, y: 60.0), CGPoint(x: 7.0, y: 90.0)] 44 | dataItem.xAxesDegreeTexts = ["周日", "一", "二", "三", "四", "五", "周六"] 45 | dataItem.yAxesDegreeTexts = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] 46 | 47 | let frameW = self.view.frame.size.width 48 | let lineChart: PDLineChart = PDLineChart(frame: CGRectMake(0, 100, frameW, frameW), dataItem: dataItem) 49 | return lineChart 50 | } 51 | 52 | func getPieChart() -> PDPieChart { 53 | let dataItem: PDPieChartDataItem = PDPieChartDataItem() 54 | dataItem.pieWidth = 80 55 | dataItem.pieMargin = 50 56 | dataItem.dataArray = [PieDataItem(description: "first pie", color: lightGreen, percentage: 0.3), 57 | PieDataItem(description: nil, color: middleGreen, percentage: 0.1), 58 | PieDataItem(description: "third pie", color: deepGreen, percentage: 0.6)] 59 | 60 | let frameW = self.view.frame.size.width 61 | let pieChart: PDPieChart = PDPieChart(frame: CGRectMake(0, 100, frameW, frameW), dataItem: dataItem) 62 | return pieChart 63 | } 64 | 65 | func getBarChart() -> PDBarChart { 66 | let dataItem: PDBarChartDataItem = PDBarChartDataItem() 67 | dataItem.xMax = 7.0 68 | dataItem.xInterval = 1.0 69 | dataItem.yMax = 100.0 70 | dataItem.yInterval = 10.0 71 | dataItem.barPointArray = [CGPoint(x: 1.0, y: 95.0), CGPoint(x: 2.0, y: 25.0), CGPoint(x: 3.0, y: 30.0), CGPoint(x: 4.0, y:50.0), CGPoint(x: 5.0, y: 55.0), CGPoint(x: 6.0, y: 60.0), CGPoint(x: 7.0, y: 90.0)] 72 | dataItem.xAxesDegreeTexts = ["周日", "一", "二", "三", "四", "五", "周六"] 73 | dataItem.yAxesDegreeTexts = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] 74 | 75 | let frameW = self.view.frame.size.width 76 | let barChart: PDBarChart = PDBarChart(frame: CGRectMake(0, 100, frameW, frameW), dataItem: dataItem) 77 | return barChart 78 | } 79 | } 80 | 81 | extension MainViewController: UITableViewDelegate, UITableViewDataSource { 82 | func numberOfSectionsInTableView(tableView: UITableView) -> Int { 83 | return 1 84 | } 85 | 86 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 87 | return 3 88 | } 89 | 90 | func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 91 | return 45 92 | } 93 | 94 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 95 | var cell: UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell! 96 | if !(cell != nil) { 97 | cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell") 98 | } 99 | 100 | switch indexPath.row { 101 | case 0: 102 | cell.textLabel?.text = "折线图 - line chart" 103 | case 1: 104 | cell.textLabel?.text = "饼状图 - pie chart" 105 | case 2: 106 | cell.textLabel?.text = "柱状图 - bar chart" 107 | default: 108 | break 109 | } 110 | 111 | return cell 112 | } 113 | 114 | func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 115 | let viewCon: UIViewController = UIViewController() 116 | viewCon.view.backgroundColor = UIColor.whiteColor() 117 | 118 | var chart: PDChart! 119 | 120 | switch indexPath.row { 121 | case 0: 122 | let lineChart: PDLineChart = self.getLineChart() 123 | chart = lineChart 124 | viewCon.view.addSubview(lineChart) 125 | case 1: 126 | let pieChart: PDPieChart = self.getPieChart() 127 | chart = pieChart 128 | viewCon.view.addSubview(pieChart) 129 | case 2: 130 | let barChart: PDBarChart = self.getBarChart() 131 | chart = barChart 132 | viewCon.view.addSubview(barChart) 133 | default: 134 | break 135 | } 136 | 137 | chart.strokeChart() 138 | 139 | self.navigationController?.pushViewController(viewCon, animated: true) 140 | } 141 | } 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /PDChartDemo/PDChart/PDBarChart/PDBarChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDBarChart.swift 3 | // PDChart 4 | // 5 | // Created by Pandara on 14-7-11. 6 | // Copyright (c) 2014年 Pandara. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import QuartzCore 11 | 12 | class PDBarChartDataItem { 13 | //optional 14 | var axesColor: UIColor = UIColor(red: 80.0 / 255, green: 80.0 / 255, blue: 80.0 / 255, alpha: 1.0) //坐标轴颜色 15 | var axesTipColor: UIColor = UIColor(red: 80.0 / 255, green: 80.0 / 255, blue: 80.0 / 255, alpha: 1.0) //坐标轴刻度值颜色 16 | var chartLayerColor: UIColor = UIColor(red: 61.0 / 255, green: 189.0 / 255, blue: 100.0 / 255, alpha: 1.0) //折线的颜色 17 | 18 | var barBgColor: UIColor = UIColor(red: 234.0 / 255, green: 234.0 / 255, blue: 234.0 / 255, alpha: 1.0) 19 | var barColor: UIColor = UIColor(red: 69.0 / 255, green: 189.0 / 255, blue: 100.0 / 255, alpha: 1.0)//69 189 100 20 | 21 | var showAxes: Bool = true 22 | var axesWidth: CGFloat = 1.0 23 | 24 | var barMargin: CGFloat = 4.0 25 | var barWidth: CGFloat! 26 | 27 | var barCornerRadius: CGFloat = 0 28 | 29 | //require 30 | var xMax: CGFloat! 31 | var xInterval: CGFloat! 32 | 33 | var yMax: CGFloat! 34 | var yInterval: CGFloat! 35 | 36 | var xAxesDegreeTexts: [String]? 37 | var yAxesDegreeTexts: [String]? 38 | 39 | var barPointArray: [CGPoint]? 40 | 41 | init() { 42 | 43 | } 44 | } 45 | 46 | class PDBarChart: PDChart { 47 | 48 | var axesComponent: PDChartAxesComponent! 49 | var dataItem: PDBarChartDataItem! 50 | 51 | //property 52 | var barBgArray: [UIView] = [] 53 | var barLayerArray: [CAShapeLayer] = [] 54 | 55 | init(frame: CGRect, dataItem: PDBarChartDataItem) { 56 | super.init(frame: frame) 57 | self.dataItem = dataItem 58 | 59 | let axesDataItem: PDChartAxesComponentDataItem = PDChartAxesComponentDataItem() 60 | axesDataItem.arrowBodyLength += 10 61 | axesDataItem.targetView = self 62 | axesDataItem.featureH = getFeatureHeight() 63 | axesDataItem.featureW = getFeatureWidth() 64 | axesDataItem.xMax = dataItem.xMax 65 | axesDataItem.xInterval = dataItem.xInterval 66 | axesDataItem.yMax = dataItem.yMax 67 | axesDataItem.yInterval = dataItem.yInterval 68 | axesDataItem.xAxesDegreeTexts = dataItem.xAxesDegreeTexts 69 | axesDataItem.showXDegree = false 70 | axesDataItem.axesWidth = dataItem.axesWidth 71 | 72 | self.axesComponent = PDChartAxesComponent(dataItem: axesDataItem) 73 | 74 | //bar width 75 | let xDegreeInterval = self.axesComponent.getXDegreeInterval() 76 | self.dataItem.barWidth = xDegreeInterval - dataItem.barMargin * 2 77 | 78 | self.addBarBackgroundView() 79 | } 80 | 81 | required init?(coder aDecoder: NSCoder) { 82 | fatalError("init(coder:) has not been implemented") 83 | } 84 | 85 | func getFeatureWidth() -> CGFloat { 86 | return CGFloat(self.frame.size.width) 87 | } 88 | 89 | func getFeatureHeight() -> CGFloat { 90 | return CGFloat(self.frame.size.height) 91 | } 92 | 93 | func getBarView(frame: CGRect) -> UIView { 94 | let barView: UIView = UIView(frame: frame) 95 | barView.backgroundColor = self.dataItem.barBgColor 96 | barView.clipsToBounds = true 97 | barView.layer.cornerRadius = self.dataItem.barCornerRadius 98 | return barView 99 | } 100 | 101 | func getBarShapeLayer(layerFrame: CGRect, barHeight: CGFloat) -> CAShapeLayer { 102 | let shapeLayer: CAShapeLayer = CAShapeLayer() 103 | shapeLayer.fillColor = UIColor.whiteColor().CGColor 104 | shapeLayer.strokeColor = self.dataItem.barColor.CGColor 105 | shapeLayer.lineWidth = self.dataItem.barWidth 106 | shapeLayer.strokeStart = 0.0 107 | shapeLayer.strokeEnd = 1.0 108 | shapeLayer.frame = layerFrame 109 | 110 | let barPath: UIBezierPath = UIBezierPath() 111 | barPath.moveToPoint(CGPointMake(self.dataItem.barWidth / 2, layerFrame.size.height)) 112 | barPath.addLineToPoint(CGPointMake(self.dataItem.barWidth / 2, layerFrame.size.height - barHeight)) 113 | barPath.stroke() 114 | 115 | shapeLayer.path = barPath.CGPath 116 | 117 | return shapeLayer 118 | } 119 | 120 | func getBarAnimation() -> CABasicAnimation { 121 | CATransaction.begin() 122 | 123 | let pathAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd") 124 | pathAnimation.duration = 1.0 125 | pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 126 | pathAnimation.fromValue = 0.0 127 | pathAnimation.toValue = 1.0 128 | 129 | CATransaction.setCompletionBlock({ 130 | () -> Void in 131 | return 132 | }) 133 | 134 | CATransaction.commit() 135 | 136 | return pathAnimation 137 | } 138 | 139 | func addBarBackgroundView() { 140 | let xDegreeInterval: CGFloat = self.axesComponent.getXDegreeInterval() 141 | let basePoint: CGPoint = self.axesComponent.getBasePoint() 142 | let yAxesHeight: CGFloat = self.axesComponent.getYAxesHeight() 143 | 144 | for i in 0.. CGFloat {//heigth between 0~yMax 65 | let basePoint: CGPoint = self.getBasePoint() 66 | let yAxesHeight = basePoint.y - dataItem.arrowHeight - dataItem.yAxesTopMargin - dataItem.arrowBodyLength 67 | return yAxesHeight 68 | } 69 | 70 | func getXAxesWidth() -> CGFloat {//width between 0~xMax 71 | let basePoint: CGPoint = self.getBasePoint() 72 | let xAxesWidth = dataItem.featureW - basePoint.x - dataItem.arrowHeight - dataItem.xAxesRightMargin - dataItem.arrowBodyLength 73 | return xAxesWidth 74 | } 75 | 76 | func getBasePoint() -> CGPoint { 77 | 78 | var neededAxesWidth: CGFloat! 79 | if dataItem.showAxes { 80 | neededAxesWidth = CGFloat(dataItem.axesWidth) 81 | } else { 82 | neededAxesWidth = 0 83 | } 84 | 85 | let basePoint: CGPoint = CGPoint(x: dataItem.xAxesLeftMargin + neededAxesWidth / 2.0, y: dataItem.featureH - (dataItem.yAxesBottomMargin + neededAxesWidth / 2.0)) 86 | return basePoint 87 | } 88 | 89 | func getXDegreeInterval() -> CGFloat { 90 | let xAxesWidth: CGFloat = self.getXAxesWidth() 91 | let xDegreeInterval: CGFloat = dataItem.xInterval / dataItem.xMax * xAxesWidth 92 | return xDegreeInterval 93 | } 94 | 95 | func getYDegreeInterval() -> CGFloat { 96 | let yAxesHeight: CGFloat = self.getYAxesHeight() 97 | let yDegreeInterval: CGFloat = dataItem.yInterval / dataItem.yMax * yAxesHeight 98 | return yDegreeInterval 99 | } 100 | 101 | func getAxesDegreeTipLabel(tipText: String, center: CGPoint, size: CGSize, fontSize: CGFloat, textAlignment: NSTextAlignment, textColor: UIColor) -> UILabel { 102 | let label: UILabel = UILabel(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: size)) 103 | label.text = tipText 104 | label.center = center 105 | label.textAlignment = textAlignment 106 | label.textColor = textColor 107 | label.backgroundColor = UIColor.clearColor() 108 | label.adjustsFontSizeToFitWidth = true 109 | label.font = UIFont.systemFontOfSize(fontSize) 110 | return label 111 | } 112 | 113 | func getXAxesDegreeTipLabel(tipText: String, center: CGPoint, size: CGSize, fontSize: CGFloat) -> UILabel { 114 | return self.getAxesDegreeTipLabel(tipText, center: center, size: size, fontSize: fontSize, textAlignment: NSTextAlignment.Center, textColor: dataItem.axesTipColor) 115 | } 116 | 117 | func getYAxesDegreeTipLabel(tipText: String, center: CGPoint, size: CGSize, fontSize: CGFloat) -> UILabel { 118 | return self.getAxesDegreeTipLabel(tipText, center: center, size: size, fontSize: fontSize, textAlignment: NSTextAlignment.Right, textColor: dataItem.axesTipColor) 119 | } 120 | 121 | func strokeAxes(context: CGContextRef?) { 122 | let xAxesWidth: CGFloat = self.getXAxesWidth() 123 | let yAxesHeight: CGFloat = self.getYAxesHeight() 124 | let basePoint: CGPoint = self.getBasePoint() 125 | 126 | 127 | if dataItem.showAxes { 128 | CGContextSetStrokeColorWithColor(context, dataItem.axesColor.CGColor) 129 | CGContextSetFillColorWithColor(context, dataItem.axesColor.CGColor) 130 | 131 | let axesPath: UIBezierPath = UIBezierPath() 132 | axesPath.lineWidth = dataItem.axesWidth 133 | axesPath.lineCapStyle = CGLineCap.Round 134 | axesPath.lineJoinStyle = CGLineJoin.Round 135 | 136 | //x axes-------------------------------------- 137 | axesPath.moveToPoint(CGPoint(x: basePoint.x, y: basePoint.y)) 138 | axesPath.addLineToPoint(CGPoint(x: basePoint.x + xAxesWidth, y: basePoint.y)) 139 | 140 | //degrees in x axes 141 | let xDegreeNum: Int = Int((dataItem.xMax - (dataItem.xMax % dataItem.xInterval)) / dataItem.xInterval) 142 | let xDegreeInterval: CGFloat = self.getXDegreeInterval() 143 | 144 | if dataItem.showXDegree { 145 | for i in 0.. UILabel { 199 | if (dataItem.xAxesDegreeTexts != nil) { 200 | for i in 0.. CGFloat { 65 | return CGFloat(self.frame.size.width) 66 | } 67 | 68 | func getFeatureHeight() -> CGFloat { 69 | return CGFloat(self.frame.size.height) 70 | } 71 | 72 | override func strokeChart() { 73 | if !(self.dataItem.pointArray != nil) { 74 | return 75 | } 76 | 77 | //绘图layer 78 | let chartLayer: CAShapeLayer = CAShapeLayer() 79 | chartLayer.lineCap = kCALineCapRound 80 | chartLayer.lineJoin = kCALineJoinRound 81 | chartLayer.fillColor = UIColor.whiteColor().CGColor 82 | chartLayer.strokeColor = self.dataItem.chartLayerColor.CGColor 83 | chartLayer.lineWidth = 2.0 84 | chartLayer.strokeStart = 0.0 85 | chartLayer.strokeEnd = 1.0 86 | self.layer.addSublayer(chartLayer) 87 | 88 | //画线段 89 | UIGraphicsBeginImageContext(self.frame.size) 90 | 91 | let progressLine: UIBezierPath = UIBezierPath() 92 | 93 | let basePoint: CGPoint = axesComponent.getBasePoint() 94 | let xAxesWidth: CGFloat = axesComponent.getXAxesWidth() 95 | let yAxesHeight: CGFloat = axesComponent.getYAxesHeight() 96 | for i in 0.. Void)!) 124 | CATransaction.setCompletionBlock({ 125 | () -> Void in 126 | }) 127 | CATransaction.commit() 128 | 129 | UIGraphicsEndImageContext() 130 | } 131 | 132 | override func drawRect(rect: CGRect) { 133 | super.drawRect(rect) 134 | 135 | let context: CGContext = UIGraphicsGetCurrentContext()! 136 | axesComponent.strokeAxes(context) 137 | } 138 | } 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /PDChartDemo/PDChart/PDPieChart/PDPieChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDPieChart.swift 3 | // Swift_iPhone_demo 4 | // 5 | // Created by Pandara on 14-7-7. 6 | // Copyright (c) 2014年 Pandara. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import QuartzCore 11 | 12 | struct PieDataItem { 13 | var description: String? 14 | var color: UIColor? 15 | var percentage: CGFloat! 16 | } 17 | 18 | let lightGreen: UIColor = UIColor(red: 69.0 / 255, green: 212.0 / 255, blue: 103.0 / 255, alpha: 1.0) 19 | let middleGreen: UIColor = UIColor(red: 66.0 / 255, green: 187.0 / 255, blue: 102.0 / 255, alpha: 1.0) 20 | let deepGreen: UIColor = UIColor(red: 64.0 / 255, green: 164.0 / 255, blue: 102.0 / 255, alpha: 1.0) 21 | 22 | class PDPieChartDataItem { 23 | //optional 24 | var animationDur: CGFloat = 1.0 25 | var clockWise: Bool = true 26 | var chartStartAngle: CGFloat = CGFloat(-M_PI / 2) 27 | var pieTipFontSize: CGFloat = 20.0 28 | var pieTipTextColor: UIColor = UIColor.whiteColor() 29 | var pieMargin: CGFloat = 0 30 | 31 | //required 32 | var pieWidth: CGFloat! 33 | var dataArray: [PieDataItem]! 34 | 35 | init() { 36 | 37 | } 38 | } 39 | 40 | class PDPieChart: PDChart { 41 | var dataItem: PDPieChartDataItem! 42 | 43 | init(frame: CGRect, dataItem: PDPieChartDataItem) { 44 | super.init(frame: frame) 45 | self.dataItem = dataItem 46 | } 47 | 48 | required init?(coder aDecoder: NSCoder) { 49 | fatalError("init(coder:) has not been implemented") 50 | } 51 | 52 | func getShapeLayerWithARCPath(color: UIColor?, lineWidth: CGFloat, center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockWise: Bool) -> CAShapeLayer { 53 | //layer 54 | let pathLayer: CAShapeLayer = CAShapeLayer() 55 | pathLayer.lineCap = kCALineCapButt 56 | pathLayer.fillColor = UIColor.clearColor().CGColor 57 | if (color != nil) { 58 | pathLayer.strokeColor = color!.CGColor 59 | } 60 | pathLayer.lineWidth = self.dataItem.pieWidth 61 | pathLayer.strokeStart = 0.0 62 | pathLayer.strokeEnd = 1.0 63 | pathLayer.backgroundColor = UIColor.clearColor().CGColor 64 | 65 | //path 66 | let path: UIBezierPath = UIBezierPath() 67 | path.lineWidth = lineWidth 68 | path.addArcWithCenter(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: self.dataItem.clockWise) 69 | path.stroke() 70 | 71 | pathLayer.path = path.CGPath 72 | return pathLayer 73 | } 74 | 75 | override func strokeChart() { 76 | var pieCenterPointArray: [CGPoint] = [] 77 | let radius: CGFloat = self.frame.size.width / 2 - self.dataItem.pieMargin - self.dataItem.pieWidth / 2 78 | let center: CGPoint = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2) 79 | 80 | let chartLayer: CAShapeLayer = CAShapeLayer() 81 | chartLayer.backgroundColor = UIColor.clearColor().CGColor 82 | self.layer.addSublayer(chartLayer) 83 | 84 | UIGraphicsBeginImageContext(self.frame.size) 85 | //每一段饼 86 | var totalPercentage: CGFloat = 0.0 87 | for i in 0.. Void in 148 | pieTipLabel.alpha = 1.0 149 | }, completion: { 150 | (completion: Bool) -> Void in 151 | return 152 | }) 153 | 154 | self.addSubview(pieTipLabel) 155 | } 156 | } 157 | 158 | override func drawRect(rect: CGRect) { 159 | super.drawRect(rect) 160 | } 161 | 162 | } 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /PDChartDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /PDChartDemoTests/PDChartDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PDChartDemoTests.swift 3 | // PDChartDemoTests 4 | // 5 | // Created by Pandara on 14-7-15. 6 | // Copyright (c) 2014年 Pandara. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class PDChartDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PDChart - Chart lib for iOS in Swift 2 | --- 3 | A simple and beautiful chart lib for iOS, developed in Swift,refering to [PNChart](https://github.com/kevinzhow/PNChart/) 4 | 5 | **Recently updated to support Swift2.2** 6 | 7 | ![PDChartDemo][1] 8 | 9 | 10 | ## Requirements 11 | 12 | PDChart works on iOS 7.0 and later version. It depends on the following Apple frameworks, which should already be included with most Xcode templates: 13 | 14 | * Foundation.framework 15 | * UIKit.framework 16 | * CoreGraphics.framework 17 | * QuartzCore.framework 18 | 19 | You will need LLVM 3.0 or later in order to build PDChart. 20 | 21 | 22 | 23 | 24 | ## Usage 25 | 26 | ### Copy the PDChart folder to your project 27 | 28 | ![lineChart][2] 29 | 30 | ```swift 31 | //for lineChart 32 | 33 | var dataItem: PDLineChartDataItem = PDLineChartDataItem() 34 | dataItem.xMax = 7.0 35 | dataItem.xInterval = 1.0 36 | dataItem.yMax = 100.0 37 | dataItem.yInterval = 10.0 38 | dataItem.pointArray = [CGPoint(x: 1.0, y: 95.0), CGPoint(x: 2.0, y: 25.0), CGPoint(x: 3.0, y: 30.0), CGPoint(x: 4.0, y:50.0), CGPoint(x: 5.0, y: 55.0), CGPoint(x: 6.0, y: 60.0), CGPoint(x: 7.0, y: 90.0)] 39 | dataItem.xAxesDegreeTexts = ["周日", "一", "二", "三", "四", "五", "周六"] 40 | dataItem.yAxesDegreeTexts = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] 41 | 42 | var lineChart: PDLineChart = PDLineChart(frame: CGRectMake(0, 100, 320, 320), dataItem: dataItem) 43 | 44 | self.view.addSubview(lineChart) 45 | lineChart.strokeChart() 46 | 47 | ``` 48 | 49 | ![barChart][3] 50 | 51 | ```swift 52 | //for barChart 53 | 54 | var dataItem: PDBarChartDataItem = PDBarChartDataItem() 55 | dataItem.xMax = 7.0 56 | dataItem.xInterval = 1.0 57 | dataItem.yMax = 100.0 58 | dataItem.yInterval = 10.0 59 | dataItem.barPointArray = [CGPoint(x: 1.0, y: 95.0), CGPoint(x: 2.0, y: 25.0), CGPoint(x: 3.0, y: 30.0), CGPoint(x: 4.0, y:50.0), CGPoint(x: 5.0, y: 55.0), CGPoint(x: 6.0, y: 60.0), CGPoint(x: 7.0, y: 90.0)] 60 | dataItem.xAxesDegreeTexts = ["周日", "一", "二", "三", "四", "五", "周六"] 61 | dataItem.yAxesDegreeTexts = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"] 62 | 63 | var barChart: PDBarChart = PDBarChart(frame: CGRectMake(0, 100, 320, 320), dataItem: dataItem) 64 | 65 | self.view.addSubview(barChart) 66 | barChart.addSubview(barChart) 67 | 68 | ``` 69 | 70 | ![pieChart][4] 71 | 72 | ```swift 73 | //for pieChart 74 | 75 | var dataItem: PDPieChartDataItem = PDPieChartDataItem() 76 | dataItem.pieWidth = 80 77 | dataItem.pieMargin = 50 78 | dataItem.dataArray = [PieDataItem(description: "first pie", color: lightGreen, percentage: 0.3), 79 | PieDataItem(description: nil, color: middleGreen, percentage: 0.1), 80 | PieDataItem(description: "third pie", color: deepGreen, percentage: 0.6)] 81 | var pieChart: PDPieChart = PDPieChart(frame: CGRectMake(0, 100, 320, 320), dataItem: dataItem) 82 | ``` 83 | 84 | ## License 85 | 86 | This code is distributed under the terms and conditions of the [MIT license](LICENSE). 87 | 88 | ## SpecialThanks 89 | [@kevinzhow](https://github.com/kevinzhow/PNChart/) PNChart 90 | 91 | 92 | [1]: http://o97h12868.bkt.clouddn.com/PDChart/pdchart.gif 93 | [2]: http://o97h12868.bkt.clouddn.com/PDChart/line_chart.png?imageView2/2/w/375 94 | [3]: http://o97h12868.bkt.clouddn.com/PDChart/bar_chart.png?imageView2/2/w/375 95 | [4]: http://o97h12868.bkt.clouddn.com/PDChart/pie_chart.png?imageView2/2/w/375 --------------------------------------------------------------------------------