├── ARLineChartDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── jun.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── jun.xcuserdatad │ └── xcschemes │ ├── ARLineChartDemo.xcscheme │ └── xcschememanagement.plist ├── ARLineChartDemo ├── ARAppDelegate.h ├── ARAppDelegate.m ├── ARLineChart │ ├── ARLineChartCommon.h │ ├── ARLineChartCommon.m │ ├── ARLineChartContentView.h │ ├── ARLineChartContentView.m │ ├── ARLineChartView.h │ └── ARLineChartView.m ├── ARLineChartDemo-Info.plist ├── ARLineChartDemo-Prefix.pch ├── ARViewController.h ├── ARViewController.m ├── Base.lproj │ ├── Main_iPad.storyboard │ └── Main_iPhone.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── en.lproj │ └── InfoPlist.strings └── main.m ├── ARLineChartDemoTests ├── ARLineChartDemoTests-Info.plist ├── ARLineChartDemoTests.m └── en.lproj │ └── InfoPlist.strings ├── LICENSE.md ├── README.md ├── Screenshot01.png └── Screenshot02.png /ARLineChartDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BF9DDA7C18ADAE20004DE974 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9DDA7B18ADAE20004DE974 /* Foundation.framework */; }; 11 | BF9DDA7E18ADAE20004DE974 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9DDA7D18ADAE20004DE974 /* CoreGraphics.framework */; }; 12 | BF9DDA8018ADAE20004DE974 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9DDA7F18ADAE20004DE974 /* UIKit.framework */; }; 13 | BF9DDA8618ADAE20004DE974 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF9DDA8418ADAE20004DE974 /* InfoPlist.strings */; }; 14 | BF9DDA8818ADAE20004DE974 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDA8718ADAE20004DE974 /* main.m */; }; 15 | BF9DDA8C18ADAE20004DE974 /* ARAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDA8B18ADAE20004DE974 /* ARAppDelegate.m */; }; 16 | BF9DDA8F18ADAE20004DE974 /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF9DDA8D18ADAE20004DE974 /* Main_iPhone.storyboard */; }; 17 | BF9DDA9218ADAE20004DE974 /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF9DDA9018ADAE20004DE974 /* Main_iPad.storyboard */; }; 18 | BF9DDA9518ADAE20004DE974 /* ARViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDA9418ADAE20004DE974 /* ARViewController.m */; }; 19 | BF9DDA9718ADAE20004DE974 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF9DDA9618ADAE20004DE974 /* Images.xcassets */; }; 20 | BF9DDA9E18ADAE20004DE974 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9DDA9D18ADAE20004DE974 /* XCTest.framework */; }; 21 | BF9DDA9F18ADAE20004DE974 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9DDA7B18ADAE20004DE974 /* Foundation.framework */; }; 22 | BF9DDAA018ADAE20004DE974 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF9DDA7F18ADAE20004DE974 /* UIKit.framework */; }; 23 | BF9DDAA818ADAE20004DE974 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BF9DDAA618ADAE20004DE974 /* InfoPlist.strings */; }; 24 | BF9DDAAA18ADAE20004DE974 /* ARLineChartDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDAA918ADAE20004DE974 /* ARLineChartDemoTests.m */; }; 25 | BF9DDABA18ADAE56004DE974 /* ARLineChartCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDAB518ADAE56004DE974 /* ARLineChartCommon.m */; }; 26 | BF9DDABB18ADAE56004DE974 /* ARLineChartContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDAB718ADAE56004DE974 /* ARLineChartContentView.m */; }; 27 | BF9DDABC18ADAE56004DE974 /* ARLineChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DDAB918ADAE56004DE974 /* ARLineChartView.m */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | BF9DDAA118ADAE20004DE974 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = BF9DDA7018ADAE20004DE974 /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = BF9DDA7718ADAE20004DE974; 36 | remoteInfo = ARLineChartDemo; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | BF9DDA7818ADAE20004DE974 /* ARLineChartDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ARLineChartDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | BF9DDA7B18ADAE20004DE974 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 43 | BF9DDA7D18ADAE20004DE974 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 44 | BF9DDA7F18ADAE20004DE974 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 45 | BF9DDA8318ADAE20004DE974 /* ARLineChartDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ARLineChartDemo-Info.plist"; sourceTree = ""; }; 46 | BF9DDA8518ADAE20004DE974 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 47 | BF9DDA8718ADAE20004DE974 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | BF9DDA8918ADAE20004DE974 /* ARLineChartDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ARLineChartDemo-Prefix.pch"; sourceTree = ""; }; 49 | BF9DDA8A18ADAE20004DE974 /* ARAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ARAppDelegate.h; sourceTree = ""; }; 50 | BF9DDA8B18ADAE20004DE974 /* ARAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARAppDelegate.m; sourceTree = ""; }; 51 | BF9DDA8E18ADAE20004DE974 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = ""; }; 52 | BF9DDA9118ADAE20004DE974 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = ""; }; 53 | BF9DDA9318ADAE20004DE974 /* ARViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ARViewController.h; sourceTree = ""; }; 54 | BF9DDA9418ADAE20004DE974 /* ARViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARViewController.m; sourceTree = ""; }; 55 | BF9DDA9618ADAE20004DE974 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 56 | BF9DDA9C18ADAE20004DE974 /* ARLineChartDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ARLineChartDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | BF9DDA9D18ADAE20004DE974 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 58 | BF9DDAA518ADAE20004DE974 /* ARLineChartDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ARLineChartDemoTests-Info.plist"; sourceTree = ""; }; 59 | BF9DDAA718ADAE20004DE974 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 60 | BF9DDAA918ADAE20004DE974 /* ARLineChartDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ARLineChartDemoTests.m; sourceTree = ""; }; 61 | BF9DDAB418ADAE56004DE974 /* ARLineChartCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARLineChartCommon.h; sourceTree = ""; }; 62 | BF9DDAB518ADAE56004DE974 /* ARLineChartCommon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARLineChartCommon.m; sourceTree = ""; }; 63 | BF9DDAB618ADAE56004DE974 /* ARLineChartContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARLineChartContentView.h; sourceTree = ""; }; 64 | BF9DDAB718ADAE56004DE974 /* ARLineChartContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARLineChartContentView.m; sourceTree = ""; }; 65 | BF9DDAB818ADAE56004DE974 /* ARLineChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARLineChartView.h; sourceTree = ""; }; 66 | BF9DDAB918ADAE56004DE974 /* ARLineChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARLineChartView.m; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | BF9DDA7518ADAE20004DE974 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | BF9DDA7E18ADAE20004DE974 /* CoreGraphics.framework in Frameworks */, 75 | BF9DDA8018ADAE20004DE974 /* UIKit.framework in Frameworks */, 76 | BF9DDA7C18ADAE20004DE974 /* Foundation.framework in Frameworks */, 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | BF9DDA9918ADAE20004DE974 /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | BF9DDA9E18ADAE20004DE974 /* XCTest.framework in Frameworks */, 85 | BF9DDAA018ADAE20004DE974 /* UIKit.framework in Frameworks */, 86 | BF9DDA9F18ADAE20004DE974 /* Foundation.framework in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | /* End PBXFrameworksBuildPhase section */ 91 | 92 | /* Begin PBXGroup section */ 93 | BF9DDA6F18ADAE20004DE974 = { 94 | isa = PBXGroup; 95 | children = ( 96 | BF9DDA8118ADAE20004DE974 /* ARLineChartDemo */, 97 | BF9DDAA318ADAE20004DE974 /* ARLineChartDemoTests */, 98 | BF9DDA7A18ADAE20004DE974 /* Frameworks */, 99 | BF9DDA7918ADAE20004DE974 /* Products */, 100 | ); 101 | sourceTree = ""; 102 | }; 103 | BF9DDA7918ADAE20004DE974 /* Products */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | BF9DDA7818ADAE20004DE974 /* ARLineChartDemo.app */, 107 | BF9DDA9C18ADAE20004DE974 /* ARLineChartDemoTests.xctest */, 108 | ); 109 | name = Products; 110 | sourceTree = ""; 111 | }; 112 | BF9DDA7A18ADAE20004DE974 /* Frameworks */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | BF9DDA7B18ADAE20004DE974 /* Foundation.framework */, 116 | BF9DDA7D18ADAE20004DE974 /* CoreGraphics.framework */, 117 | BF9DDA7F18ADAE20004DE974 /* UIKit.framework */, 118 | BF9DDA9D18ADAE20004DE974 /* XCTest.framework */, 119 | ); 120 | name = Frameworks; 121 | sourceTree = ""; 122 | }; 123 | BF9DDA8118ADAE20004DE974 /* ARLineChartDemo */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | BF9DDAB318ADAE56004DE974 /* ARLineChart */, 127 | BF9DDA8A18ADAE20004DE974 /* ARAppDelegate.h */, 128 | BF9DDA8B18ADAE20004DE974 /* ARAppDelegate.m */, 129 | BF9DDA8D18ADAE20004DE974 /* Main_iPhone.storyboard */, 130 | BF9DDA9018ADAE20004DE974 /* Main_iPad.storyboard */, 131 | BF9DDA9318ADAE20004DE974 /* ARViewController.h */, 132 | BF9DDA9418ADAE20004DE974 /* ARViewController.m */, 133 | BF9DDA9618ADAE20004DE974 /* Images.xcassets */, 134 | BF9DDA8218ADAE20004DE974 /* Supporting Files */, 135 | ); 136 | path = ARLineChartDemo; 137 | sourceTree = ""; 138 | }; 139 | BF9DDA8218ADAE20004DE974 /* Supporting Files */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | BF9DDA8318ADAE20004DE974 /* ARLineChartDemo-Info.plist */, 143 | BF9DDA8418ADAE20004DE974 /* InfoPlist.strings */, 144 | BF9DDA8718ADAE20004DE974 /* main.m */, 145 | BF9DDA8918ADAE20004DE974 /* ARLineChartDemo-Prefix.pch */, 146 | ); 147 | name = "Supporting Files"; 148 | sourceTree = ""; 149 | }; 150 | BF9DDAA318ADAE20004DE974 /* ARLineChartDemoTests */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | BF9DDAA918ADAE20004DE974 /* ARLineChartDemoTests.m */, 154 | BF9DDAA418ADAE20004DE974 /* Supporting Files */, 155 | ); 156 | path = ARLineChartDemoTests; 157 | sourceTree = ""; 158 | }; 159 | BF9DDAA418ADAE20004DE974 /* Supporting Files */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | BF9DDAA518ADAE20004DE974 /* ARLineChartDemoTests-Info.plist */, 163 | BF9DDAA618ADAE20004DE974 /* InfoPlist.strings */, 164 | ); 165 | name = "Supporting Files"; 166 | sourceTree = ""; 167 | }; 168 | BF9DDAB318ADAE56004DE974 /* ARLineChart */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | BF9DDAB418ADAE56004DE974 /* ARLineChartCommon.h */, 172 | BF9DDAB518ADAE56004DE974 /* ARLineChartCommon.m */, 173 | BF9DDAB618ADAE56004DE974 /* ARLineChartContentView.h */, 174 | BF9DDAB718ADAE56004DE974 /* ARLineChartContentView.m */, 175 | BF9DDAB818ADAE56004DE974 /* ARLineChartView.h */, 176 | BF9DDAB918ADAE56004DE974 /* ARLineChartView.m */, 177 | ); 178 | path = ARLineChart; 179 | sourceTree = ""; 180 | }; 181 | /* End PBXGroup section */ 182 | 183 | /* Begin PBXNativeTarget section */ 184 | BF9DDA7718ADAE20004DE974 /* ARLineChartDemo */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = BF9DDAAD18ADAE20004DE974 /* Build configuration list for PBXNativeTarget "ARLineChartDemo" */; 187 | buildPhases = ( 188 | BF9DDA7418ADAE20004DE974 /* Sources */, 189 | BF9DDA7518ADAE20004DE974 /* Frameworks */, 190 | BF9DDA7618ADAE20004DE974 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = ARLineChartDemo; 197 | productName = ARLineChartDemo; 198 | productReference = BF9DDA7818ADAE20004DE974 /* ARLineChartDemo.app */; 199 | productType = "com.apple.product-type.application"; 200 | }; 201 | BF9DDA9B18ADAE20004DE974 /* ARLineChartDemoTests */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = BF9DDAB018ADAE20004DE974 /* Build configuration list for PBXNativeTarget "ARLineChartDemoTests" */; 204 | buildPhases = ( 205 | BF9DDA9818ADAE20004DE974 /* Sources */, 206 | BF9DDA9918ADAE20004DE974 /* Frameworks */, 207 | BF9DDA9A18ADAE20004DE974 /* Resources */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | BF9DDAA218ADAE20004DE974 /* PBXTargetDependency */, 213 | ); 214 | name = ARLineChartDemoTests; 215 | productName = ARLineChartDemoTests; 216 | productReference = BF9DDA9C18ADAE20004DE974 /* ARLineChartDemoTests.xctest */; 217 | productType = "com.apple.product-type.bundle.unit-test"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | BF9DDA7018ADAE20004DE974 /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | CLASSPREFIX = AR; 226 | LastUpgradeCheck = 0500; 227 | ORGANIZATIONNAME = "Arwer Software"; 228 | TargetAttributes = { 229 | BF9DDA9B18ADAE20004DE974 = { 230 | TestTargetID = BF9DDA7718ADAE20004DE974; 231 | }; 232 | }; 233 | }; 234 | buildConfigurationList = BF9DDA7318ADAE20004DE974 /* Build configuration list for PBXProject "ARLineChartDemo" */; 235 | compatibilityVersion = "Xcode 3.2"; 236 | developmentRegion = English; 237 | hasScannedForEncodings = 0; 238 | knownRegions = ( 239 | en, 240 | Base, 241 | ); 242 | mainGroup = BF9DDA6F18ADAE20004DE974; 243 | productRefGroup = BF9DDA7918ADAE20004DE974 /* Products */; 244 | projectDirPath = ""; 245 | projectRoot = ""; 246 | targets = ( 247 | BF9DDA7718ADAE20004DE974 /* ARLineChartDemo */, 248 | BF9DDA9B18ADAE20004DE974 /* ARLineChartDemoTests */, 249 | ); 250 | }; 251 | /* End PBXProject section */ 252 | 253 | /* Begin PBXResourcesBuildPhase section */ 254 | BF9DDA7618ADAE20004DE974 /* Resources */ = { 255 | isa = PBXResourcesBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | BF9DDA9218ADAE20004DE974 /* Main_iPad.storyboard in Resources */, 259 | BF9DDA9718ADAE20004DE974 /* Images.xcassets in Resources */, 260 | BF9DDA8F18ADAE20004DE974 /* Main_iPhone.storyboard in Resources */, 261 | BF9DDA8618ADAE20004DE974 /* InfoPlist.strings in Resources */, 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | BF9DDA9A18ADAE20004DE974 /* Resources */ = { 266 | isa = PBXResourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | BF9DDAA818ADAE20004DE974 /* InfoPlist.strings in Resources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | /* End PBXResourcesBuildPhase section */ 274 | 275 | /* Begin PBXSourcesBuildPhase section */ 276 | BF9DDA7418ADAE20004DE974 /* Sources */ = { 277 | isa = PBXSourcesBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | BF9DDA8818ADAE20004DE974 /* main.m in Sources */, 281 | BF9DDA9518ADAE20004DE974 /* ARViewController.m in Sources */, 282 | BF9DDA8C18ADAE20004DE974 /* ARAppDelegate.m in Sources */, 283 | BF9DDABC18ADAE56004DE974 /* ARLineChartView.m in Sources */, 284 | BF9DDABB18ADAE56004DE974 /* ARLineChartContentView.m in Sources */, 285 | BF9DDABA18ADAE56004DE974 /* ARLineChartCommon.m in Sources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | BF9DDA9818ADAE20004DE974 /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | BF9DDAAA18ADAE20004DE974 /* ARLineChartDemoTests.m in Sources */, 294 | ); 295 | runOnlyForDeploymentPostprocessing = 0; 296 | }; 297 | /* End PBXSourcesBuildPhase section */ 298 | 299 | /* Begin PBXTargetDependency section */ 300 | BF9DDAA218ADAE20004DE974 /* PBXTargetDependency */ = { 301 | isa = PBXTargetDependency; 302 | target = BF9DDA7718ADAE20004DE974 /* ARLineChartDemo */; 303 | targetProxy = BF9DDAA118ADAE20004DE974 /* PBXContainerItemProxy */; 304 | }; 305 | /* End PBXTargetDependency section */ 306 | 307 | /* Begin PBXVariantGroup section */ 308 | BF9DDA8418ADAE20004DE974 /* InfoPlist.strings */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | BF9DDA8518ADAE20004DE974 /* en */, 312 | ); 313 | name = InfoPlist.strings; 314 | sourceTree = ""; 315 | }; 316 | BF9DDA8D18ADAE20004DE974 /* Main_iPhone.storyboard */ = { 317 | isa = PBXVariantGroup; 318 | children = ( 319 | BF9DDA8E18ADAE20004DE974 /* Base */, 320 | ); 321 | name = Main_iPhone.storyboard; 322 | sourceTree = ""; 323 | }; 324 | BF9DDA9018ADAE20004DE974 /* Main_iPad.storyboard */ = { 325 | isa = PBXVariantGroup; 326 | children = ( 327 | BF9DDA9118ADAE20004DE974 /* Base */, 328 | ); 329 | name = Main_iPad.storyboard; 330 | sourceTree = ""; 331 | }; 332 | BF9DDAA618ADAE20004DE974 /* InfoPlist.strings */ = { 333 | isa = PBXVariantGroup; 334 | children = ( 335 | BF9DDAA718ADAE20004DE974 /* en */, 336 | ); 337 | name = InfoPlist.strings; 338 | sourceTree = ""; 339 | }; 340 | /* End PBXVariantGroup section */ 341 | 342 | /* Begin XCBuildConfiguration section */ 343 | BF9DDAAB18ADAE20004DE974 /* Debug */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | ALWAYS_SEARCH_USER_PATHS = NO; 347 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 348 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 349 | CLANG_CXX_LIBRARY = "libc++"; 350 | CLANG_ENABLE_MODULES = YES; 351 | CLANG_ENABLE_OBJC_ARC = YES; 352 | CLANG_WARN_BOOL_CONVERSION = YES; 353 | CLANG_WARN_CONSTANT_CONVERSION = YES; 354 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 355 | CLANG_WARN_EMPTY_BODY = YES; 356 | CLANG_WARN_ENUM_CONVERSION = YES; 357 | CLANG_WARN_INT_CONVERSION = YES; 358 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | GCC_C_LANGUAGE_STANDARD = gnu99; 363 | GCC_DYNAMIC_NO_PIC = NO; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 370 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 371 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 372 | GCC_WARN_UNDECLARED_SELECTOR = YES; 373 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 374 | GCC_WARN_UNUSED_FUNCTION = YES; 375 | GCC_WARN_UNUSED_VARIABLE = YES; 376 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 377 | ONLY_ACTIVE_ARCH = YES; 378 | SDKROOT = iphoneos; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | }; 381 | name = Debug; 382 | }; 383 | BF9DDAAC18ADAE20004DE974 /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 388 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 389 | CLANG_CXX_LIBRARY = "libc++"; 390 | CLANG_ENABLE_MODULES = YES; 391 | CLANG_ENABLE_OBJC_ARC = YES; 392 | CLANG_WARN_BOOL_CONVERSION = YES; 393 | CLANG_WARN_CONSTANT_CONVERSION = YES; 394 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 395 | CLANG_WARN_EMPTY_BODY = YES; 396 | CLANG_WARN_ENUM_CONVERSION = YES; 397 | CLANG_WARN_INT_CONVERSION = YES; 398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 399 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 400 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 401 | COPY_PHASE_STRIP = YES; 402 | ENABLE_NS_ASSERTIONS = NO; 403 | GCC_C_LANGUAGE_STANDARD = gnu99; 404 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 405 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 406 | GCC_WARN_UNDECLARED_SELECTOR = YES; 407 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 408 | GCC_WARN_UNUSED_FUNCTION = YES; 409 | GCC_WARN_UNUSED_VARIABLE = YES; 410 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 411 | SDKROOT = iphoneos; 412 | TARGETED_DEVICE_FAMILY = "1,2"; 413 | VALIDATE_PRODUCT = YES; 414 | }; 415 | name = Release; 416 | }; 417 | BF9DDAAE18ADAE20004DE974 /* Debug */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 421 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 422 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 423 | GCC_PREFIX_HEADER = "ARLineChartDemo/ARLineChartDemo-Prefix.pch"; 424 | INFOPLIST_FILE = "ARLineChartDemo/ARLineChartDemo-Info.plist"; 425 | PRODUCT_NAME = "$(TARGET_NAME)"; 426 | WRAPPER_EXTENSION = app; 427 | }; 428 | name = Debug; 429 | }; 430 | BF9DDAAF18ADAE20004DE974 /* Release */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 434 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 435 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 436 | GCC_PREFIX_HEADER = "ARLineChartDemo/ARLineChartDemo-Prefix.pch"; 437 | INFOPLIST_FILE = "ARLineChartDemo/ARLineChartDemo-Info.plist"; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | WRAPPER_EXTENSION = app; 440 | }; 441 | name = Release; 442 | }; 443 | BF9DDAB118ADAE20004DE974 /* Debug */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 447 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ARLineChartDemo.app/ARLineChartDemo"; 448 | FRAMEWORK_SEARCH_PATHS = ( 449 | "$(SDKROOT)/Developer/Library/Frameworks", 450 | "$(inherited)", 451 | "$(DEVELOPER_FRAMEWORKS_DIR)", 452 | ); 453 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 454 | GCC_PREFIX_HEADER = "ARLineChartDemo/ARLineChartDemo-Prefix.pch"; 455 | GCC_PREPROCESSOR_DEFINITIONS = ( 456 | "DEBUG=1", 457 | "$(inherited)", 458 | ); 459 | INFOPLIST_FILE = "ARLineChartDemoTests/ARLineChartDemoTests-Info.plist"; 460 | PRODUCT_NAME = "$(TARGET_NAME)"; 461 | TEST_HOST = "$(BUNDLE_LOADER)"; 462 | WRAPPER_EXTENSION = xctest; 463 | }; 464 | name = Debug; 465 | }; 466 | BF9DDAB218ADAE20004DE974 /* Release */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 470 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ARLineChartDemo.app/ARLineChartDemo"; 471 | FRAMEWORK_SEARCH_PATHS = ( 472 | "$(SDKROOT)/Developer/Library/Frameworks", 473 | "$(inherited)", 474 | "$(DEVELOPER_FRAMEWORKS_DIR)", 475 | ); 476 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 477 | GCC_PREFIX_HEADER = "ARLineChartDemo/ARLineChartDemo-Prefix.pch"; 478 | INFOPLIST_FILE = "ARLineChartDemoTests/ARLineChartDemoTests-Info.plist"; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | TEST_HOST = "$(BUNDLE_LOADER)"; 481 | WRAPPER_EXTENSION = xctest; 482 | }; 483 | name = Release; 484 | }; 485 | /* End XCBuildConfiguration section */ 486 | 487 | /* Begin XCConfigurationList section */ 488 | BF9DDA7318ADAE20004DE974 /* Build configuration list for PBXProject "ARLineChartDemo" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | BF9DDAAB18ADAE20004DE974 /* Debug */, 492 | BF9DDAAC18ADAE20004DE974 /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | BF9DDAAD18ADAE20004DE974 /* Build configuration list for PBXNativeTarget "ARLineChartDemo" */ = { 498 | isa = XCConfigurationList; 499 | buildConfigurations = ( 500 | BF9DDAAE18ADAE20004DE974 /* Debug */, 501 | BF9DDAAF18ADAE20004DE974 /* Release */, 502 | ); 503 | defaultConfigurationIsVisible = 0; 504 | }; 505 | BF9DDAB018ADAE20004DE974 /* Build configuration list for PBXNativeTarget "ARLineChartDemoTests" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | BF9DDAB118ADAE20004DE974 /* Debug */, 509 | BF9DDAB218ADAE20004DE974 /* Release */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | }; 513 | /* End XCConfigurationList section */ 514 | }; 515 | rootObject = BF9DDA7018ADAE20004DE974 /* Project object */; 516 | } 517 | -------------------------------------------------------------------------------- /ARLineChartDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ARLineChartDemo.xcodeproj/project.xcworkspace/xcuserdata/jun.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/longjun3000/ARLineChart/fe51ced0a476c906f0f9e6b87915f438f1e756a8/ARLineChartDemo.xcodeproj/project.xcworkspace/xcuserdata/jun.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ARLineChartDemo.xcodeproj/project.xcworkspace/xcuserdata/jun.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ARLineChartDemo.xcodeproj/xcuserdata/jun.xcuserdatad/xcschemes/ARLineChartDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /ARLineChartDemo.xcodeproj/xcuserdata/jun.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ARLineChartDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | BF9DDA7718ADAE20004DE974 16 | 17 | primary 18 | 19 | 20 | BF9DDA9B18ADAE20004DE974 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARAppDelegate.h 3 | // ARLineChartDemo 4 | // 5 | // Created by LongJun on 14-2-14. 6 | // Copyright (c) 2014年 Arwer Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ARAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARAppDelegate.m 3 | // ARLineChartDemo 4 | // 5 | // Created by LongJun on 14-2-14. 6 | // Copyright (c) 2014年 Arwer Software. All rights reserved. 7 | // 8 | 9 | #import "ARAppDelegate.h" 10 | 11 | @implementation ARAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // 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. 22 | // 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. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // 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. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 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 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChart/ARLineChartCommon.h: -------------------------------------------------------------------------------- 1 | // 2 | // SportLineChartUtilty.h 3 | // testLineChart 4 | // 5 | // Created by LongJun on 13-12-21. 6 | // Copyright (c) 2013年 LongJun. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define line1Color [UIColor colorWithRed:(float)249/255 green:(float)176/255 blue:(float)47/255 alpha:1.0]//棕黄色 12 | #define line2Color [UIColor colorWithRed:(float)73/255 green:(float)146/255 blue:(float)187/255 alpha:1.0]//青蓝色 13 | #define xylineColor [UIColor blackColor] 14 | 15 | 16 | @interface ARLineChartCommon : NSObject 17 | 18 | + (void)drawPoint:(CGContextRef)context point:(CGPoint)point color:(UIColor *)color; 19 | + (void)drawLine:(CGContextRef)context startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint lineColor:(UIColor *)lineColor; 20 | + (void)drawText:(CGContextRef)context text:(NSString*)text point:(CGPoint)point color:(UIColor *)color font:(UIFont*)font textAlignment:(NSTextAlignment)textAlignment; 21 | + (void)drawText2:(CGContextRef)context text:(NSString*)text color:(UIColor *)color fontSize:(CGFloat)fontSize; 22 | 23 | 24 | @end 25 | 26 | 27 | @interface RLLineChartItem : NSObject 28 | 29 | @property double xValue; //水平x轴的值 30 | @property double y1Value; //第一根垂直的y轴的值 31 | @property double y2Value; //第二根垂直的y轴的值 32 | 33 | @end -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChart/ARLineChartCommon.m: -------------------------------------------------------------------------------- 1 | // 2 | // SportLineChartUtilty.m 3 | // testLineChart 4 | // 5 | // Created by LongJun on 13-12-21. 6 | // Copyright (c) 2013年 LongJun. All rights reserved. 7 | // 8 | 9 | #import "ARLineChartCommon.h" 10 | 11 | @implementation ARLineChartCommon 12 | 13 | + (void)drawPoint:(CGContextRef)context point:(CGPoint)point color:(UIColor *)color{ 14 | 15 | CGContextSetShouldAntialias(context, YES ); //抗锯齿 16 | CGColorSpaceRef Pointcolorspace1 = CGColorSpaceCreateDeviceRGB(); 17 | CGContextSetStrokeColorSpace(context, Pointcolorspace1); 18 | CGContextSetStrokeColorWithColor(context, color.CGColor); 19 | CGContextMoveToPoint(context, point.x,point.y); 20 | CGContextAddArc(context, point.x, point.y, 2, 0, 360, 0); 21 | CGContextClosePath(context); 22 | CGContextSetFillColorWithColor(context, color.CGColor); 23 | CGContextFillPath(context); 24 | CGColorSpaceRelease(Pointcolorspace1); 25 | } 26 | + (void)drawLine:(CGContextRef)context startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint lineColor:(UIColor *)lineColor{ 27 | 28 | CGContextSetShouldAntialias(context, YES ); //抗锯齿 29 | CGColorSpaceRef Linecolorspace1 = CGColorSpaceCreateDeviceRGB(); 30 | CGContextSetStrokeColorSpace(context, Linecolorspace1); 31 | CGContextSetLineWidth(context, 0.5); 32 | CGContextSetStrokeColorWithColor(context, lineColor.CGColor); 33 | CGContextMoveToPoint(context, startPoint.x, startPoint.y); 34 | CGContextAddLineToPoint(context, endPoint.x, endPoint.y); 35 | CGContextStrokePath(context); 36 | CGColorSpaceRelease(Linecolorspace1); 37 | } 38 | 39 | + (void)drawText:(CGContextRef)context text:(NSString*)text point:(CGPoint)point color:(UIColor *)color font:(UIFont*)font textAlignment:(NSTextAlignment)textAlignment 40 | { 41 | // UIFont *font = [UIFont systemFontOfSize: fontSize]; 42 | [color set]; 43 | CGSize title1Size = [text sizeWithFont:font]; 44 | CGRect titleRect1 = CGRectMake(point.x, 45 | point.y, 46 | title1Size.width, 47 | title1Size.height); 48 | [text drawInRect:titleRect1 withFont:font lineBreakMode:NSLineBreakByClipping alignment:textAlignment]; 49 | 50 | } 51 | 52 | + (void)drawText2:(CGContextRef)context text:(NSString*)text color:(UIColor *)color fontSize:(CGFloat)fontSize 53 | { 54 | UIFont *font = [UIFont systemFontOfSize: fontSize]; 55 | // CGContextSelectFont(context, "Helvetica", 24.0, kCGEncodingMacRoman); 56 | CGContextSelectFont(context, font.fontName.UTF8String, fontSize, kCGEncodingMacRoman); 57 | CGContextSetTextDrawingMode(context, kCGTextFill); 58 | // CGContextSetRGBFillColor(context, 0, 255, 255, 1); 59 | CGContextSetStrokeColorWithColor(context, color.CGColor); 60 | 61 | CGAffineTransform xform = CGAffineTransformMake( 62 | 1.0, 0.0, 63 | 0.0, -1.0, 64 | 0.0, 0.0); 65 | CGContextSetTextMatrix(context, xform); 66 | const char* ctext = text.UTF8String; 67 | CGContextShowTextAtPoint(context, 10, 100, ctext, strlen(ctext)); 68 | } 69 | 70 | @end 71 | 72 | @implementation RLLineChartItem 73 | 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChart/ARLineChartContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SportLineChartContentView.h 3 | // testLineChart 4 | // 5 | // Created by LongJun on 13-12-21. 6 | // Copyright (c) 2013年 LongJun. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ARLineChartView.h" 11 | 12 | @interface ARLineChartContentView : UIView 13 | 14 | //构造函数,必须使用 15 | - (id)initWithFrame:(CGRect)frame dataSource:(NSArray*)dataSource; 16 | 17 | //x轴和y轴同时放大一个刻度 18 | - (void)zoomUp; 19 | //x轴和y轴同时减小一个刻度 20 | - (void)zoomDown; 21 | //x轴和y轴还原到原始刻度 22 | - (void)zoomOriginal; 23 | 24 | //x轴放大一个刻度 25 | - (void)zoomHorizontalUp; 26 | //x轴减小一个刻度 27 | - (void)zoomHorizontalDown; 28 | 29 | //y轴放大一个刻度 30 | - (void)zoomVerticalUp; 31 | //y轴减小一个刻度 32 | - (void)zoomVerticalDown; 33 | 34 | //刷新图表 35 | - (void)refreshData:(NSArray*)dataSource; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChart/ARLineChartContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SportLineChartContentView.m 3 | // testLineChart 4 | // 5 | // Created by LongJun on 13-12-21. 6 | // Copyright (c) 2013年 LongJun. All rights reserved. 7 | // 8 | 9 | #import "ARLineChartContentView.h" 10 | #import "ARLineChartCommon.h" 11 | 12 | #define DEFAULT_Y_COUNT 4 //可见区域y轴竖线总数 13 | #define DEFAULT_X_COUNT 4 //可见区域x轴总数 14 | 15 | typedef enum { 16 | XViewAll = 0, //x轴显示所有 17 | XViewLast = 1 //x轴显示最后部分 18 | }XView; 19 | 20 | @interface ARLineChartContentView () 21 | 22 | @property (strong, nonatomic) NSMutableArray *xArray; //x轴刻度 23 | @property (strong, nonatomic) NSMutableArray *y1Array; //左边y轴刻度 24 | @property (strong, nonatomic) NSMutableArray *y2Array; //右边y轴刻度 25 | 26 | @property (strong, nonatomic) NSArray *dataSource; //数据源 27 | 28 | @property CGFloat marginLeft; 29 | @property CGFloat marginRight; 30 | @property CGFloat marginBottom; 31 | @property (strong, nonatomic) UIFont *xyTextFont; 32 | @property (strong, nonatomic) UIColor *xyTextColor; 33 | @property CGPoint originPoint; 34 | @property CGPoint leftTopPoint; 35 | @property CGPoint rightBottomPoint; 36 | @property CGFloat xPerStepWidth; 37 | @property CGFloat yPerStepHeight; 38 | @property UIColor *dataLineColor; 39 | @property CGFloat xPerValue; 40 | @property NSInteger currXStepCount; //当前X轴刻度总数 41 | @property NSInteger currYStepCount; //当前y轴刻度总数 42 | 43 | @property int maxHeight; 44 | @property int maxWidth; 45 | @property CGPoint contentScroll; 46 | @property XView xview; 47 | 48 | static bool isLineIntersectRectangle(CGFloat linePointX1, 49 | CGFloat linePointY1, 50 | CGFloat linePointX2, 51 | CGFloat linePointY2, 52 | CGFloat rectangleLeftTopX, 53 | CGFloat rectangleLeftTopY, 54 | CGFloat rectangleRightBottomX, 55 | CGFloat rectangleRightBottomY); 56 | @end 57 | 58 | 59 | @implementation ARLineChartContentView 60 | 61 | - (id)initWithFrame:(CGRect)frame dataSource:(NSArray*)dataSource 62 | { 63 | self = [super initWithFrame:frame]; 64 | if (self) { 65 | // Initialization code 66 | self.backgroundColor = [UIColor clearColor]; 67 | // self.backgroundColor = [UIColor yellowColor]; 68 | 69 | 70 | //////////////////// 数据源排序(冒泡排序,x轴的数据(距离)从小到大排序) ///////////////// 71 | //根据 RLLineChartItem.xValue属性进行排序 72 | NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"_xValue" ascending:YES]; 73 | self.dataSource = [dataSource sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor1, nil]]; 74 | 75 | // //************* test 打印排序的 ************* 76 | // for (NSInteger i = 0; i < self.dataSource.count; i++) { 77 | // SportLineChartItem *item = [self.dataSource objectAtIndex:i]; 78 | // NSLog(@"排序后: item.xValue=%.2lf, item.y1Value=%.2lf, item.y2Value=%.2lf", item.xValue, item.y1Value, item.y2Value); 79 | // } 80 | // //************ end test ********************* 81 | 82 | 83 | //生成x轴、左y轴、右y轴刻度值 84 | [self buildXYSetpArray:DEFAULT_X_COUNT yStepCount:DEFAULT_Y_COUNT]; 85 | self.currXStepCount = DEFAULT_X_COUNT; 86 | self.currYStepCount = DEFAULT_Y_COUNT; 87 | 88 | 89 | self.xyTextFont = [UIFont systemFontOfSize:8]; 90 | self.xyTextColor = [UIColor lightGrayColor]; 91 | self.dataLineColor = [UIColor lightGrayColor]; 92 | 93 | ////////////// 找到最大的数,转换成字符串,得到其高度/宽度;画x轴y轴要留出这些刻度字符串的高度/宽度 ///////////////// 94 | double xMax = [[self.xArray objectAtIndex:0] integerValue]; 95 | for (NSNumber *num in self.xArray) { 96 | if ([num doubleValue] > xMax) { 97 | xMax = [num doubleValue]; 98 | } 99 | } 100 | NSString *xMaxStr = [NSString stringWithFormat:@"%.2lf", xMax]; 101 | CGSize size = [xMaxStr sizeWithFont: self.xyTextFont]; 102 | self.marginBottom = size.height; 103 | // 104 | double y1Max = [[self.y1Array objectAtIndex:0] integerValue]; 105 | for (NSNumber *num in self.y1Array) { 106 | if ([num doubleValue] > y1Max) { 107 | y1Max = [num doubleValue]; 108 | } 109 | } 110 | NSString *y1MaxStr = [NSString stringWithFormat:@"%.2lf", y1Max]; 111 | size = [y1MaxStr sizeWithFont: self.xyTextFont]; 112 | self.marginLeft = size.width; 113 | // 114 | double y2Max = [[self.y2Array objectAtIndex:0] integerValue]; 115 | for (NSNumber *num in self.y2Array) { 116 | if ([num doubleValue] > y2Max) { 117 | y2Max = [num doubleValue]; 118 | } 119 | } 120 | NSString *y2MaxStr = [NSString stringWithFormat:@"%.2lf", y2Max]; 121 | size = [y2MaxStr sizeWithFont: self.xyTextFont]; 122 | self.marginRight = size.width; 123 | 124 | // 125 | self.originPoint = CGPointMake(self.marginLeft + 2, self.frame.size.height - self.marginBottom - 2); 126 | self.leftTopPoint = CGPointMake(self.originPoint.x, 0 + 2); 127 | self.rightBottomPoint = CGPointMake(self.frame.size.width - self.marginRight - 2, self.originPoint.y); 128 | 129 | // 130 | //x轴上每一个Step的距离 131 | self.xPerStepWidth = (self.rightBottomPoint.x - self.originPoint.x) / (DEFAULT_X_COUNT) - 0.1; 132 | self.maxWidth = (self.xArray.count - 1) * self.xPerStepWidth; 133 | 134 | //y轴上每一个Step的距离 135 | self.yPerStepHeight = (self.originPoint.y - self.leftTopPoint.y) / (DEFAULT_Y_COUNT) - 0.1; 136 | //y轴上最大Step数 137 | NSInteger yStepCount = (self.y1Array.count > self.y2Array.count ? self.y1Array.count : self.y2Array.count); 138 | self.maxHeight = (yStepCount - 1) * self.yPerStepHeight; 139 | 140 | 141 | } 142 | return self; 143 | } 144 | 145 | - (void)buildXYSetpArray:(NSInteger)xStepCount yStepCount:(NSInteger)yStepCount 146 | { 147 | //////////////////// 生成x轴、左y轴、右y轴刻度值数组 /////////////////////// 148 | if (self.dataSource.count >= 2) { 149 | float xMin, xMax, y1Min, y1Max, y2Min, y2Max; 150 | RLLineChartItem *item = [self.dataSource objectAtIndex:0]; 151 | xMin = item.xValue; xMax = item.xValue; 152 | y1Min = item.y1Value; y1Max = item.y1Value; 153 | y2Min = item.y2Value; y2Max = item.y2Value; 154 | 155 | for (NSInteger i = 1; i < self.dataSource.count; i++) { 156 | RLLineChartItem *item = [self.dataSource objectAtIndex:i]; 157 | if (item.xValue < xMin) 158 | xMin = item.xValue; 159 | else if (item.xValue > xMax) 160 | xMax = item.xValue; 161 | 162 | if (item.y1Value < y1Min) 163 | y1Min = item.y1Value; 164 | else if (item.y1Value > y1Max) 165 | y1Max = item.y1Value; 166 | 167 | if (item.y2Value < y2Min) 168 | y2Min = item.y2Value; 169 | else if (item.y2Value > y2Max) 170 | y2Max = item.y2Value; 171 | } 172 | 173 | //x轴:千米 174 | if (!self.xArray) 175 | self.xArray = [NSMutableArray array]; 176 | else 177 | [self.xArray removeAllObjects]; 178 | float xPer = (xMax ) / xStepCount ; 179 | self.xPerValue = xPer; 180 | for (int i=0; i= 2) { 224 | float xMin, xMax; 225 | RLLineChartItem *item = [self.dataSource objectAtIndex:0]; 226 | xMin = item.xValue; xMax = item.xValue; 227 | 228 | for (NSInteger i = 1; i < self.dataSource.count; i++) { 229 | RLLineChartItem *item = [self.dataSource objectAtIndex:i]; 230 | if (item.xValue < xMin) 231 | xMin = item.xValue; 232 | else if (item.xValue > xMax) 233 | xMax = item.xValue; 234 | 235 | } 236 | 237 | //x轴:千米 238 | if (!self.xArray) 239 | self.xArray = [NSMutableArray array]; 240 | else 241 | [self.xArray removeAllObjects]; 242 | float xPer = (xMax ) / xStepCount ; 243 | self.xPerValue = xPer; 244 | for (int i=0; i self.originPoint.x && xPosition < self.rightBottomPoint.x) { 276 | 277 | //画x轴文字 278 | [self.xyTextColor set]; 279 | CGSize title1Size = [valStr sizeWithFont:self.xyTextFont]; 280 | CGRect titleRect1 = CGRectMake(xPosition - (title1Size.width)/2, 281 | self.originPoint.y + 2, 282 | title1Size.width, 283 | title1Size.height); 284 | [valStr drawInRect:titleRect1 withFont:self.xyTextFont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter]; 285 | 286 | //画竖线(不包含原点位置的竖线) 287 | CGFloat dashPattern[]= {6.0, 5}; 288 | CGContextSetLineDash(context, 0.0, dashPattern, 2); //虚线效果 289 | [ARLineChartCommon drawLine:context 290 | startPoint:CGPointMake(xPosition, self.originPoint.y) 291 | endPoint:CGPointMake(xPosition, self.leftTopPoint.y) 292 | lineColor:self.dataLineColor]; 293 | } 294 | } 295 | 296 | /////////////////////// 左边垂直方向 ///////////////////////// 297 | for (NSInteger i = 0; i < self.y1Array.count; i++) { 298 | NSNumber *num = [self.y1Array objectAtIndex:i]; 299 | NSString *valStr = [NSString stringWithFormat:@"%.2lf", [num doubleValue]]; 300 | // CGSize textSize = [valStr sizeWithFont: self.xyTextFont]; 301 | 302 | CGFloat y1Position = self.originPoint.y - (i+1) * self.yPerStepHeight + self.contentScroll.y; // - (textSize.height/2); 303 | 304 | if (y1Position < self.originPoint.y && y1Position > self.leftTopPoint.y) { 305 | //画左y轴文字 306 | [line1Color set]; 307 | CGSize title1Size = [valStr sizeWithFont:self.xyTextFont]; 308 | CGRect titleRect1 = CGRectMake(1, 309 | y1Position - (title1Size.height)/2, 310 | title1Size.width, 311 | title1Size.height); 312 | [valStr drawInRect:titleRect1 withFont:self.xyTextFont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentRight]; 313 | 314 | //画横线(不包含原点位置的横线) 315 | CGFloat dashPattern[]= {6.0, 5}; 316 | CGContextSetLineDash(context, 0.0, dashPattern, 2); //虚线效果 317 | [ARLineChartCommon drawLine:context 318 | startPoint:CGPointMake(self.originPoint.x, y1Position) 319 | endPoint:CGPointMake(self.rightBottomPoint.x, y1Position) 320 | lineColor:self.dataLineColor]; 321 | } 322 | } 323 | 324 | /////////////////////// 右边垂直方向 ///////////////////////// 325 | for (NSInteger i = 0; i < self.y2Array.count; i++) { 326 | NSNumber *num = [self.y2Array objectAtIndex:i]; 327 | NSString *valStr = [NSString stringWithFormat:@"%.2lf", [num doubleValue]]; 328 | // CGSize textSize = [valStr sizeWithFont: self.xyTextFont]; 329 | 330 | CGFloat y2Position = self.originPoint.y - (i+1) * self.yPerStepHeight + self.contentScroll.y; // - (textSize.height/2); 331 | 332 | if (y2Position < self.originPoint.y && y2Position > self.leftTopPoint.y) { 333 | //画右y轴文字 334 | [line2Color set]; 335 | CGSize title1Size = [valStr sizeWithFont:self.xyTextFont]; 336 | CGRect titleRect1 = CGRectMake(self.rightBottomPoint.x + 1, 337 | y2Position - (title1Size.height)/2, 338 | title1Size.width, 339 | title1Size.height); 340 | [valStr drawInRect:titleRect1 withFont:self.xyTextFont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentRight]; 341 | 342 | //画横线(不包含原点位置的横线) 343 | CGFloat dashPattern[]= {6.0, 5}; 344 | CGContextSetLineDash(context, 0.0, dashPattern, 2); //虚线效果 345 | [ARLineChartCommon drawLine:context 346 | startPoint:CGPointMake(self.originPoint.x, y2Position) 347 | endPoint:CGPointMake(self.rightBottomPoint.x, y2Position) 348 | lineColor:self.dataLineColor]; 349 | } 350 | } 351 | 352 | /////////////////////// 根据数据源画折线 ///////////////////////// 353 | if (self.dataSource && self.dataSource.count > 0) { 354 | 355 | for (NSInteger i = 0; i < self.dataSource.count-1; i++) { 356 | RLLineChartItem *item = (RLLineChartItem*)[self.dataSource objectAtIndex:i]; 357 | RLLineChartItem *item2 = (RLLineChartItem*)[self.dataSource objectAtIndex:i+1]; 358 | 359 | float xPerStepVal = [(NSNumber*)[self.xArray objectAtIndex:0] floatValue]; 360 | // if (xPerStepVal == 0) xPerStepVal = [(NSNumber*)[self.xArray objectAtIndex:1] floatValue]; 361 | float xPosition = self.originPoint.x + ((self.xPerStepWidth * item.xValue) / xPerStepVal) + self.contentScroll.x; 362 | float xPosition2 = self.originPoint.x + ((self.xPerStepWidth * item2.xValue) / xPerStepVal) + self.contentScroll.x; 363 | 364 | float y1PerStepVal = [(NSNumber*)[self.y1Array objectAtIndex:0] floatValue]; 365 | // if (y1PerStepVal == 0) y1PerStepVal = [(NSNumber*)[self.y1Array objectAtIndex:1] floatValue]; 366 | float y1Position = self.originPoint.y - fabs(((self.yPerStepHeight * item.y1Value) / y1PerStepVal )) + self.contentScroll.y; 367 | float y1Position2 = self.originPoint.y - fabs(((self.yPerStepHeight * item2.y1Value) / y1PerStepVal )) + self.contentScroll.y; 368 | 369 | float y2PerStepVal = [(NSNumber*)[self.y2Array objectAtIndex:0] floatValue]; 370 | // if (y2PerStepVal == 0) y2PerStepVal = [(NSNumber*)[self.y2Array objectAtIndex:1] floatValue]; 371 | float y2Position = self.originPoint.y - fabs(((self.yPerStepHeight * item.y2Value) / y2PerStepVal )) + self.contentScroll.y; 372 | float y2Position2 = self.originPoint.y - fabs(((self.yPerStepHeight * item2.y2Value) / y2PerStepVal )) + self.contentScroll.y; 373 | 374 | CGPoint startPoint = CGPointMake(xPosition, y1Position); 375 | CGPoint endPoint = CGPointMake(xPosition2, y1Position2); 376 | // graphPoints1[i] = startPoint; 377 | 378 | CGPoint startPoint2 = CGPointMake(xPosition, y2Position); 379 | CGPoint endPoint2 = CGPointMake(xPosition2, y2Position2); 380 | 381 | CGFloat normal[1]={1}; 382 | CGContextSetLineDash(context,0,normal,0); //画实线 383 | 384 | //画折线 385 | if ( isLineIntersectRectangle(xPosition, y1Position, xPosition2, y1Position2, _leftTopPoint.x, _leftTopPoint.y, _rightBottomPoint.x, _rightBottomPoint.y) ) 386 | { 387 | [ARLineChartCommon drawLine:context startPoint:startPoint endPoint:endPoint lineColor:line1Color]; 388 | } 389 | //画折线2 390 | if ( isLineIntersectRectangle(xPosition, y2Position, xPosition2, y2Position2, _leftTopPoint.x, _leftTopPoint.y, _rightBottomPoint.x, _rightBottomPoint.y) ) 391 | { 392 | [ARLineChartCommon drawLine:context startPoint:startPoint2 endPoint:endPoint2 lineColor:line2Color]; 393 | } 394 | 395 | 396 | } 397 | } 398 | 399 | ///////////////// 画原点上的左y轴 //////////////////// 400 | CGFloat normal[1]={1}; 401 | CGContextSetLineDash(context,0,normal,0); //画实线 402 | [ARLineChartCommon drawLine:context 403 | startPoint:self.originPoint 404 | endPoint:self.leftTopPoint 405 | lineColor:self.dataLineColor]; 406 | ///////////////// 画右y轴 ////////////////////////// 407 | [ARLineChartCommon drawLine:context 408 | startPoint:self.rightBottomPoint 409 | endPoint:CGPointMake(self.rightBottomPoint.x, self.leftTopPoint.y) 410 | lineColor:self.dataLineColor]; 411 | //////////////// 画原点上的x轴 /////////////////////// 412 | [ARLineChartCommon drawLine:context 413 | startPoint:CGPointMake(self.originPoint.x, self.originPoint.y) 414 | endPoint:CGPointMake(self.rightBottomPoint.x, self.rightBottomPoint.y) 415 | lineColor:self.dataLineColor]; 416 | 417 | 418 | } 419 | 420 | //static CGPoint s_p1; 421 | //static CGPoint s_p2; 422 | //CGFloat s_xDistance; 423 | //CGFloat s_yDistance; 424 | 425 | -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 426 | { 427 | // NSArray * touchesArr=[[event allTouches] allObjects]; 428 | // if (touchesArr.count == 2) { 429 | // 430 | //// s_p1 = [[touchesArr objectAtIndex:0] locationInView:self]; 431 | //// s_p2 =[[touchesArr objectAtIndex:1] locationInView:self]; 432 | // CGPoint p1 =[[touchesArr objectAtIndex:0] locationInView:self]; 433 | // CGPoint p2 =[[touchesArr objectAtIndex:1] locationInView:self]; 434 | // 435 | // // CGFloat xDiff = fabs(p1.x-s_p1.x) + fabs(p2.x-s_p2.x); 436 | // // CGFloat yDiff = fabs(p1.y-s_p1.y) + fabs(p2.y-s_p2.y); 437 | // s_xDistance = fabs(p2.x - p1.x); 438 | // s_yDistance = fabs(p2.y - p1.y); 439 | // NSLog(@"touchesBegan xDistance:%f",s_xDistance); 440 | // NSLog(@"touchesBegan yDistance:%f",s_yDistance); 441 | // 442 | // } 443 | } 444 | 445 | -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 446 | { 447 | 448 | 449 | NSArray * touchesArr=[[event allTouches] allObjects]; 450 | if (touchesArr.count == 1) { 451 | 452 | CGPoint touchLocation=[[touches anyObject] locationInView:self]; 453 | CGPoint prevouseLocation=[[touches anyObject] previousLocationInView:self]; 454 | float xDiffrance=touchLocation.x-prevouseLocation.x; 455 | float yDiffrance=touchLocation.y-prevouseLocation.y; 456 | 457 | _contentScroll.x+=xDiffrance; 458 | _contentScroll.y+=yDiffrance; 459 | 460 | if (_contentScroll.x >0) { 461 | _contentScroll.x=0; 462 | } 463 | if(_contentScroll.y<0) 464 | { 465 | _contentScroll.y=0; 466 | } 467 | 468 | if (-_contentScroll.x>self.maxWidth) { 469 | _contentScroll.x=-self.maxWidth; 470 | } 471 | if (_contentScroll.y>self.maxHeight) { 472 | _contentScroll.y=self.maxHeight; 473 | } 474 | 475 | [self setNeedsDisplay]; 476 | } 477 | 478 | 479 | 480 | 481 | } 482 | 483 | -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 484 | { 485 | NSArray * touchesArr=[[event allTouches] allObjects]; 486 | if (touchesArr.count == 1) { 487 | 488 | UITouch *touch = [touches anyObject]; 489 | if (touch.tapCount == 2) { 490 | NSLog(@"双击了"); 491 | if (self.xview == XViewLast) { 492 | [self zoomLastX]; 493 | self.xview = XViewAll; 494 | } 495 | else { 496 | [self zoomOriginal]; 497 | self.xview = XViewLast; 498 | } 499 | } 500 | } 501 | // else if (touchesArr.count == 2) { 502 | // 503 | // CGFloat len = 100-20, offset = 80-20; 504 | // CGPoint p1 =[[touchesArr objectAtIndex:0] locationInView:self]; 505 | // CGPoint p2 =[[touchesArr objectAtIndex:1] locationInView:self]; 506 | // 507 | // CGFloat xDiff = fabs(p1.x-s_p1.x) + fabs(p2.x-s_p2.x); 508 | // CGFloat yDiff = fabs(p1.y-s_p1.y) + fabs(p2.y-s_p2.y); 509 | //// CGFloat xDiff = (p1.x-s_p1.x) + (p2.x-s_p2.x); 510 | //// CGFloat yDiff = (p1.y-s_p1.y) + (p2.y-s_p2.y); 511 | // 512 | // NSLog(@"捏合长度x:%f",xDiff); 513 | // NSLog(@"捏合长度y:%f",yDiff); 514 | // 515 | // CGFloat xDistance = fabs(p2.x - p1.x); 516 | // CGFloat yDistance = fabs(p2.y - p1.y); 517 | // NSLog(@"xDistance:%f",xDistance); 518 | // NSLog(@"yDistance:%f",yDistance); 519 | // 520 | // 521 | // if (xDiff >= len && yDiff <= offset) { //认为是水平捏合手势 522 | // NSLog(@"是水平捏合手势"); 523 | // if (xDistance - s_xDistance > 0) { //双指向外 524 | // NSLog(@"水平双指向外"); 525 | // [self zoomHorizontalUp]; 526 | // } 527 | // else { //双指向内 528 | // NSLog(@"水平双指向内"); 529 | // [self zoomHorizontalDown]; 530 | // } 531 | // } 532 | // else if (xDiff <= offset && yDiff >= len) { //认为是垂直捏合手势 533 | // NSLog(@"是垂直捏合手势"); 534 | // if (yDistance - s_yDistance > 0) { //双指向外 535 | // NSLog(@"垂直双指向外"); 536 | // [self zoomVerticalUp]; 537 | // } 538 | // else { //双指向内 539 | // NSLog(@"垂直双指向内"); 540 | // [self zoomVerticalDown]; 541 | // } 542 | // } 543 | // else { //认为捏合手势 544 | // NSLog(@"是捏合手势"); 545 | // if (xDistance - s_xDistance > 0 || yDistance - s_yDistance > 0) { //双指向外 546 | // NSLog(@"捏合手势双指向外"); 547 | // [self zoomUp]; 548 | // } 549 | // else { //双指向内 550 | // NSLog(@"捏合手势双指向内"); 551 | // [self zoomDown]; 552 | // } 553 | // } 554 | // 555 | // 556 | // } 557 | } 558 | 559 | /**

判断线段是否在矩形内

560 | * 先看线段所在直线是否与矩形相交, 561 | * 如果不相交则返回false, 562 | * 如果相交, 563 | * 则看线段的两个点是否在矩形的同一边(即两点的x(y)坐标都比矩形的小x(y)坐标小,或者大), 564 | * 若在同一边则返回false, 565 | * 否则就是相交的情况。 566 | * @param linePointX1 线段起始点x坐标 567 | * @param linePointY1 线段起始点y坐标 568 | * @param linePointX2 线段结束点x坐标 569 | * @param linePointY2 线段结束点y坐标 570 | * @param rectangleLeftTopX 矩形左上点x坐标 571 | * @param rectangleLeftTopY 矩形左上点y坐标 572 | * @param rectangleRightBottomX 矩形右下点x坐标 573 | * @param rectangleRightBottomY 矩形右下点y坐标 574 | * @return 是否相交 575 | */ 576 | static bool isLineIntersectRectangle(CGFloat linePointX1, 577 | CGFloat linePointY1, 578 | CGFloat linePointX2, 579 | CGFloat linePointY2, 580 | CGFloat rectangleLeftTopX, 581 | CGFloat rectangleLeftTopY, 582 | CGFloat rectangleRightBottomX, 583 | CGFloat rectangleRightBottomY) 584 | { 585 | CGFloat lineHeight = linePointY1 - linePointY2; 586 | CGFloat lineWidth = linePointX2 - linePointX1; // 计算叉乘 587 | CGFloat c = linePointX1 * linePointY2 - linePointX2 * linePointY1; 588 | if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0) 589 | || (lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c >= 0) 590 | || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c <= 0) 591 | || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c >= 0)) 592 | { 593 | 594 | if (rectangleLeftTopX > rectangleRightBottomX) { 595 | CGFloat temp = rectangleLeftTopX; 596 | rectangleLeftTopX = rectangleRightBottomX; 597 | rectangleRightBottomX = temp; 598 | } 599 | if (rectangleLeftTopY < rectangleRightBottomY) { 600 | CGFloat temp1 = rectangleLeftTopY; 601 | rectangleLeftTopY = rectangleRightBottomY; 602 | rectangleRightBottomY = temp1; } 603 | if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX) 604 | || (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX) 605 | || (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY) 606 | || (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY)) { 607 | return false; 608 | } else { 609 | return true; 610 | } 611 | } else { 612 | return false; 613 | } 614 | } 615 | 616 | //x轴和y轴同时放大一个刻度 617 | - (void)zoomUp 618 | { 619 | //x轴刻度总数量增加 620 | self.currXStepCount++; 621 | //Y轴刻度总数量增加 622 | self.currYStepCount++; 623 | 624 | //生成x轴、左y轴、右y轴刻度值 625 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 626 | 627 | // //x轴上每一个Step的距离 628 | // self.xPerStepWidth = (self.rightBottomPoint.x - self.originPoint.x) / (self.currXStepCount) - 0.1; 629 | self.maxWidth = (self.xArray.count - 1) * self.xPerStepWidth; 630 | // 631 | // //y轴上每一个Step的距离 632 | // self.yPerStepHeight = (self.originPoint.y - self.leftTopPoint.y) / (self.currYStepCount) - 0.1; 633 | //y轴上最大Step数 634 | NSInteger yStepCount = (self.y1Array.count > self.y2Array.count ? self.y1Array.count : self.y2Array.count); 635 | self.maxHeight = (yStepCount - 1) * self.yPerStepHeight; 636 | 637 | //重绘 638 | [self setNeedsDisplay]; 639 | } 640 | //x轴和y轴同时减小一个刻度 641 | - (void)zoomDown 642 | { 643 | //x轴刻度总数量增加 644 | self.currXStepCount--; 645 | if (self.currXStepCount < DEFAULT_X_COUNT) self.currXStepCount = DEFAULT_X_COUNT; 646 | //Y轴刻度总数量增加 647 | self.currYStepCount--; 648 | if (self.currYStepCount < DEFAULT_Y_COUNT) self.currYStepCount = DEFAULT_Y_COUNT; 649 | 650 | //生成x轴、左y轴、右y轴刻度值 651 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 652 | 653 | // //x轴上每一个Step的距离 654 | // self.xPerStepWidth = (self.rightBottomPoint.x - self.originPoint.x) / (self.currXStepCount) - 0.1; 655 | self.maxWidth = (self.xArray.count - 1) * self.xPerStepWidth; 656 | // 657 | // //y轴上每一个Step的距离 658 | // self.yPerStepHeight = (self.originPoint.y - self.leftTopPoint.y) / (self.currYStepCount) - 0.1; 659 | //y轴上最大Step数 660 | NSInteger yStepCount = (self.y1Array.count > self.y2Array.count ? self.y1Array.count : self.y2Array.count); 661 | self.maxHeight = (yStepCount - 1) * self.yPerStepHeight; 662 | 663 | //重绘 664 | [self setNeedsDisplay]; 665 | } 666 | //x轴和y轴还原到原始刻度 667 | - (void)zoomOriginal 668 | { 669 | self.currXStepCount = DEFAULT_X_COUNT; 670 | self.currYStepCount = DEFAULT_Y_COUNT; 671 | _contentScroll.x=0; 672 | _contentScroll.y=0; 673 | 674 | //生成x轴、左y轴、右y轴刻度值 675 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 676 | 677 | //x轴上每一个Step的距离 678 | self.xPerStepWidth = (self.rightBottomPoint.x - self.originPoint.x) / (DEFAULT_X_COUNT) - 0.1; 679 | self.maxWidth = (self.xArray.count - 1) * self.xPerStepWidth; 680 | 681 | // //y轴上每一个Step的距离 682 | // self.yPerStepHeight = (self.originPoint.y - self.leftTopPoint.y) / (DEFAULT_Y_COUNT) - 0.1; 683 | //y轴上最大Step数 684 | NSInteger yStepCount = (self.y1Array.count > self.y2Array.count ? self.y1Array.count : self.y2Array.count); 685 | self.maxHeight = (yStepCount - 1) * self.yPerStepHeight; 686 | 687 | //重绘 688 | [self setNeedsDisplay]; 689 | } 690 | //x轴放大移动到最后刻度 691 | - (void)zoomLastX 692 | { 693 | //x轴刻度总数量增加 694 | self.currXStepCount = self.dataSource.count; 695 | 696 | //生成x轴、左y轴、右y轴刻度值 697 | [self buildXSetpArray:self.currXStepCount]; 698 | 699 | // 700 | self.maxWidth = (self.xArray.count -1 ) * self.xPerStepWidth; 701 | // 702 | _contentScroll.x=-self.maxWidth + (self.xPerStepWidth * 3); 703 | 704 | 705 | //重绘 706 | [self setNeedsDisplay]; 707 | 708 | } 709 | 710 | //x轴放大一个刻度 711 | - (void)zoomHorizontalUp 712 | { 713 | //x轴刻度总数量增加 714 | self.currXStepCount++; 715 | 716 | //生成x轴、左y轴、右y轴刻度值 717 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 718 | 719 | // //x轴上每一个Step的距离 720 | // self.xPerStepWidth = (self.rightBottomPoint.x - self.originPoint.x) / (self.currXStepCount) - 0.1; 721 | self.maxWidth = (self.xArray.count - 1) * self.xPerStepWidth; 722 | 723 | //重绘 724 | [self setNeedsDisplay]; 725 | 726 | } 727 | //x轴减小一个刻度 728 | - (void)zoomHorizontalDown 729 | { 730 | //x轴刻度总数量减少 731 | self.currXStepCount--; 732 | if (self.currXStepCount < DEFAULT_X_COUNT) self.currXStepCount = DEFAULT_X_COUNT; 733 | 734 | //生成x轴、左y轴、右y轴刻度值 735 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 736 | 737 | // //x轴上每一个Step的距离 738 | // self.xPerStepWidth = (self.rightBottomPoint.x - self.originPoint.x) / (self.currXStepCount) - 0.1; 739 | self.maxWidth = (self.xArray.count - 1) * self.xPerStepWidth; 740 | // 741 | // _contentScroll.x=-self.maxWidth + (self.xPerStepWidth * 3); 742 | 743 | //重绘 744 | [self setNeedsDisplay]; 745 | } 746 | 747 | //y轴放大一个刻度 748 | - (void)zoomVerticalUp 749 | { 750 | //Y轴刻度总数量增加 751 | self.currYStepCount++; 752 | 753 | //生成x轴、左y轴、右y轴刻度值 754 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 755 | 756 | // //y轴上每一个Step的距离 757 | // self.yPerStepHeight = (self.originPoint.y - self.leftTopPoint.y) / (self.currYStepCount) - 0.1; 758 | //y轴上最大Step数 759 | NSInteger yStepCount = (self.y1Array.count > self.y2Array.count ? self.y1Array.count : self.y2Array.count); 760 | self.maxHeight = (yStepCount - 1) * self.yPerStepHeight; 761 | 762 | //重绘 763 | [self setNeedsDisplay]; 764 | } 765 | //y轴减小一个刻度 766 | - (void)zoomVerticalDown 767 | { 768 | //Y轴刻度总数量减少 769 | self.currYStepCount--; 770 | if (self.currYStepCount < DEFAULT_Y_COUNT) self.currYStepCount = DEFAULT_Y_COUNT; 771 | 772 | //生成x轴、左y轴、右y轴刻度值 773 | [self buildXYSetpArray:self.currXStepCount yStepCount:self.currYStepCount]; 774 | 775 | // //y轴上每一个Step的距离 776 | // self.yPerStepHeight = (self.originPoint.y - self.leftTopPoint.y) / (self.currYStepCount) - 0.1; 777 | //y轴上最大Step数 778 | NSInteger yStepCount = (self.y1Array.count > self.y2Array.count ? self.y1Array.count : self.y2Array.count); 779 | self.maxHeight = (yStepCount - 1) * self.yPerStepHeight; 780 | // 781 | // _contentScroll.y = self.maxHeight + (self.yPerStepHeight * 3); 782 | 783 | //重绘 784 | [self setNeedsDisplay]; 785 | } 786 | 787 | //刷新图表 788 | - (void)refreshData:(NSArray*)dataSource 789 | { 790 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 791 | //////////////////// 数据源排序(冒泡排序,x轴的数据(距离)从小到大排序) ///////////////// 792 | //根据 RLLineChartItem.xValue属性进行排序 793 | NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"_xValue" ascending:YES]; 794 | self.dataSource = [dataSource sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor1, nil]]; 795 | 796 | dispatch_async(dispatch_get_main_queue(), ^{ 797 | if (self.xview == XViewLast) { 798 | [self zoomLastX]; 799 | } 800 | else { 801 | [self zoomOriginal]; 802 | } 803 | }); 804 | }); 805 | 806 | 807 | } 808 | 809 | @end 810 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChart/ARLineChartView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RLLineChartView.h 3 | // testLineChart 4 | // 5 | // Created by LongJun on 13-12-21. 6 | // Copyright (c) 2013年 LongJun. All rights reserved. 7 | // 8 | /* 使用方法: 9 | ///////////// Test 创建数据源 ///////////////////// 10 | NSMutableArray *dataSource = [NSMutableArray array]; 11 | // rand() /((double)(RAND_MAX)/100) //取0-100中间的浮点数 12 | double distanceMin = 0, distanceMax = 100; 13 | double altitudeMin = 5.0, altitudeMax = 50; 14 | double speedMin = 0.5, speedMax = 15; 15 | srand(time(NULL)); //随机数种子 16 | for (int i=0; i< 11; i++) { 17 | // for (int i=0; i< self.xArray.count; i++) { 18 | RLLineChartItem *item = [[RLLineChartItem alloc] init]; 19 | double randVal; 20 | 21 | randVal = rand() /((double)(RAND_MAX)/distanceMax) + distanceMin; 22 | item.xValue = randVal; 23 | // item.xValue = [(NSNumber*)[self.xArray objectAtIndex:i] doubleValue]; 24 | 25 | randVal = rand() /((double)(RAND_MAX)/altitudeMax) + altitudeMin; 26 | item.y1Value = randVal; 27 | 28 | randVal = rand() /((double)(RAND_MAX)/speedMax) + speedMin; 29 | item.y2Value = randVal; 30 | 31 | NSLog(@"随机: item.xValue=%.2lf, item.y1Value=%.2lf, item.y2Value=%.2lf", item.xValue, item.y1Value, item.y2Value); 32 | [dataSource addObject:item]; 33 | } 34 | /////////////// End Test /////////////////////////// 35 | 36 | ////////////// 创建图表视图 ////////////////////////// 37 | CGRect rect = CGRectMake(5, 40, 38 | self.view.frame.size.width - 5 - 5, 39 | 300); 40 | self.lineChartView = [[RLLineChartView alloc] initWithFrame:rect dataSource:dataSource]; 41 | self.lineChartView.title1 = @"海拔(米)"; 42 | self.lineChartView.title2 = @"速度(千米/小时)"; 43 | self.lineChartView.titleX = @"千米"; 44 | [self.view addSubview:self.lineChartView]; 45 | 46 | */ 47 | 48 | #import 49 | 50 | @interface ARLineChartView : UIView 51 | 52 | 53 | //构造函数,必须使用 54 | - (id)initWithFrame:(CGRect)frame dataSource:(NSArray*)dataSource xTitle:(NSString*)xTitle y1Title:(NSString*)y1Title y2Title:(NSString*)y2Title desc1:(NSString*)desc1 desc2:(NSString*)desc2; 55 | 56 | //x轴和y轴同时放大一个刻度 57 | - (void)zoomUp; 58 | //x轴和y轴同时减小一个刻度 59 | - (void)zoomDown; 60 | //x轴和y轴还原到原始刻度 61 | - (void)zoomOriginal; 62 | 63 | //x轴放大一个刻度 64 | - (void)zoomHorizontalUp; 65 | //x轴减小一个刻度 66 | - (void)zoomHorizontalDown; 67 | 68 | //y轴放大一个刻度 69 | - (void)zoomVerticalUp; 70 | //y轴减小一个刻度 71 | - (void)zoomVerticalDown; 72 | 73 | //刷新图表 74 | - (void)refreshData:(NSArray*)dataSource; 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChart/ARLineChartView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RLLineChartView.m 3 | // testLineChart 4 | // 5 | // Created by LongJun on 13-12-21. 6 | // Copyright (c) 2013年 LongJun. All rights reserved. 7 | // 8 | #if !__has_feature(objc_arc) 9 | #error "This source file must be compiled with ARC enabled!" 10 | #endif 11 | 12 | #import "ARLineChartView.h" 13 | #import "ARLineChartContentView.h" 14 | #import "ARLineChartCommon.h" 15 | 16 | 17 | #define MARGIN_TOP 5 18 | #define Y1_MARGIN_LEFT 20 19 | #define Y2_MARGIN_RIGHT 20 20 | #define X_MARGIN_BUTTOM 10 //x轴横线距离底边的高度 21 | 22 | @interface ARLineChartView () 23 | 24 | @property (strong, nonatomic) NSString *title1; 25 | @property (strong, nonatomic) NSString *title2; 26 | @property (strong, nonatomic) NSString *titleX; 27 | @property (strong, nonatomic) NSString *desc1; 28 | @property (strong, nonatomic) NSString *desc2; 29 | 30 | @property (strong, nonatomic) ARLineChartContentView *lineChartContentView; 31 | 32 | @end 33 | 34 | @implementation ARLineChartView 35 | 36 | - (id)initWithFrame:(CGRect)frame dataSource:(NSArray*)dataSource xTitle:(NSString*)xTitle y1Title:(NSString*)y1Title y2Title:(NSString*)y2Title desc1:(NSString*)desc1 desc2:(NSString*)desc2 37 | { 38 | self = [super initWithFrame:frame]; 39 | if (self) { 40 | // Initialization code 41 | self.backgroundColor = [UIColor clearColor]; 42 | // self.backgroundColor = [UIColor brownColor]; 43 | // self.backgroundColor = [UIColor whiteColor]; 44 | 45 | //////////// test /////////////////// 46 | self.titleX = xTitle ? xTitle : @"X"; 47 | self.title1 = y1Title ? y1Title : @"Y1"; 48 | self.title2 = y2Title ? y2Title : @"Y2"; 49 | 50 | self.desc1 = desc1 ? desc1 : @"Desc1"; 51 | self.desc2 = desc2 ? desc2 : @"Desc2"; 52 | //////////// end ////////////////// 53 | 54 | ////////////////////////// 上面的标题 ////////////////////////// 55 | UIFont *font = [UIFont systemFontOfSize:14]; 56 | CGFloat y = MARGIN_TOP; 57 | 58 | CGSize title1Size = [y1Title sizeWithFont:font]; 59 | CGRect titleRect1 = CGRectMake((self.frame.size.width - title1Size.width) / 2, 60 | y, 61 | title1Size.width, 62 | title1Size.height); 63 | UILabel *lblTitle1 = [[UILabel alloc] initWithFrame:titleRect1]; 64 | lblTitle1.text = y1Title; 65 | lblTitle1.textColor = line1Color; 66 | lblTitle1.font = font; 67 | [self addSubview:lblTitle1]; 68 | 69 | // 70 | y = titleRect1.origin.y + titleRect1.size.height + 2; 71 | CGSize title2Size = [y2Title sizeWithFont:font]; 72 | CGRect titleRect2 = CGRectMake((self.frame.size.width - title2Size.width) / 2, 73 | y, 74 | title2Size.width, 75 | title2Size.height); 76 | UILabel *lblTitle2 = [[UILabel alloc] initWithFrame:titleRect2]; 77 | lblTitle2.text = y2Title; 78 | lblTitle2.textColor = line2Color; 79 | lblTitle2.font = font; 80 | [self addSubview:lblTitle2]; 81 | 82 | 83 | ////////////////////// 折线图内容区域 /////////////////////////// 84 | y = titleRect2.origin.y + titleRect2.size.height + 5; 85 | CGRect rect = CGRectMake(0, 86 | y, 87 | self.frame.size.width, 88 | self.frame.size.height - y - X_MARGIN_BUTTOM); 89 | self.lineChartContentView = [[ARLineChartContentView alloc] initWithFrame:rect dataSource:dataSource]; 90 | [self addSubview:self.lineChartContentView]; 91 | 92 | 93 | ////////////////////// 注册手势监听 /////////////////////////// 94 | UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self 95 | action:@selector(pinchDetected:)]; 96 | 97 | [self addGestureRecognizer:pinchRecognizer]; 98 | 99 | } 100 | return self; 101 | } 102 | 103 | 104 | // Only override drawRect: if you perform custom drawing. 105 | // An empty implementation adversely affects performance during animation. 106 | - (void)drawRect:(CGRect)rect 107 | { 108 | CGContextRef context = UIGraphicsGetCurrentContext(); 109 | 110 | // ////////////////////////// 画标题 ////////////////////////// 111 | // UIColor *textColor = line1Color; 112 | // UIFont *font = [UIFont systemFontOfSize:14]; 113 | // CGFloat y = MARGIN_TOP; 114 | // 115 | // //画标题1 116 | // [textColor set]; 117 | // CGSize title1Size = [self.title1 sizeWithFont:font]; 118 | // CGRect titleRect1 = CGRectMake((self.frame.size.width - title1Size.width) / 2, 119 | // y, 120 | // title1Size.width, 121 | // title1Size.height); 122 | // [self.title1 drawInRect:titleRect1 withFont:font lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter]; 123 | // 124 | // //画标题2 125 | // textColor = line2Color; 126 | // [textColor set]; 127 | // y = titleRect1.origin.y + titleRect1.size.height + 2; 128 | // CGSize title2Size = [self.title2 sizeWithFont:font]; 129 | // CGRect titleRect2 = CGRectMake((self.frame.size.width - title2Size.width) / 2, 130 | // y, 131 | // title2Size.width, 132 | // title2Size.height); 133 | // [self.title2 drawInRect:titleRect2 withFont:font lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter]; 134 | 135 | 136 | ////////////////////// 画底部线条颜色说明文字 ////////////////////////// 137 | //短线条1 138 | UIColor *textColor = line1Color; 139 | [textColor set]; 140 | CGFloat originY = self.frame.size.height - X_MARGIN_BUTTOM; 141 | CGFloat y = originY + (X_MARGIN_BUTTOM/2); 142 | CGPoint startPoint = CGPointMake(Y1_MARGIN_LEFT, y); 143 | CGPoint endPoint = CGPointMake(Y1_MARGIN_LEFT+ 15, y); 144 | [ARLineChartCommon drawLine:context startPoint:startPoint endPoint:endPoint lineColor:textColor]; 145 | //描述文字1 146 | UIFont *descFont = [UIFont systemFontOfSize:8]; 147 | CGSize desc1Size = [self.desc1 sizeWithFont:descFont]; 148 | // startPoint = CGPointMake(endPoint.x + 3, y - (desc1Size.height/2)); 149 | CGRect desc1Rect = CGRectMake(endPoint.x + 3, 150 | y - (desc1Size.height/2), 151 | desc1Size.width, 152 | desc1Size.height); 153 | [self.title1 drawInRect:desc1Rect withFont:descFont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentLeft]; 154 | 155 | //短线条2 156 | textColor = line2Color; 157 | [textColor set]; 158 | 159 | startPoint = CGPointMake(desc1Rect.origin.x + desc1Rect.size.width + 10, y); 160 | endPoint = CGPointMake(startPoint.x + 15, y); 161 | [ARLineChartCommon drawLine:context startPoint:startPoint endPoint:endPoint lineColor:textColor]; 162 | //描述文字2 163 | CGSize desc2Size = [self.desc2 sizeWithFont:descFont]; 164 | // startPoint = CGPointMake(endPoint.x + 3, y - (desc2Size.height/2)); 165 | CGRect desc2Rect = CGRectMake(endPoint.x + 3, 166 | y - (desc2Size.height/2), 167 | desc2Size.width, 168 | desc2Size.height); 169 | [self.title2 drawInRect:desc2Rect withFont:descFont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentLeft]; 170 | 171 | //x轴说明文字 172 | [[UIColor grayColor] set]; 173 | UIFont *titleXFont = [UIFont systemFontOfSize:10]; 174 | CGSize titleXSize = [self.title1 sizeWithFont:titleXFont]; 175 | // startPoint = CGPointMake(self.frame.size.width - Y2_MARGIN_RIGHT - titleXSize.width, y - (titleXSize.height/2)); 176 | //x: self.frame.size.width - Y2_MARGIN_RIGHT - titleXSize.width - 140 177 | CGRect titleXRect = CGRectMake((self.frame.size.width - titleXSize.width) / 2, 178 | y - (titleXSize.height/2), 179 | titleXSize.width, 180 | titleXSize.height); 181 | [self.titleX drawInRect:titleXRect withFont:titleXFont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentRight]; 182 | 183 | } 184 | 185 | //// Only override drawRect: if you perform custom drawing. 186 | //// An empty implementation adversely affects performance during animation. 187 | //- (void)drawRect:(CGRect)rect 188 | //{ 189 | // // Drawing code 190 | // 191 | // CGContextRef context = UIGraphicsGetCurrentContext(); 192 | // CGContextSetRGBStrokeColor (context, 142.0/ 255.0, 161.0/ 255.0, 189.0/ 255.0, 1.0); 193 | // CGContextSetLineWidth(context, 1.0 );//这里设置成了1但画出的线还是2px,给我们的感觉好像最小只能是2px。 194 | // CGContextSetShouldAntialias(context, YES ); //抗锯齿 195 | // CGContextMoveToPoint(context, 1.0 , 24.0 ); 196 | // CGContextAddLineToPoint(context, 83.0 , 54.0 ); 197 | // CGContextClosePath(context); 198 | // CGContextStrokePath(context); 199 | // 200 | // // 201 | // [self drawPoint:context point:CGPointMake(50, 60) color:[UIColor redColor]]; 202 | // // 203 | // [self drawLine:context 204 | // startPoint:CGPointMake(20, 30) 205 | // endPoint:CGPointMake(20, 100) 206 | // lineColor:[UIColor blueColor]]; 207 | //} 208 | 209 | //x轴和y轴同时放大一个刻度 210 | - (void)zoomUp 211 | { 212 | [self.lineChartContentView zoomUp]; 213 | } 214 | //x轴和y轴同时减小一个刻度 215 | - (void)zoomDown 216 | { 217 | [self.lineChartContentView zoomDown]; 218 | } 219 | //x轴和y轴还原到原始刻度 220 | - (void)zoomOriginal 221 | { 222 | [self.lineChartContentView zoomOriginal]; 223 | } 224 | 225 | //x轴放大一个刻度 226 | - (void)zoomHorizontalUp 227 | { 228 | [self.lineChartContentView zoomHorizontalUp]; 229 | } 230 | //x轴减小一个刻度 231 | - (void)zoomHorizontalDown 232 | { 233 | [self.lineChartContentView zoomHorizontalDown]; 234 | } 235 | 236 | //y轴放大一个刻度 237 | - (void)zoomVerticalUp 238 | { 239 | [self.lineChartContentView zoomVerticalUp]; 240 | } 241 | //y轴减小一个刻度 242 | - (void)zoomVerticalDown 243 | { 244 | [self.lineChartContentView zoomVerticalDown]; 245 | } 246 | 247 | //刷新图表 248 | - (void)refreshData:(NSArray*)dataSource 249 | { 250 | [self.lineChartContentView refreshData:dataSource]; 251 | } 252 | 253 | - (IBAction)pinchDetected:(UIPinchGestureRecognizer *)sender { 254 | 255 | //比例(经常用到放缩比例)这个属性默认值是1,通过获取放缩比例属性 256 | CGFloat scale = [(UIPinchGestureRecognizer *)sender scale]; 257 | // //捏合的速度 258 | // CGFloat velocity = [(UIPinchGestureRecognizer *)sender velocity]; 259 | 260 | // NSString *resultString = [[NSString alloc] initWithFormat: 261 | // 262 | // @"Pinch - scale = %f, velocity = %f", 263 | // 264 | // scale, velocity]; 265 | 266 | // NSLog(@"%@", resultString); 267 | // if([sender state] == UIGestureRecognizerStateEnded) { 268 | if([sender state] == UIGestureRecognizerStateChanged) { 269 | if (scale >= 1.1) { //放大 270 | 271 | [self.lineChartContentView zoomHorizontalUp]; 272 | } 273 | else { //缩小 274 | [self.lineChartContentView zoomHorizontalDown]; 275 | } 276 | } 277 | 278 | } 279 | 280 | 281 | @end 282 | 283 | 284 | 285 | 286 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChartDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.arwer.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main_iPhone 29 | UIMainStoryboardFile~ipad 30 | Main_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARLineChartDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ARViewController.h 3 | // ARLineChartDemo 4 | // 5 | // Created by LongJun on 14-2-14. 6 | // Copyright (c) 2014年 Arwer Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ARViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ARLineChartDemo/ARViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARViewController.m 3 | // ARLineChartDemo 4 | // 5 | // Created by LongJun on 14-2-14. 6 | // Copyright (c) 2014年 Arwer Software. All rights reserved. 7 | // 8 | 9 | #import "ARViewController.h" 10 | #import "ARLineChartView.h" 11 | #import "ARLineChartCommon.h" 12 | 13 | @interface ARViewController () 14 | 15 | @property (strong, nonatomic) ARLineChartView *lineChartView; 16 | 17 | @end 18 | 19 | @implementation ARViewController 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | 26 | 27 | //************* Test: Create Data Source ************* 28 | NSMutableArray *dataSource = [NSMutableArray array]; 29 | // rand() /((double)(RAND_MAX)/100) //取0-100中间的浮点数 30 | double distanceMin = 0, distanceMax = 100; 31 | double altitudeMin = 5.0, altitudeMax = 50; 32 | double speedMin = 0.5, speedMax = 15; 33 | 34 | srand(time(NULL)); //Random seed 35 | 36 | for (int i=0; i< 11; i++) { 37 | 38 | RLLineChartItem *item = [[RLLineChartItem alloc] init]; 39 | double randVal; 40 | 41 | randVal = rand() /((double)(RAND_MAX)/distanceMax) + distanceMin; 42 | item.xValue = randVal; 43 | 44 | randVal = rand() /((double)(RAND_MAX)/altitudeMax) + altitudeMin; 45 | item.y1Value = randVal; 46 | 47 | randVal = rand() /((double)(RAND_MAX)/speedMax) + speedMin; 48 | item.y2Value = randVal; 49 | 50 | NSLog(@"Random: item.xValue=%.2lf, item.y1Value=%.2lf, item.y2Value=%.2lf", item.xValue, item.y1Value, item.y2Value); 51 | [dataSource addObject:item]; 52 | } 53 | //************ End Test ********************* 54 | 55 | ////////////// Create Line Char ////////////////////////// 56 | CGRect rect = CGRectMake(5, 40, 57 | self.view.frame.size.width - 5 - 5, 58 | 300); 59 | // self.lineChartView = [[ARLineChartView alloc] initWithFrame:rect dataSource:dataSource xTitle:@"千米" y1Title:@"海拔(米)" y2Title:@"速度(千米/小时)" desc1:@"海拔" desc2:@"速度"]; 60 | self.lineChartView = [[ARLineChartView alloc] initWithFrame:rect dataSource:dataSource xTitle:@"Kilometre" y1Title:@"Altitude (meters)" y2Title:@"Speed (km/h)" desc1:@"Altitude" desc2:@"Speed"]; 61 | [self.view addSubview:self.lineChartView]; 62 | 63 | ////////////// Test: Create Control Button //////////////////// 64 | rect = CGRectMake(self.lineChartView.frame.origin.x, 65 | self.lineChartView.frame.origin.y + self.lineChartView.frame.size.height +2, 66 | 100, 20); 67 | UIButton *btnZoomUp = [UIButton buttonWithType:UIButtonTypeSystem]; 68 | btnZoomUp.frame = rect; 69 | btnZoomUp.titleLabel.font = [UIFont systemFontOfSize:10]; 70 | [btnZoomUp setTitle:@"Zoom In All" forState:UIControlStateNormal]; //整体放大 71 | [btnZoomUp addTarget:self action:@selector(zoomUpAction:) forControlEvents:UIControlEventTouchUpInside]; 72 | [self.view addSubview:btnZoomUp]; 73 | 74 | // 75 | rect = CGRectMake(btnZoomUp.frame.origin.x + btnZoomUp.frame.size.width + 5, 76 | btnZoomUp.frame.origin.y, 77 | btnZoomUp.frame.size.width, 78 | btnZoomUp.frame.size.height); 79 | UIButton *btnZoomDown = [UIButton buttonWithType:UIButtonTypeSystem]; 80 | btnZoomDown.frame = rect; 81 | btnZoomDown.titleLabel.font = btnZoomUp.titleLabel.font; 82 | [btnZoomDown setTitle:@"Zoom Out All" forState:UIControlStateNormal]; //整体缩小 83 | [btnZoomDown addTarget:self action:@selector(zoomDownAction:) forControlEvents:UIControlEventTouchUpInside]; 84 | [self.view addSubview:btnZoomDown]; 85 | 86 | // 87 | rect = CGRectMake(btnZoomDown.frame.origin.x + btnZoomDown.frame.size.width + 5, 88 | btnZoomDown.frame.origin.y, 89 | btnZoomDown.frame.size.width, 90 | btnZoomDown.frame.size.height); 91 | UIButton *btnZoomOriginal = [UIButton buttonWithType:UIButtonTypeSystem]; 92 | btnZoomOriginal.frame = rect; 93 | btnZoomOriginal.titleLabel.font = btnZoomUp.titleLabel.font; 94 | [btnZoomOriginal setTitle:@"Original Size" forState:UIControlStateNormal]; //原始大小 95 | [btnZoomOriginal addTarget:self action:@selector(zoomOriginalAction:) forControlEvents:UIControlEventTouchUpInside]; 96 | [self.view addSubview:btnZoomOriginal]; 97 | 98 | // 99 | rect = CGRectMake(btnZoomUp.frame.origin.x , 100 | btnZoomUp.frame.origin.y + btnZoomUp.frame.size.height + 10, 101 | btnZoomDown.frame.size.width, 102 | btnZoomDown.frame.size.height); 103 | UIButton *btnZoomHorizontaUp = [UIButton buttonWithType:UIButtonTypeSystem]; 104 | btnZoomHorizontaUp.frame = rect; 105 | btnZoomHorizontaUp.titleLabel.font = btnZoomUp.titleLabel.font; 106 | [btnZoomHorizontaUp setTitle:@"Zoom In Horizontal" forState:UIControlStateNormal]; //水平放大 107 | [btnZoomHorizontaUp addTarget:self action:@selector(zoomHorizontaUpAction:) forControlEvents:UIControlEventTouchUpInside]; 108 | [self.view addSubview:btnZoomHorizontaUp]; 109 | 110 | // 111 | rect = CGRectMake(btnZoomHorizontaUp.frame.origin.x + btnZoomHorizontaUp.frame.size.width + 25, 112 | btnZoomHorizontaUp.frame.origin.y, 113 | btnZoomHorizontaUp.frame.size.width, 114 | btnZoomHorizontaUp.frame.size.height); 115 | UIButton *btnZoomHorizontaDown = [UIButton buttonWithType:UIButtonTypeSystem]; 116 | btnZoomHorizontaDown.frame = rect; 117 | btnZoomHorizontaDown.titleLabel.font = btnZoomUp.titleLabel.font; 118 | // btnZoomHorizontaDown.titleLabel.textColor = [UIColor blueColor]; 119 | // btnZoomHorizontaDown.backgroundColor = [UIColor clearColor]; 120 | [btnZoomHorizontaDown setTitle:@"Zoom Out Horizontal" forState:UIControlStateNormal]; //水平缩小 121 | [btnZoomHorizontaDown addTarget:self action:@selector(zoomHorizontaDownAction:) forControlEvents:UIControlEventTouchUpInside]; 122 | [self.view addSubview:btnZoomHorizontaDown]; 123 | 124 | // 125 | rect = CGRectMake(btnZoomUp.frame.origin.x , 126 | btnZoomHorizontaUp.frame.origin.y + btnZoomHorizontaUp.frame.size.height + 10, 127 | btnZoomHorizontaDown.frame.size.width, 128 | btnZoomHorizontaDown.frame.size.height); 129 | UIButton *btnZoomVerticalUp = [UIButton buttonWithType:UIButtonTypeSystem]; 130 | btnZoomVerticalUp.frame = rect; 131 | btnZoomVerticalUp.titleLabel.font = btnZoomUp.titleLabel.font; 132 | [btnZoomVerticalUp setTitle:@"Zoom In Vertical" forState:UIControlStateNormal]; //垂直放大 133 | [btnZoomVerticalUp addTarget:self action:@selector(zoomVerticalUpAction:) forControlEvents:UIControlEventTouchUpInside]; 134 | [self.view addSubview:btnZoomVerticalUp]; 135 | 136 | // 137 | rect = CGRectMake(btnZoomVerticalUp.frame.origin.x + btnZoomVerticalUp.frame.size.width + 25, 138 | btnZoomVerticalUp.frame.origin.y, 139 | btnZoomVerticalUp.frame.size.width, 140 | btnZoomVerticalUp.frame.size.height); 141 | UIButton *btnZoomVerticalDown = [UIButton buttonWithType:UIButtonTypeSystem]; 142 | btnZoomVerticalDown.frame = rect; 143 | btnZoomVerticalDown.titleLabel.font = btnZoomUp.titleLabel.font; 144 | [btnZoomVerticalDown setTitle:@"Zoom Out Vertical" forState:UIControlStateNormal]; //垂直缩小 145 | [btnZoomVerticalDown addTarget:self action:@selector(zoomVerticalDownAction:) forControlEvents:UIControlEventTouchUpInside]; 146 | [self.view addSubview:btnZoomVerticalDown]; 147 | 148 | 149 | 150 | } 151 | 152 | - (void)didReceiveMemoryWarning 153 | { 154 | [super didReceiveMemoryWarning]; 155 | // Dispose of any resources that can be recreated. 156 | } 157 | 158 | - (void)zoomUpAction:(id)sender 159 | { 160 | [self.lineChartView zoomUp]; 161 | } 162 | - (void)zoomDownAction:(id)sender 163 | { 164 | [self.lineChartView zoomDown]; 165 | } 166 | - (void)zoomOriginalAction:(id)sender 167 | { 168 | [self.lineChartView zoomOriginal]; 169 | } 170 | - (void)zoomHorizontaUpAction:(id)sender 171 | { 172 | [self.lineChartView zoomHorizontalUp]; 173 | } 174 | - (void)zoomHorizontaDownAction:(id)sender 175 | { 176 | [self.lineChartView zoomHorizontalDown]; 177 | } 178 | - (void)zoomVerticalUpAction:(id)sender 179 | { 180 | [self.lineChartView zoomVerticalUp]; 181 | } 182 | - (void)zoomVerticalDownAction:(id)sender 183 | { 184 | [self.lineChartView zoomVerticalDown]; 185 | } 186 | 187 | @end 188 | 189 | -------------------------------------------------------------------------------- /ARLineChartDemo/Base.lproj/Main_iPad.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 | -------------------------------------------------------------------------------- /ARLineChartDemo/Base.lproj/Main_iPhone.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 | -------------------------------------------------------------------------------- /ARLineChartDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /ARLineChartDemo/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 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /ARLineChartDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ARLineChartDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ARLineChartDemo 4 | // 5 | // Created by LongJun on 14-2-14. 6 | // Copyright (c) 2014年 Arwer Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ARAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ARAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ARLineChartDemoTests/ARLineChartDemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.arwer.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ARLineChartDemoTests/ARLineChartDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ARLineChartDemoTests.m 3 | // ARLineChartDemoTests 4 | // 5 | // Created by LongJun on 14-2-14. 6 | // Copyright (c) 2014年 Arwer Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ARLineChartDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ARLineChartDemoTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ARLineChartDemoTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 LongJun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ARLineChart 2 | =========== 3 | 4 | ARLineChart is a line char view on iOS , written using Objective-C . There are scenarios for applications requiring dual- Y axis. 5 | x -axis and y-axis can zoom in and out , you can scroll , double-click can restore the original size. 6 | 7 | ARLineChart是一个iOS的折线图,使用Objective-C编写。适用于需要有双Y轴的应用场景。 8 | x轴和y轴可以放大和缩小,可以滚动,双击可以还原原始大小。 9 | 10 | ![image](https://raw.githubusercontent.com/longjun3000/ARLineChart/master/Screenshot01.png) 11 | ![image](https://raw.githubusercontent.com/longjun3000/ARLineChart/master/Screenshot02.png) 12 | 13 | How to use ? 14 | ============ 15 | 1. "ARLineChart" folder all the files can be added to the project . 16 | 17 | 2. where it is needed to introduce the header file : 18 | ``` 19 | #import "ARLineChartView.h" 20 | #import "ARLineChartCommon.h" 21 | ``` 22 | 23 | 3. the initialization data sources, such as : 24 | ``` 25 | NSMutableArray *dataSource = [NSMutableArray array]; 26 | double distanceMin = 0, distanceMax = 100; 27 | double altitudeMin = 5.0, altitudeMax = 50; 28 | double speedMin = 0.5, speedMax = 15; 29 | 30 | srand(time(NULL)); //Random seed 31 | 32 | for (int i=0; i< 11; i++) { 33 | 34 | ARLineChartItem *item = [[ARLineChartItem alloc] init]; 35 | double randVal; 36 | 37 | randVal = rand() /((double)(RAND_MAX)/distanceMax) + distanceMin; 38 | item.xValue = randVal; 39 | 40 | randVal = rand() /((double)(RAND_MAX)/altitudeMax) + altitudeMin; 41 | item.y1Value = randVal; 42 | 43 | randVal = rand() /((double)(RAND_MAX)/speedMax) + speedMin; 44 | item.y2Value = randVal; 45 | 46 | NSLog(@"Random: item.xValue=%.2lf, item.y1Value=%.2lf, item.y2Value=%.2lf", item.xValue, item.y1Value, item.y2Value); 47 | [dataSource addObject:item]; 48 | } 49 | ``` 50 | 51 | 4. the initialization line chart view: 52 | ``` 53 | CGRect rect = CGRectMake (5, 40, self.view.frame.size.width - 5 - 5, 300); 54 | self.lineChartView = [[ARLineChartView alloc] initWithFrame: rect dataSource: dataSource xTitle: @ "Kilometre" y1Title: @ "Altitude (meters)" y2Title: @ "Speed ​​(km / h)" desc1: @ "Altitude" desc2: @ "Speed"]; 55 | [self.view addSubview: self.lineChartView]; 56 | ``` 57 | 58 | 如何使用? 59 | ======== 60 | 1、将“ARLineChart”文件夹内所有文件加入到工程中即可。 61 | 62 | 2、在需要的地方引入头文件: 63 | ``` 64 | #import "ARLineChartView.h" 65 | #import "ARLineChartCommon.h" 66 | ``` 67 | 68 | 3、初始化数据源,例如: 69 | ``` 70 | NSMutableArray *dataSource = [NSMutableArray array]; 71 | double distanceMin = 0, distanceMax = 100; 72 | double altitudeMin = 5.0, altitudeMax = 50; 73 | double speedMin = 0.5, speedMax = 15; 74 | 75 | srand(time(NULL)); //Random seed 76 | 77 | for (int i=0; i< 11; i++) { 78 | 79 | ARLineChartItem *item = [[ARLineChartItem alloc] init]; 80 | double randVal; 81 | 82 | randVal = rand() /((double)(RAND_MAX)/distanceMax) + distanceMin; 83 | item.xValue = randVal; 84 | 85 | randVal = rand() /((double)(RAND_MAX)/altitudeMax) + altitudeMin; 86 | item.y1Value = randVal; 87 | 88 | randVal = rand() /((double)(RAND_MAX)/speedMax) + speedMin; 89 | item.y2Value = randVal; 90 | 91 | NSLog(@"Random: item.xValue=%.2lf, item.y1Value=%.2lf, item.y2Value=%.2lf", item.xValue, item.y1Value, item.y2Value); 92 | [dataSource addObject:item]; 93 | } 94 | ``` 95 | 96 | 4、初始化折线图视图: 97 | ``` 98 | CGRect rect = CGRectMake (5, 40, self.view.frame.size.width - 5 - 5, 300); 99 | self.lineChartView = [[ARLineChartView alloc] initWithFrame: rect dataSource: dataSource xTitle: @ "Kilometre" y1Title: @ "Altitude (meters)" y2Title: @ "Speed ​​(km / h)" desc1: @ "Altitude" desc2: @ "Speed"]; 100 | [self.view addSubview: self.lineChartView]; 101 | ``` 102 | 103 | 104 | Contact 105 | ======= 106 | ArwerSoftware@gmail.com 107 | 108 | 联系方式 109 | ======= 110 | ArwerSoftware@gmail.com 111 | 112 | 113 | License 114 | ======= 115 | The MIT License (MIT) 116 | 117 | Copyright © 2014 LongJun 118 | 119 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 120 | 121 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 122 | 123 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 124 | 125 | -------------------------------------------------------------------------------- /Screenshot01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/longjun3000/ARLineChart/fe51ced0a476c906f0f9e6b87915f438f1e756a8/Screenshot01.png -------------------------------------------------------------------------------- /Screenshot02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/longjun3000/ARLineChart/fe51ced0a476c906f0f9e6b87915f438f1e756a8/Screenshot02.png --------------------------------------------------------------------------------