diff --git a/JHChartDemo.xcodeproj/project.pbxproj b/JHChartDemo.xcodeproj/project.pbxproj index 5fa37d0..42d6cad 100644 --- a/JHChartDemo.xcodeproj/project.pbxproj +++ b/JHChartDemo.xcodeproj/project.pbxproj @@ -50,6 +50,10 @@ E9D49A191E0927EC000453F0 /* 柱状图demo2.png in Resources */ = {isa = PBXBuildFile; fileRef = E9D49A181E0927EC000453F0 /* 柱状图demo2.png */; }; E9D49A1B1E092D21000453F0 /* 饼状图demo1.png in Resources */ = {isa = PBXBuildFile; fileRef = E9D49A1A1E092D21000453F0 /* 饼状图demo1.png */; }; E9DAFF3E1D6EB6E900D4E148 /* JHTableDataRowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E9DAFF3D1D6EB6E900D4E148 /* JHTableDataRowModel.m */; }; + F133F98C1FDA476E0056E5A5 /* UIDebuggingInformationOverlay+Enable.m in Sources */ = {isa = PBXBuildFile; fileRef = F133F98B1FDA476D0056E5A5 /* UIDebuggingInformationOverlay+Enable.m */; }; + F1743D651FCFBB7300B2738A /* JHRowItem.m in Sources */ = {isa = PBXBuildFile; fileRef = F1743D641FCFBB7300B2738A /* JHRowItem.m */; }; + F1B4D44D1FCFF3020035E16D /* JHRowChart.m in Sources */ = {isa = PBXBuildFile; fileRef = F1743D611FCFBB0200B2738A /* JHRowChart.m */; }; + F1E85A481FD7C91E00713875 /* JHDualBarChart.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E85A471FD7C91E00713875 /* JHDualBarChart.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -138,6 +142,13 @@ E9D49A1A1E092D21000453F0 /* 饼状图demo1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "饼状图demo1.png"; sourceTree = ""; }; E9DAFF3C1D6EB6E900D4E148 /* JHTableDataRowModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JHTableDataRowModel.h; sourceTree = ""; }; E9DAFF3D1D6EB6E900D4E148 /* JHTableDataRowModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JHTableDataRowModel.m; sourceTree = ""; }; + F133F98B1FDA476D0056E5A5 /* UIDebuggingInformationOverlay+Enable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDebuggingInformationOverlay+Enable.m"; sourceTree = ""; }; + F1743D601FCFBB0200B2738A /* JHRowChart.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JHRowChart.h; sourceTree = ""; }; + F1743D611FCFBB0200B2738A /* JHRowChart.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHRowChart.m; sourceTree = ""; }; + F1743D631FCFBB7300B2738A /* JHRowItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JHRowItem.h; sourceTree = ""; }; + F1743D641FCFBB7300B2738A /* JHRowItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHRowItem.m; sourceTree = ""; }; + F1E85A461FD7C91E00713875 /* JHDualBarChart.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JHDualBarChart.h; sourceTree = ""; }; + F1E85A471FD7C91E00713875 /* JHDualBarChart.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHDualBarChart.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -265,6 +276,12 @@ 7DEA76341F09DD720060D893 /* JHColumnItem.m */, 7DEA76361F0A34200060D893 /* JHIndexPath.h */, 7DEA76371F0A34200060D893 /* JHIndexPath.m */, + F1743D601FCFBB0200B2738A /* JHRowChart.h */, + F1743D611FCFBB0200B2738A /* JHRowChart.m */, + F1743D631FCFBB7300B2738A /* JHRowItem.h */, + F1743D641FCFBB7300B2738A /* JHRowItem.m */, + F1E85A461FD7C91E00713875 /* JHDualBarChart.h */, + F1E85A471FD7C91E00713875 /* JHDualBarChart.m */, ); path = JHChart; sourceTree = ""; @@ -272,6 +289,7 @@ AAF615181CBF9E7F00E066C3 /* GIFResource */ = { isa = PBXGroup; children = ( + F133F98B1FDA476D0056E5A5 /* UIDebuggingInformationOverlay+Enable.m */, 7D5EE57A1EE67E5500246792 /* 折线图demo-1.png */, 7D5EE5781EE67E4B00246792 /* 表格图demo-1.png */, E92CB0401E0BDBFF00861E35 /* 散点图demo1.png */, @@ -357,12 +375,12 @@ AA5E2BA61CBA298F00FC19EE /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = JH; TargetAttributes = { AA5E2BAD1CBA298F00FC19EE = { CreatedOnToolsVersion = 7.2.1; - DevelopmentTeam = HRJA43XU8W; + DevelopmentTeam = A4ZY6X2WCR; }; AA5E2BC61CBA298F00FC19EE = { CreatedOnToolsVersion = 7.2.1; @@ -448,12 +466,15 @@ AA0031601CBCCFD500F4FDEB /* JHShowController.m in Sources */, E9135FE61D2B810B00ED9F6D /* JHRingChart.m in Sources */, AAA60A8F1CD8A81A0094D6E5 /* JHPieChart.m in Sources */, + F1B4D44D1FCFF3020035E16D /* JHRowChart.m in Sources */, + F133F98C1FDA476E0056E5A5 /* UIDebuggingInformationOverlay+Enable.m in Sources */, E92CB03F1E0BA14900861E35 /* JHScatterChart.m in Sources */, AA57D8A91CD9C492003EA0A7 /* JHShowInfoView.m in Sources */, AAA60A911CD8A81A0094D6E5 /* JHPieItemsView.m in Sources */, 7DEA76351F09DD720060D893 /* JHColumnItem.m in Sources */, AAE935E81CBE0CCA002517EB /* JHWaveChart.m in Sources */, AA5E2BE71CBA2B3100FC19EE /* JHLineChart.m in Sources */, + F1E85A481FD7C91E00713875 /* JHDualBarChart.m in Sources */, E922F8051D82A8B0000C7C77 /* JHRadarChart.m in Sources */, 7DEA76381F0A34200060D893 /* JHIndexPath.m in Sources */, AA5E2BEA1CBA2CE700FC19EE /* JHChart.m in Sources */, @@ -462,6 +483,7 @@ AA5E2BB61CBA298F00FC19EE /* AppDelegate.m in Sources */, AAA60A901CD8A81A0094D6E5 /* JHPieForeBGView.m in Sources */, AA5E2BB31CBA298F00FC19EE /* main.m in Sources */, + F1743D651FCFBB7300B2738A /* JHRowItem.m in Sources */, E9DAFF3E1D6EB6E900D4E148 /* JHTableDataRowModel.m in Sources */, E90C3EB01D6D971A0019BE6A /* JHTableChart.m in Sources */, ); @@ -526,13 +548,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -569,13 +599,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -604,6 +642,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = A4ZY6X2WCR; INFOPLIST_FILE = JHChartDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -619,6 +658,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = A4ZY6X2WCR; INFOPLIST_FILE = JHChartDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; diff --git a/JHChartDemo.xcodeproj/xcuserdata/Mayqiyue.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/JHChartDemo.xcodeproj/xcuserdata/Mayqiyue.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/JHChartDemo.xcodeproj/xcuserdata/Mayqiyue.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/JHChartDemo.xcodeproj/xcuserdata/Mayqiyue.xcuserdatad/xcschemes/xcschememanagement.plist b/JHChartDemo.xcodeproj/xcuserdata/Mayqiyue.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..d40c537 --- /dev/null +++ b/JHChartDemo.xcodeproj/xcuserdata/Mayqiyue.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + JHChartDemo.xcscheme + + orderHint + 0 + + + + diff --git a/JHChartDemo/.DS_Store b/JHChartDemo/.DS_Store index 3de11bb..13919dc 100644 Binary files a/JHChartDemo/.DS_Store and b/JHChartDemo/.DS_Store differ diff --git a/JHChartDemo/AppDelegate.m b/JHChartDemo/AppDelegate.m index 894409f..1622fad 100644 --- a/JHChartDemo/AppDelegate.m +++ b/JHChartDemo/AppDelegate.m @@ -17,6 +17,10 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. +#if DEBUG + id overlayClass = NSClassFromString(@"UIDebuggingInformationOverlay"); + [overlayClass performSelector:NSSelectorFromString(@"prepareDebuggingOverlay")]; +#endif return YES; } diff --git a/JHChartDemo/Base.lproj/Main.storyboard b/JHChartDemo/Base.lproj/Main.storyboard index 1803b36..c44d933 100644 --- a/JHChartDemo/Base.lproj/Main.storyboard +++ b/JHChartDemo/Base.lproj/Main.storyboard @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -10,7 +14,7 @@ - + @@ -30,9 +34,9 @@ - + - + diff --git a/JHChartDemo/GIFResource/UIDebuggingInformationOverlay+Enable.m b/JHChartDemo/GIFResource/UIDebuggingInformationOverlay+Enable.m new file mode 100644 index 0000000..3853a38 --- /dev/null +++ b/JHChartDemo/GIFResource/UIDebuggingInformationOverlay+Enable.m @@ -0,0 +1,99 @@ +// +// UIDebuggingInformationOverlay+Enable.m +// UIDebuggingInformationOverlay +// +// Created by whf5566 on 2017/12/05. +// Copyright © 2017年 whf5566. All rights reserved. +// + +#import +#import + + +/* + In iOS 11, Apple added additional checks to disable this overlay unless the + device is an internal device. To get around this, we swizzle out the + -[UIDebuggingInformationOverlay init] method (which returns nil now if + the device is non-internal) and +[UIDebuggingInformationOverlay prepareDebuggingOverlay] + method. + + Usage: + 1.Copy this file to your project. + 2.Add the following code to [AppDelegate application:didFinishLaunchingWithOptions:] + + #if DEBUG + id overlayClass = NSClassFromString(@"UIDebuggingInformationOverlay"); + [overlayClass performSelector:NSSelectorFromString(@"prepareDebuggingOverlay")]; + #endif + + */ + + +#if defined(DEBUG) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0 + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincomplete-implementation" +#pragma clang diagnostic ignored "-Wundeclared-selector" +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +@interface UIWindow (PrivateMethods) +- (void)_setWindowControlsStatusBarOrientation:(BOOL)orientation; +@end + +@interface FakeWindowClass : UIWindow +@end + +@implementation FakeWindowClass + +- (instancetype)initSwizzled { + self = [super init]; + if (self) { + [self _setWindowControlsStatusBarOrientation:NO]; + } + return self; +} + +@end + +@implementation NSObject (UIDebuggingInformationOverlayEnable) + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class cls = NSClassFromString(@"UIDebuggingInformationOverlay"); + [FakeWindowClass swizzleSelector:@selector(init) newSelector:@selector(initSwizzled) forClass:cls isClassMethod:NO]; + [self swizzleSelector:@selector(prepareDebuggingOverlay) newSelector:@selector(prepareDebuggingOverlaySwizzled) forClass:cls isClassMethod:YES]; + }); +} + ++ (void)swizzleSelector:(SEL)originalSelector newSelector:(SEL)swizzledSelector forClass:(Class)class isClassMethod:(BOOL)isClassMethod { + Method originalMethod = NULL; + Method swizzledMethod = NULL; + + if (isClassMethod) { + originalMethod = class_getClassMethod(class, originalSelector); + swizzledMethod = class_getClassMethod([self class], swizzledSelector); + } else { + originalMethod = class_getInstanceMethod(class, originalSelector); + swizzledMethod = class_getInstanceMethod([self class], swizzledSelector); + } + method_exchangeImplementations(originalMethod, swizzledMethod); +} + ++ (void)prepareDebuggingOverlaySwizzled { + id overlayClass = NSClassFromString(@"UIDebuggingInformationOverlayInvokeGestureHandler"); + id handler = [overlayClass performSelector:NSSelectorFromString(@"mainHandler")]; + + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:handler action:@selector(_handleActivationGesture:)]; + tapGesture.numberOfTouchesRequired = 2; + tapGesture.numberOfTapsRequired = 1; + tapGesture.delegate = handler; + + UIView *statusBarWindow = [[UIApplication sharedApplication] valueForKey:@"statusBarWindow"]; + [statusBarWindow addGestureRecognizer:tapGesture]; +} + +@end +#pragma clang diagnostic pop + +#endif diff --git a/JHChartDemo/JHChart/JHChart.h b/JHChartDemo/JHChart/JHChart.h index 32a0cbf..603cf74 100644 --- a/JHChartDemo/JHChart/JHChart.h +++ b/JHChartDemo/JHChart/JHChart.h @@ -11,9 +11,14 @@ #import #define P_M(x,y) CGPointMake(x, y) +#define G_W(r) CGRectGetWidth(r) +#define G_H(r) CGRectGetHeight(r) + +#define SAFE_ACCESS(a, i) (((a).count > i) ? (a)[i] : nil) #define weakSelf(weakSelf) __weak typeof(self) weakself = self; #define XORYLINEMAXSIZE CGSizeMake(CGFLOAT_MAX,30) + @interface JHChart : UIView @@ -150,4 +155,7 @@ - (CGSize)sizeOfStringWithMaxSize:(CGSize)maxSize textFont:(CGFloat)fontSize aimString:(NSString *)aimString; + +- (CGSize)sizeOfString:(NSString *)string withFont:(UIFont *)font; + @end diff --git a/JHChartDemo/JHChart/JHChart.m b/JHChartDemo/JHChart/JHChart.m index d5e13fd..6e69b34 100644 --- a/JHChartDemo/JHChart/JHChart.m +++ b/JHChartDemo/JHChart/JHChart.m @@ -155,12 +155,16 @@ - (void)drawPointWithRedius:(CGFloat)redius andColor:(UIColor *)color andPoint:( * @return 占用尺寸 */ - (CGSize)sizeOfStringWithMaxSize:(CGSize)maxSize textFont:(CGFloat)fontSize aimString:(NSString *)aimString{ - - return [[NSString stringWithFormat:@"%@",aimString] boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} context:nil].size; - } +- (CGSize)sizeOfString:(NSString *)string withFont:(UIFont *)font { + return [string boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) + options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine + attributes:@{NSFontAttributeName:font} context:nil].size; +} + + -(void)dealloc{ #if DEBUG NSLog(@"%@ has dealloc",NSStringFromClass([self class])); diff --git a/JHChartDemo/JHChart/JHChartHeader.h b/JHChartDemo/JHChart/JHChartHeader.h index 4970660..16aef55 100644 --- a/JHChartDemo/JHChart/JHChartHeader.h +++ b/JHChartDemo/JHChart/JHChartHeader.h @@ -6,13 +6,15 @@ // Copyright © 2016年 JH. All rights reserved. // - #import "JHChart.h" #import "JHLineChart.h" #import "JHWaveChart.h" #import "JHPieChart.h" #import "JHRingChart.h" #import "JHColumnChart.h" +#import "JHRowChart.h" +#import "JHRowChart.h" #import "JHTableChart.h" #import "JHRadarChart.h" #import "JHScatterChart.h" +#import "JHDualBarChart.h" diff --git a/JHChartDemo/JHChart/JHColumnChart.h b/JHChartDemo/JHChart/JHColumnChart.h index d34392a..6eef798 100644 --- a/JHChartDemo/JHChart/JHColumnChart.h +++ b/JHChartDemo/JHChart/JHColumnChart.h @@ -17,7 +17,6 @@ @interface JHColumnChart : JHChart - /** * Each histogram of the background color, if you do not set the default value for green. Setup must ensure that the number and type of the data source array are the same, otherwise the default is not set. */ @@ -36,15 +35,13 @@ */ @property (nonatomic, strong) NSArray * xShowInfoText; - /** * The background color of the content view */ @property (nonatomic, strong) UIColor * bgVewBackgoundColor; - /** - * Column spacing, non continuous, default is 5 + * Column spacing, non continuous, default is 15 */ @property (nonatomic, assign) CGFloat typeSpace; @@ -93,13 +90,11 @@ */ @property (nonatomic,assign) BOOL isShowLineChart; - /** * If isShowLineChart proprety is YES,we need this value array to draw chart */ @property (nonatomic,strong)NSArray * lineValueArray; - /** * If isShowLineChart proprety is Yes,we will draw path of this linechart with this color * Default is blue @@ -112,7 +107,4 @@ */ @property (nonatomic,strong)UIColor * lineChartValuePointColor; - - - @end diff --git a/JHChartDemo/JHChart/JHColumnChart.m b/JHChartDemo/JHChart/JHColumnChart.m index ff08944..710418a 100644 --- a/JHChartDemo/JHChart/JHColumnChart.m +++ b/JHChartDemo/JHChart/JHColumnChart.m @@ -9,6 +9,7 @@ #import "JHColumnChart.h" #import #import "JHColumnItem.h" + @interface JHColumnChart () //背景图 @@ -44,80 +45,55 @@ -(NSMutableArray *)drawLineValue{ } -(NSMutableArray *)showViewArr{ - - if (!_showViewArr) { _showViewArr = [NSMutableArray array]; } return _showViewArr; - } -(NSMutableArray *)layerArr{ - - if (!_layerArr) { _layerArr = [NSMutableArray array]; } - return _layerArr; } - -(UIScrollView *)BGScrollView{ - - if (!_BGScrollView) { - _BGScrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; _BGScrollView.showsHorizontalScrollIndicator = NO; _BGScrollView.backgroundColor = _bgVewBackgoundColor; [self addSubview:_BGScrollView]; } - return _BGScrollView; - - } - -(void)setBgVewBackgoundColor:(UIColor *)bgVewBackgoundColor{ - _bgVewBackgoundColor = bgVewBackgoundColor; self.BGScrollView.backgroundColor = _bgVewBackgoundColor; - } - -(NSMutableArray *)yLineDataArr{ - - if (!_yLineDataArr) { _yLineDataArr = [NSMutableArray array]; } return _yLineDataArr; - } -(instancetype)initWithFrame:(CGRect)frame{ - - if (self = [super initWithFrame:frame]) { - _needXandYLine = YES; _isShowYLine = YES; _lineChartPathColor = [UIColor blueColor]; _lineChartValuePointColor = [UIColor yellowColor]; } return self; - } -(void)setLineValueArray:(NSArray *)lineValueArray{ - if (!_isShowLineChart) { return; } @@ -143,8 +119,6 @@ -(void)setLineValueArray:(NSArray *)lineValueArray{ _maxHeight += 4; _perHeight = (CGRectGetHeight(self.frame) - 30 - _originSize.y)/_maxHeight; - - } -(void)setValueArr:(NSArray *)valueArr{ @@ -152,12 +126,12 @@ -(void)setValueArr:(NSArray *)valueArr{ _valueArr = valueArr; CGFloat max = 0; - + for (NSArray *arr in _valueArr) { for (id number in arr) { CGFloat currentNumber = 0; - + if ([number isKindOfClass:[NSArray class]]) { for (id sub in number) { currentNumber += [NSString stringWithFormat:@"%@",sub].floatValue; @@ -168,9 +142,7 @@ -(void)setValueArr:(NSArray *)valueArr{ if (currentNumber>max) { max = currentNumber; } - } - } if (max<5.0) { @@ -183,13 +155,11 @@ -(void)setValueArr:(NSArray *)valueArr{ _maxHeight += 4; _perHeight = (CGRectGetHeight(self.frame) - 30 - _originSize.y - self.contentInsets.top)/_maxHeight; - - } -(void)showAnimation{ - + [self clear]; _columnWidth = (_columnWidth<=0?30:_columnWidth); @@ -210,23 +180,17 @@ -(void)showAnimation{ UIBezierPath *bezier = [UIBezierPath bezierPath]; if (self.isShowYLine) { - [bezier moveToPoint:CGPointMake(self.originSize.x, CGRectGetHeight(self.frame) - self.originSize.y)]; - [bezier addLineToPoint:P_M(self.originSize.x, 20)]; + [bezier moveToPoint:P_M(self.originSize.x, CGRectGetHeight(self.frame) - self.originSize.y)]; + [bezier addLineToPoint:P_M(self.originSize.x, 20)]; } - - [bezier moveToPoint:CGPointMake(self.originSize.x, CGRectGetHeight(self.frame) - self.originSize.y)]; - - [bezier addLineToPoint:P_M(_maxWidth , CGRectGetHeight(self.frame) - self.originSize.y)]; - + [bezier moveToPoint:P_M(self.originSize.x, CGRectGetHeight(self.frame) - self.originSize.y)]; + [bezier addLineToPoint:P_M(_maxWidth, CGRectGetHeight(self.frame) - self.originSize.y)]; layer.path = bezier.CGPath; - layer.strokeColor = (_colorForXYLine==nil?([UIColor blackColor].CGColor):_colorForXYLine.CGColor); - - + CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; - basic.duration = self.isShowYLine?1.5:0.75; basic.fromValue = @(0); @@ -237,13 +201,10 @@ -(void)showAnimation{ basic.fillMode = kCAFillModeForwards; - [layer addAnimation:basic forKey:nil]; [self.BGScrollView.layer addSublayer:layer]; -// _maxHeight += 4; - /* 设置虚线辅助线 */ UIBezierPath *second = [UIBezierPath bezierPath]; for (NSInteger i = 0; i<5; i++) { @@ -251,11 +212,8 @@ -(void)showAnimation{ CGFloat height = _perHeight * (i+1)*pace; [second moveToPoint:P_M(_originSize.x, CGRectGetHeight(self.frame) - _originSize.y -height)]; [second addLineToPoint:P_M(_maxWidth, CGRectGetHeight(self.frame) - _originSize.y - height)]; - - - + CATextLayer *textLayer = [CATextLayer layer]; - textLayer.contentsScale = [UIScreen mainScreen].scale; NSString *text =[NSString stringWithFormat:@"%ld",(i + 1) * pace]; CGFloat be = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:text].width; @@ -273,44 +231,27 @@ -(void)showAnimation{ textLayer.foregroundColor = (_drawTextColorForX_Y==nil?[UIColor blackColor].CGColor:_drawTextColorForX_Y.CGColor); [_BGScrollView.layer addSublayer:textLayer]; [self.layerArr addObject:textLayer]; - } CAShapeLayer *shapeLayer = [CAShapeLayer layer]; - shapeLayer.path = second.CGPath; - shapeLayer.strokeColor = (_dashColor==nil?([UIColor darkGrayColor].CGColor):_dashColor.CGColor); - shapeLayer.lineWidth = 0.5; - [shapeLayer setLineDashPattern:@[@(3),@(3)]]; CABasicAnimation *basic2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; - - basic2.duration = 1.5; - basic2.fromValue = @(0); - basic2.toValue = @(1); - basic2.autoreverses = NO; - - - basic2.fillMode = kCAFillModeForwards; [shapeLayer addAnimation:basic2 forKey:nil]; [self.BGScrollView.layer addSublayer:shapeLayer]; [self.layerArr addObject:shapeLayer]; - } - - - /* 绘制X轴提示语 不管是否设置了是否绘制X、Y轴 提示语都应有 */ if (_xShowInfoText.count == _valueArr.count&&_xShowInfoText.count>0) { @@ -318,50 +259,28 @@ -(void)showAnimation{ for (NSInteger i = 0; i<_xShowInfoText.count; i++) { - - CATextLayer *textLayer = [CATextLayer layer]; - CGFloat wid = count * _columnWidth; - - - CGSize size = [_xShowInfoText[i] boundingRectWithSize:CGSizeMake(wid, MAXFLOAT) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:self.xDescTextFontSize]} context:nil].size; - textLayer.frame = CGRectMake( i * (count * _columnWidth + _typeSpace) + _typeSpace + _originSize.x+ _drawFromOriginX, CGRectGetHeight(self.frame) - _originSize.y+5,wid, size.height); textLayer.string = _xShowInfoText[i]; textLayer.contentsScale = [UIScreen mainScreen].scale; - UIFont *font = [UIFont systemFontOfSize:self.xDescTextFontSize]; - - + UIFont *font = [UIFont systemFontOfSize:self.xDescTextFontSize]; textLayer.fontSize = font.pointSize; - textLayer.foregroundColor = _drawTextColorForX_Y.CGColor; - textLayer.alignmentMode = kCAAlignmentCenter; [_BGScrollView.layer addSublayer:textLayer]; - [self.layerArr addObject:textLayer]; - - } - - } - - - - - /* 动画展示 */ for (NSInteger i = 0; i<_valueArr.count; i++) { - NSArray *arr = _valueArr[i]; - + for (NSInteger j = 0; j*leftBarBGColors; + +@property (nonatomic, strong) NSArray *rightBarBGColors; + +/** + * Data source array + */ +@property (nonatomic, strong) NSArray *leftBarValues; +@property (nonatomic, strong) NSArray *rightBarValues; + +/** + * X axis classification of each icon + */ +@property (nonatomic, strong) NSArray *xTexts; + +@property (nonatomic, assign) CGFloat yLeftRadix; + +@property (nonatomic, assign) CGFloat yRightRadix; + +/** + * X axis classification of each icon + */ +@property (nonatomic, assign) NSUInteger levelLineNum; + +@property (nonatomic, copy) UIFont *xTextFont; + +@property (nonatomic, copy) UIFont *yleftTextFont; + +@property (nonatomic, copy) UIFont *yRightTextFont; + +@property (nonatomic, copy) UIFont *barTextFont; + +@property (nonatomic, copy) NSString *yLeftDetailText; + +@property (nonatomic, copy) NSString *yRightDetailText; + +@property (nonatomic, copy) UIFont *yDetailTextFont; + +@property (nonatomic, copy) UIFont *chartSubTitleFont; + +/** + * Whether the need for Y, X axis, the default YES + */ +@property (nonatomic, assign) BOOL needXLine; + +@property (nonatomic, assign) BOOL needYLines; + +@property (nonatomic, assign) BOOL needLeftYTexts; + +@property (nonatomic, assign) BOOL needRightYTexts; + +@property (nonatomic, assign) CGFloat leftYTextsMargin; + +/** + * The background color of the content view + */ +@property (nonatomic, strong) UIColor *chartBackgroundColor; + +/** + * Column spacing, non continuous, default is 15 + */ +@property (nonatomic, assign) CGFloat barSpacing; + +/** + * The width of the column, the default is 40 + */ +@property (nonatomic, assign) CGFloat barWidth; + +/** + * Y, X axis line color + */ +@property (nonatomic, strong) UIColor *colorForXYLine; + +/** + * X, Y axis text description color + */ +@property (nonatomic, strong) UIColor *drawTextColorForX_Y; + +/** + * Dotted line guide color + */ +@property (nonatomic, strong) UIColor *levelLineColor; + +/** + * Controls whether text for x-axis be straight or rotate 45 degree. + */ +@property (nonatomic) BOOL rotateForXAxisText; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * If showLineChart proprety is YES,we need this value array to draw chart + */ +/** + * Whether this chart show line or not.Default is NO; + */ +@property (nonatomic, assign) BOOL showLineChart; + + +@property (nonatomic, strong) NSArray *leftLineValues; + +/** + * If isShowLineChart proprety is Yes,we will draw path of this linechart with this color + * Default is blue + */ +@property (nonatomic, strong) UIColor *leftLinePathColor; + +/** + * if isShowLineChart proprety is Yes,we will draw this linechart valuepoint with this color + * Default is yellow + */ +@property (nonatomic, strong) UIColor *leftLinePointColor; + +@property (nonatomic, strong) NSArray *rightLineValues; + +/** + * If isShowLineChart proprety is Yes,we will draw path of this linechart with this color + * Default is blue + */ +@property (nonatomic, strong) UIColor *rightLinePathColor; + +/** + * if isShowLineChart proprety is Yes,we will draw this linechart valuepoint with this color + * Default is yellow + */ +@property (nonatomic, strong)UIColor *rightLinePointColor; + + +@end diff --git a/JHChartDemo/JHChart/JHDualBarChart.m b/JHChartDemo/JHChart/JHDualBarChart.m new file mode 100644 index 0000000..c159f20 --- /dev/null +++ b/JHChartDemo/JHChart/JHDualBarChart.m @@ -0,0 +1,517 @@ +// +// JHDualBarChart.m +// JHChartDemo +// +// Created by Mayqiyue on 06/12/2017. +// Copyright © 2017 JH. All rights reserved. +// + +#import "JHDualBarChart.h" +@interface JHDualBarChart () +{ + CGFloat _maxH, _maxW, lPerH, rPerH; +} + +@property (nonatomic, strong) UIScrollView *scrollView; + +@property (nonatomic, strong) NSMutableArray *leftBarViews; +@property (nonatomic, strong) NSMutableArray *rightBarViews; +@property (nonatomic, strong) NSMutableArray *layerArr; + +@property (nonatomic, strong) NSMutableArray *drawLineValue; + +@end + +@implementation JHDualBarChart + +- (instancetype)init { + self = [super init]; + if (self) { + NSAssert(false, @"Please use initWithFrame"); + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit { + [self addSubview:self.scrollView]; + + _needYLines = YES; + _needXLine = YES; + _needLeftYTexts = YES; + _needRightYTexts = YES; + _leftYTextsMargin = 5; + _xTextFont = [UIFont systemFontOfSize:8]; + _yRightTextFont = [UIFont systemFontOfSize:8]; + _yleftTextFont = [UIFont systemFontOfSize:8]; + _barTextFont = [UIFont systemFontOfSize:8]; + _yDetailTextFont = [UIFont systemFontOfSize:10]; + _chartSubTitleFont = [UIFont systemFontOfSize:16]; + _drawTextColorForX_Y = [UIColor blackColor]; + _colorForXYLine = [UIColor blackColor]; + _levelLineColor = [UIColor blackColor]; + _showLineChart = false; + self.contentInsets = UIEdgeInsetsMake(50, 50, 40, 50); + self.chartOrigin = CGPointMake(0, self.scrollView.frame.size.height-self.contentInsets.bottom); +} + +- (void)showAnimation { + NSAssert(self.leftBarBGColors.count > 0 || self.rightBarBGColors.count > 0, @""); + + [self clear]; + + _barWidth = _barWidth ? : 30; + _barSpacing = _barSpacing ?: 15; + _maxW = self.chartOrigin.x + _barWidth * (_leftBarValues.count + _rightBarValues.count) + _barSpacing * (1 + MAX(_leftBarValues.count, _rightBarValues.count)); + _maxH = self.frame.size.height - self.contentInsets.top - self.contentInsets.bottom; + lPerH = _maxH / (_levelLineNum * _yLeftRadix); + rPerH = _maxH / (_levelLineNum * _yRightRadix); + + self.scrollView.contentSize = CGSizeMake(_maxW, _maxH); + + CGPoint p = [self.scrollView convertPoint:self.chartOrigin toView:self]; + + [self drawChartTitles]; + [self drawXAndYAxis:p]; + [self drawLevelLines:p]; + [self drawDualYTexts:p]; + [self drawXTexts]; + [self drawBars]; +} + +- (void)drawChartTitles { + NSMutableArray *array = [NSMutableArray new]; + + if (self.leftBarValues.count > 0) { + CALayer *lump = [CALayer layer]; + lump.backgroundColor = self.leftBarBGColors.firstObject.CGColor; + lump.frame = CGRectMake(0, 0, 10, 10); + CATextLayer *l = [self createTextLayer:self.yLeftDetailText font:self.chartSubTitleFont color:self.leftBarBGColors.firstObject]; + CGRect f = l.frame; + f.size.width += 6; + l.frame = f; + + CALayer *container = [CALayer new]; + container.backgroundColor = [UIColor clearColor].CGColor; + container.frame = CGRectMake(0, 0, lump.frame.size.width + l.frame.size.width + 5, MAX(lump.frame.size.height, l.frame.size.height)); + + [container addSublayer:lump]; + [container addSublayer:l]; + + lump.position = P_M(lump.frame.size.width/2.0, container.frame.size.height/2.0); + l.position = P_M(lump.frame.size.width + 5 + l.frame.size.width/2.0, container.frame.size.height/2.0); + + [array addObject:container]; + } + if (self.rightBarValues.count > 0) { + CALayer *lump = [CALayer layer]; + lump.backgroundColor = self.rightBarBGColors.firstObject.CGColor; + lump.frame = CGRectMake(0, 0, 10, 10); + CATextLayer *l = [self createTextLayer:self.yRightDetailText font:self.chartSubTitleFont color:self.rightBarBGColors.firstObject]; + CGRect f = l.frame; + f.size.width += 6; + l.frame = f; + + + CALayer *container = [CALayer new]; + container.backgroundColor = [UIColor clearColor].CGColor; + container.frame = CGRectMake(0, 0, lump.frame.size.width + l.frame.size.width + 5, MAX(lump.frame.size.height, l.frame.size.height)); + + lump.position = P_M(lump.frame.size.width/2.0, container.frame.size.height/2.0); + l.position = P_M(lump.frame.size.width + 5 + l.frame.size.width/2.0, container.frame.size.height/2.0); + + [container addSublayer:lump]; + [container addSublayer:l]; + + [array addObject:container]; + } + + for (CALayer *l in array) { + [self.layerArr addObject:l]; + [self.layer addSublayer:l]; + } + + if (array.count == 1) { + array.firstObject.position = P_M(self.frame.size.width/2.0f, 30); + } + else if (array.count == 2) { + CGFloat h = 15; + CGFloat w = (self.frame.size.width - h - array.firstObject.frame.size.width - array[1].frame.size.width) / 2.0; + array.firstObject.position = P_M(w + array.firstObject.frame.size.width/2.0f, 30); + array[1].position = P_M(CGRectGetMaxX(array.firstObject.frame) + h + array[1].frame.size.width/2.0f, 30); + } +} + +- (void)drawXAndYAxis:(CGPoint)p { + if (_needXLine) { + UIBezierPath *bezier = [UIBezierPath bezierPath]; + [bezier moveToPoint:p]; + [bezier addLineToPoint:P_M(self.frame.size.width - p.x, p.y)]; + + if (_needYLines) { + [bezier moveToPoint:p]; + [bezier addLineToPoint:P_M(p.x, self.contentInsets.top)]; + [bezier moveToPoint:P_M(self.frame.size.width - p.x, p.y)]; + [bezier addLineToPoint:P_M(self.frame.size.width - p.x, self.contentInsets.top)]; + } + + CAShapeLayer *layer = [CAShapeLayer layer]; + layer.path = bezier.CGPath; + layer.strokeColor = _colorForXYLine.CGColor; + + [self.layer addSublayer:layer]; + [self.layerArr addObject:layer]; + } +} + +- (void)drawLevelLines:(CGPoint)p { + + UIBezierPath *path = [UIBezierPath bezierPath]; + for (NSInteger i = 1; i <_levelLineNum + 1; i++) { + CGFloat h = i * lPerH * _yLeftRadix; + [path moveToPoint:P_M(p.x, p.y - h)]; + [path addLineToPoint:P_M(self.frame.size.width - p.x, p.y - h)]; + } + + CABasicAnimation *basic2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + basic2.duration = 1.5; + basic2.fromValue = @(0); + basic2.toValue = @(1); + basic2.autoreverses = NO; + basic2.duration = 1.0; + basic2.fillMode = kCAFillModeForwards; + + CAShapeLayer *shapeLayer = [CAShapeLayer layer]; + shapeLayer.path = path.CGPath; + shapeLayer.strokeColor = _levelLineColor.CGColor; + shapeLayer.lineWidth = 0.5; + [shapeLayer setLineDashPattern:@[@(3),@(3)]]; + [shapeLayer addAnimation:basic2 forKey:nil]; + + [self.layer insertSublayer:shapeLayer atIndex:0]; + [self.layerArr addObject:shapeLayer]; +} + +- (void)drawXTexts { + /* Darw x texts*/ + for (NSInteger i = 0; i<_xTexts.count; i++) { + CATextLayer *textLayer = [CATextLayer layer]; + CGSize size = [self sizeOfStringWithMaxSize:CGSizeMake(MAXFLOAT, MAXFLOAT) textFont:self.xTextFont.pointSize aimString:_xTexts[i]]; + textLayer.bounds = CGRectMake(0, 0, size.width, size.height); + textLayer.string = _xTexts[i]; + textLayer.contentsScale = [UIScreen mainScreen].scale; + textLayer.fontSize = self.xTextFont.pointSize; + textLayer.foregroundColor = _drawTextColorForX_Y.CGColor; + textLayer.alignmentMode = kCAAlignmentCenter; + + if (_leftBarValues.count > i && _rightBarValues.count > i) { + textLayer.position = CGPointMake(self.chartOrigin.x + (_barWidth * 2 + _barSpacing) * (i + 1) - _barWidth, self.chartOrigin.y + size.height/2.0f + 5); + } + else { + textLayer.position = CGPointMake(self.chartOrigin.x + (i + MIN(_leftBarValues.count, _rightBarValues.count)) * _barWidth + (_barSpacing) * (i + 1) + _barWidth/2.0, self.chartOrigin.y + size.height/2.0f + 5); + } + + if (self.rotateForXAxisText) { + CGFloat r = -45.0 / 180.0 * M_PI; + textLayer.transform = CATransform3DMakeRotation(r, 0.0, 0.0, 1.0); + textLayer.position = CGPointMake(textLayer.position.x - size.width/2.0 * cos(r), textLayer.position.y - size.width/2.0 * sin(r)); + } + else { + textLayer.transform = CATransform3DIdentity; + } + + [self.scrollView.layer addSublayer:textLayer]; + [self.layerArr addObject:textLayer]; + } +} + +- (void)drawDualYTexts:(CGPoint)p { + + for (NSInteger i = 1; i <_levelLineNum + 1; i++) { + CGFloat h = i * lPerH * _yLeftRadix; + + if (self.needLeftYTexts) { + CATextLayer *layer = [self createTextLayer:@(i * _yLeftRadix).stringValue font:_yleftTextFont color:_drawTextColorForX_Y]; + layer.position = CGPointMake(p.x - layer.frame.size.width/2.0 - _leftYTextsMargin, p.y - h); + [self.layer addSublayer:layer]; + [self.layerArr addObject:layer]; + } + + if (self.needRightYTexts) { + CATextLayer *layer = [self createTextLayer:@(i * _yRightRadix).stringValue font:_yRightTextFont color:_drawTextColorForX_Y]; + layer.position = CGPointMake(self.frame.size.width - p.x + layer.frame.size.width/2.0 + _leftYTextsMargin, p.y - h); + [self.layer addSublayer:layer]; + [self.layerArr addObject:layer]; + } + } + + if (_needLeftYTexts) { + CATextLayer *layer = [self createTextLayer:_yLeftDetailText font:_yDetailTextFont color:_drawTextColorForX_Y]; + layer.position = CGPointMake(p.x - layer.frame.size.height/2.0 - 20, p.y - _maxH/2.0f); + layer.transform = CATransform3DMakeRotation(-M_PI_2, 0.0, 0.0, 1.0); + + [self.layer addSublayer:layer]; + [self.layerArr addObject:layer]; + } + if (self.needRightYTexts) { + CATextLayer *layer = [self createTextLayer:_yRightDetailText font:_yDetailTextFont color:_drawTextColorForX_Y]; + layer.position = CGPointMake(self.frame.size.width - p.x + layer.frame.size.height/2.0 + _leftYTextsMargin + 20, p.y - _maxH/2.0f); + layer.transform = CATransform3DMakeRotation(-M_PI_2, 0.0, 0.0, 1.0); + + [self.layer addSublayer:layer]; + [self.layerArr addObject:layer]; + } +} + + +- (void)drawBars { + + NSArray *moreArr = self.leftBarValues.count >= self.rightBarValues.count ? self.leftBarValues : self.rightBarValues; + + for (NSUInteger i = 0; i < self.leftBarValues.count; i ++) { + UIView *view = [UIView new]; + view.backgroundColor = self.leftBarBGColors.count > i ? self.leftBarBGColors[i] : self.leftBarBGColors.firstObject; + [self.scrollView addSubview:view]; + [self.leftBarViews addObject:view]; + } + + for (NSUInteger i = 0; i < self.rightBarValues.count; i ++) { + UIView *view = [UIView new]; + view.backgroundColor = self.rightBarBGColors.count > i ? self.rightBarBGColors[i] : self.rightBarBGColors.firstObject; + [self.scrollView addSubview:view]; + [self.rightBarViews addObject:view]; + } + + for (NSUInteger i = 0; i < moreArr.count; i ++) { + UIView *left = self.leftBarViews.count > i ? self.leftBarViews[i] : nil; + UIView *right = self.rightBarViews.count > i ? self.rightBarViews[i] : nil; + + if (!left) { + right.frame = CGRectMake(self.chartOrigin.x + (self.leftBarViews.count + i) * _barWidth + (i + 1) * _barSpacing, self.chartOrigin.y, _barWidth, 0); + } + if (!right) { + left.frame = CGRectMake(self.chartOrigin.x + (self.rightBarViews.count + i) * _barWidth + (i + 1) * _barSpacing, self.chartOrigin.y, _barWidth, 0); + } + else { + left.frame = CGRectMake(self.chartOrigin.x + i * (_barWidth*2 + _barSpacing) + _barSpacing, self.chartOrigin.y, _barWidth, 0); + right.frame = CGRectMake(self.chartOrigin.x + i * (_barWidth*2 + _barSpacing) + _barSpacing + _barWidth, self.chartOrigin.y, _barWidth, 0); + } + + [UIView animateWithDuration:1 animations:^{ + if (left) { + CGRect frame = left.frame; + frame.size.height = self.leftBarValues[i].floatValue * lPerH; + frame.origin.y = self.chartOrigin.y - frame.size.height - 1; + left.frame = frame; + } + if (right) { + CGRect frame = right.frame; + frame.size.height = self.rightBarValues[i].floatValue * rPerH; + frame.origin.y = self.chartOrigin.y - frame.size.height - 1; + right.frame = frame; + } + + } completion:^(BOOL finished) { + if (!finished) { + return; + } + + /* 动画结束后添加提示文字 */ + void (^addTextBlock)(UIView *, UIFont *, NSString *) = ^(UIView *view, UIFont *font, NSString *str) { + CGSize size = [self sizeOfStringWithMaxSize:CGSizeMake(MAXFLOAT, MAXFLOAT) textFont:font.pointSize aimString:str]; + + CATextLayer *textLayer = [CATextLayer layer]; + textLayer.bounds = CGRectMake(0, 0, size.width, size.height); + textLayer.position = CGPointMake(CGRectGetMidX(view.frame), CGRectGetMinY(view.frame) - size.height - 3); + textLayer.string = str; + textLayer.fontSize = font.pointSize; + textLayer.alignmentMode = kCAAlignmentCenter; + textLayer.contentsScale = [UIScreen mainScreen].scale; + textLayer.foregroundColor = self.drawTextColorForX_Y.CGColor; + + [self.layerArr addObject:textLayer]; + [self.scrollView.layer addSublayer:textLayer]; + }; + + if (self.leftBarValues.count > i) { + addTextBlock(left, self.barTextFont, self.leftBarValues[i].stringValue); + } + if (self.rightBarValues.count > i) { + addTextBlock(right, self.barTextFont, self.rightBarValues[i].stringValue); + } + + [self drawLineChart]; + }]; + } +} + +- (void)drawLineChart { + if (!self.showLineChart) { + return; + } + NSAssert(self.leftLineValues.count <= MAX(self.leftBarValues.count, self.rightBarValues.count), @""); + NSAssert(self.rightLineValues.count <= MAX(self.leftBarValues.count, self.rightBarValues.count), @""); + + void (^addLineBlock)(NSArray *, CGFloat, UIColor *, BOOL) = ^(NSArray *values, CGFloat h, UIColor *lineColor, BOOL isLeft) { + + UIBezierPath *path = [UIBezierPath bezierPath]; + for (NSUInteger i = 0; i < values.count; i ++) { + UIView *l = SAFE_ACCESS(self.leftBarViews, i); + UIView *r = SAFE_ACCESS(self.rightBarViews, i); + if (l && r) { + if (i == 0) { + [path moveToPoint:P_M(CGRectGetMidX((isLeft ? l : r).frame), self.chartOrigin.y - h * [values[i] floatValue])]; + } + else { + [path addLineToPoint:P_M(CGRectGetMidX((isLeft ? l : r).frame), self.chartOrigin.y - h * [values[i] floatValue])]; + } + } + else if (l || r) { + l = l ?: r; + if (i == 0) { + [path moveToPoint:P_M(CGRectGetMidX(l.frame), self.chartOrigin.y - h * [values[i] floatValue])]; + } + else { + [path addLineToPoint:P_M(CGRectGetMidX(l.frame), self.chartOrigin.y - h * [values[i] floatValue])]; + } + } + } + + CAShapeLayer *shaper = [CAShapeLayer layer]; + shaper.path = path.CGPath; + shaper.frame = self.scrollView.bounds; + shaper.lineWidth = 1.5; + shaper.fillColor = [UIColor clearColor].CGColor; + shaper.strokeColor = lineColor.CGColor; + + [self.layerArr addObject:shaper]; + + CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))]; + + basic.fromValue = @0; + basic.toValue = @1; + basic.duration = 1; + basic.delegate = self; + [shaper addAnimation:basic forKey:@"stokentoend"]; + [self.scrollView.layer addSublayer:shaper]; + }; + + addLineBlock(self.leftLineValues, lPerH, self.leftLinePathColor, true); + addLineBlock(self.rightLineValues, rPerH, self.rightLinePathColor, false); +} + +- (void)clear { + [self.leftBarViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [self.rightBarViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + [self.layerArr makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; +} + +- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { + if (flag) { + // TODO: add line point + } +} + +#pragma mark - Geters and Setters + +- (void)setContentInsets:(UIEdgeInsets)contentInsets { + [super setContentInsets:contentInsets]; + self.scrollView.frame = CGRectMake(contentInsets.left, + 0, + self.frame.size.width - contentInsets.left - contentInsets.right, + self.frame.size.height); +} + +- (void)setLeftBarValues:(NSArray *)leftBarValues { + NSAssert(_yLeftRadix > 0, @"You should set yLeftRadix first"); + + _leftBarValues = leftBarValues; + + CGFloat max = 0; + for (NSNumber *num in leftBarValues) { + max = MAX(num.floatValue, max); + } + CGFloat t = max/_yLeftRadix; + t = t - floor(t) > 0 ? t + 1 : t; + self.levelLineNum = MAX((NSUInteger)t, _levelLineNum); +} + +- (void)setRightBarValues:(NSArray *)rightBarValues { + NSAssert(_yRightRadix > 0, @"You should set yLeftRadix first"); + + _rightBarValues = rightBarValues; + + CGFloat max = 0; + for (NSNumber *num in rightBarValues) { + max = MAX(num.floatValue, max); + } + CGFloat t = max/_yRightRadix; + t = t - floor(t) > 0 ? t + 1 : t; + self.levelLineNum = MAX((NSUInteger)t, _levelLineNum); +} + +- (void)setLevelLineNum:(NSUInteger)levelLineNum { + _levelLineNum = MAX(_levelLineNum, levelLineNum); +} + +- (void)setChartBackgroundColor:(UIColor *)chartBackgroundColor { + _chartBackgroundColor = chartBackgroundColor; +} + +- (UIScrollView *)scrollView { + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] init]; + _scrollView.frame = self.bounds; + _scrollView.showsHorizontalScrollIndicator = false; + _scrollView.backgroundColor = [UIColor clearColor]; + _scrollView.clipsToBounds = true; + } + return _scrollView; +} + +- (NSMutableArray *)layerArr { + if (!_layerArr) { + _layerArr = [[NSMutableArray alloc] init]; + } + return _layerArr; +} + +- (NSMutableArray *)rightBarViews { + if (!_rightBarViews) { + _rightBarViews = [[NSMutableArray alloc] init]; + } + return _rightBarViews; +} + +- (NSMutableArray *)leftBarViews { + if (!_leftBarViews) { + _leftBarViews = [[NSMutableArray alloc] init]; + } + return _leftBarViews; +} + +- (CATextLayer *)createTextLayer:(NSString *)text + font:(UIFont *)font + color:(UIColor *)textColor { + CATextLayer *textLayer = [CATextLayer layer]; + textLayer.contentsScale = [UIScreen mainScreen].scale; + CGSize size = [self sizeOfString:text withFont:font]; + textLayer.bounds = CGRectMake(0, 0, size.width, size.height); + CGFontRef fontRef = CGFontCreateWithFontName((__bridge CFStringRef)font.fontName); + textLayer.font = fontRef; + textLayer.fontSize = font.pointSize; + CGFontRelease(fontRef); + + textLayer.string = text; + textLayer.foregroundColor = textColor.CGColor; + return textLayer; +} + +@end diff --git a/JHChartDemo/JHChart/JHLineChart.m b/JHChartDemo/JHChart/JHLineChart.m index 5d9a610..754b7c6 100644 --- a/JHChartDemo/JHChart/JHLineChart.m +++ b/JHChartDemo/JHChart/JHLineChart.m @@ -40,7 +40,7 @@ -(instancetype)initWithFrame:(CGRect)frame andLineChartType:(JHLineChartType)lin self.backgroundColor = [UIColor whiteColor]; _lineType = lineChartType; _lineWidth = 0.5; - + _yLineDataArr = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7"]; _xLineDataArr = @[@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7"]; _showXDescVertical = NO; @@ -90,7 +90,7 @@ -(void)clear{ */ - (void)configPerXAndPerY{ - + switch (_lineChartQuadrantType) { case JHLineChartQuadrantTypeFirstQuardrant: { @@ -115,8 +115,8 @@ - (void)configPerXAndPerY{ break; case JHLineChartQuadrantTypeAllQuardrant: { - _perXLen = (_xLength/2-kXandYSpaceForSuperView)/([_xLineDataArr[0] count]); - _perYlen = (_yLength/2-kXandYSpaceForSuperView)/[_yLineDataArr[0] count]; + _perXLen = (_xLength/2-kXandYSpaceForSuperView)/([_xLineDataArr[0] count]); + _perYlen = (_yLength/2-kXandYSpaceForSuperView)/[_yLineDataArr[0] count]; } break; @@ -167,7 +167,7 @@ -(void)setValueArr:(NSArray *)valueArr{ * 更新Y轴的刻度大小 */ - (void)updateYScale{ - switch (_lineChartQuadrantType) { + switch (_lineChartQuadrantType) { case JHLineChartQuadrantTypeFirstAndFouthQuardrant:{ NSInteger max = 0; @@ -186,47 +186,47 @@ - (void)updateYScale{ } - min = labs(min); - max = (min5) { - for (NSInteger i = 0; i<5; i++) { + if (max<=10&&max>5) { + for (NSInteger i = 0; i<5; i++) { - [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*2]]; - [minArr addObject:[NSString stringWithFormat:@"-%ld",(i+1)*2]]; - } + [arr addObject:[NSString stringWithFormat:@"%ld",(i+1)*2]]; + [minArr addObject:[NSString stringWithFormat:@"-%ld",(i+1)*2]]; + } + + }else if(max>10&&max<=100){ + + + for (NSInteger i = 0; i10&&max<=100){ - - - for (NSInteger i = 0; i0) { CGFloat xPace = (_xLength-kXandYSpaceForSuperView)/(_xLineDataArr.count-1); @@ -454,15 +454,15 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ label.numberOfLines = 0; label.transform = CGAffineTransformRotate(label.transform, _xDescriptionAngle); [self addSubview:label]; - + }else{ CGFloat len = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.xDescTextFontSize aimString:_xLineDataArr[i]].width; [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x, p.y-3) andIsDottedLine:NO andColor:self.xAndYLineColor]; - + [self drawText:[NSString stringWithFormat:@"%@",_xLineDataArr[i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:self.xDescTextFontSize]; } } - + } @@ -493,10 +493,10 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ p = P_M(self.chartOrigin.x + _xLength, p.y); len = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:rightArray[i]].width; hei = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:rightArray[i]].height; - + [self drawText:[NSString stringWithFormat:@"%@",rightArray[i]] andContext:context atPoint:P_M(p.x + 3, p.y-hei / 2) WithColor:_xAndYNumberColor andFontSize:self.yDescTextFontSize]; - + } } @@ -527,9 +527,9 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ [self drawLineWithContext:context andStarPoint:P_M(self.contentInsets.left, self.chartOrigin.y) andEndPoint:P_M(self.contentInsets.left+_xLength, self.chartOrigin.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; if (_showYLine) { - [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.chartOrigin.x,self.chartOrigin.y-_yLength) andIsDottedLine:NO andColor:self.xAndYLineColor]; + [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.chartOrigin.x,self.chartOrigin.y-_yLength) andIsDottedLine:NO andColor:self.xAndYLineColor]; } - + if (_xLineDataArr.count == 2) { NSArray * rightArr = _xLineDataArr[1]; NSArray * leftArr = _xLineDataArr[0]; @@ -548,9 +548,9 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ [self addSubview:label]; }else{ CGFloat len = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.xDescTextFontSize aimString:rightArr[i]].width; - + [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x, p.y-3) andIsDottedLine:NO andColor:self.xAndYLineColor]; - + [self drawText:[NSString stringWithFormat:@"%@",rightArr[i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:self.xDescTextFontSize]; } } @@ -580,13 +580,13 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ CGFloat len = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:_yLineDataArr[i]].width; CGFloat hei = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:_yLineDataArr[i]].height; if (_showYLevelLine) { - [self drawLineWithContext:context andStarPoint:P_M(self.contentInsets.left, p.y) andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:YES andColor:self.xAndYLineColor]; + [self drawLineWithContext:context andStarPoint:P_M(self.contentInsets.left, p.y) andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:YES andColor:self.xAndYLineColor]; }else [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; [self drawText:[NSString stringWithFormat:@"%@",_yLineDataArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-hei / 2) WithColor:_xAndYNumberColor andFontSize:self.yDescTextFontSize]; } } - + }break; case JHLineChartQuadrantTypeFirstAndFouthQuardrant:{ [self drawLineWithContext:context andStarPoint:self.chartOrigin andEndPoint:P_M(self.contentInsets.left+_xLength, self.chartOrigin.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; @@ -611,11 +611,11 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ }else{ CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.xDescTextFontSize aimString:_xLineDataArr[i]].width; [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x , p.y-3) andIsDottedLine:NO andColor:self.xAndYLineColor]; - + if (i==0) { len = -2; } - + [self drawText:[NSString stringWithFormat:@"%@",_xLineDataArr[i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:self.xDescTextFontSize]; } } @@ -632,7 +632,7 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:topArr[i]].width; CGFloat hei = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:topArr[i]].height; if (_showYLevelLine) { - [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:YES andColor:self.xAndYLineColor]; + [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:YES andColor:self.xAndYLineColor]; }else [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; [self drawText:[NSString stringWithFormat:@"%@",topArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-hei / 2) WithColor:_xAndYNumberColor andFontSize:self.yDescTextFontSize]; @@ -644,11 +644,11 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ CGPoint p = P_M(self.chartOrigin.x, self.chartOrigin.y + (i+1)*yPace); CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:bottomArr[i]].width; CGFloat hei = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:bottomArr[i]].height; - + if (_showYLevelLine) { - [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:YES andColor:self.xAndYLineColor]; + [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(self.contentInsets.left+_xLength, p.y) andIsDottedLine:YES andColor:self.xAndYLineColor]; }else{ - + [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; } [self drawText:[NSString stringWithFormat:@"%@",bottomArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-hei / 2) WithColor:_xAndYNumberColor andFontSize:self.yDescTextFontSize]; @@ -656,7 +656,7 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ } - + }break; case JHLineChartQuadrantTypeAllQuardrant:{ [self drawLineWithContext:context andStarPoint:P_M(self.chartOrigin.x-_xLength/2, self.chartOrigin.y) andEndPoint:P_M(self.chartOrigin.x+_xLength/2, self.chartOrigin.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; @@ -686,7 +686,7 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ }else{ CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.xDescTextFontSize aimString:rightArr[i]].width; [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x, p.y-3) andIsDottedLine:NO andColor:self.xAndYLineColor]; - + [self drawText:[NSString stringWithFormat:@"%@",rightArr[i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:self.xDescTextFontSize]; } } @@ -703,13 +703,13 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ }else{ CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.xDescTextFontSize aimString:leftArr[i]].width; [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x, p.y-3) andIsDottedLine:NO andColor:self.xAndYLineColor]; - + [self drawText:[NSString stringWithFormat:@"%@",leftArr[leftArr.count-1-i]] andContext:context atPoint:P_M(p.x-len/2, p.y+2) WithColor:_xAndYNumberColor andFontSize:self.xDescTextFontSize]; } } } - + if (_yLineDataArr.count == 2) { @@ -721,7 +721,7 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ CGPoint p = P_M(self.chartOrigin.x, self.chartOrigin.y - (i+1)*yPace); CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:topArr[i]].width; CGFloat hei = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:topArr[i]].height; - + [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; [self drawText:[NSString stringWithFormat:@"%@",topArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-hei / 2) WithColor:_xAndYNumberColor andFontSize:self.yDescTextFontSize]; @@ -732,7 +732,7 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ CGPoint p = P_M(self.chartOrigin.x, self.chartOrigin.y + (i+1)*yPace); CGFloat len = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:bottomArr[i]].width; CGFloat hei = [self sizeOfStringWithMaxSize:CGSizeMake(CGFLOAT_MAX, 30) textFont:self.yDescTextFontSize aimString:bottomArr[i]].height; - + [self drawLineWithContext:context andStarPoint:p andEndPoint:P_M(p.x+3, p.y) andIsDottedLine:NO andColor:self.xAndYLineColor]; [self drawText:[NSString stringWithFormat:@"%@",bottomArr[i]] andContext:context atPoint:P_M(p.x-len-3, p.y-hei / 2) WithColor:_xAndYNumberColor andFontSize:self.yDescTextFontSize]; } @@ -746,7 +746,7 @@ - (void)drawXAndYLineWithContext:(CGContextRef)context{ break; } - + } /** @@ -836,27 +836,27 @@ - (void)configValueDataArray{ for (NSArray *valueArr in _valueArr) { NSMutableArray *dataMArr = [NSMutableArray array]; - - - CGPoint p ; - for (NSInteger i = 0; i<[_xLineDataArr[0] count]; i++) { - p = P_M(self.contentInsets.left + kXandYSpaceForSuperView+i*_perXLen, self.contentInsets.top + _yLength - [valueArr[i] floatValue]*_perValue); - [dataMArr addObject:[NSValue valueWithCGPoint:p]]; - } - - for (NSInteger i = 0; i<[_xLineDataArr[1] count]; i++) { - p = P_M(self.chartOrigin.x+i*_perXLen, self.contentInsets.top + _yLength - [valueArr[i+[_xLineDataArr[0] count]] floatValue]*_perValue); - [dataMArr addObject:[NSValue valueWithCGPoint:p]]; - - } - + + + CGPoint p ; + for (NSInteger i = 0; i<[_xLineDataArr[0] count]; i++) { + p = P_M(self.contentInsets.left + kXandYSpaceForSuperView+i*_perXLen, self.contentInsets.top + _yLength - [valueArr[i] floatValue]*_perValue); + [dataMArr addObject:[NSValue valueWithCGPoint:p]]; + } + + for (NSInteger i = 0; i<[_xLineDataArr[1] count]; i++) { + p = P_M(self.chartOrigin.x+i*_perXLen, self.contentInsets.top + _yLength - [valueArr[i+[_xLineDataArr[0] count]] floatValue]*_perValue); + [dataMArr addObject:[NSValue valueWithCGPoint:p]]; - + } + + + [_drawDataArr addObject:[dataMArr copy]]; } - - + + }break; @@ -882,135 +882,105 @@ - (void)configValueDataArray{ _perValue = _perYlen/[[_yLineDataArr[0] firstObject] floatValue]; for (NSArray *valueArr in _valueArr) { NSMutableArray *dataMArr = [NSMutableArray array]; - - - CGPoint p ; - for (NSInteger i = 0; i<[_xLineDataArr[0] count]; i++) { - p = P_M(self.contentInsets.left + kXandYSpaceForSuperView+i*_perXLen, self.chartOrigin.y-[valueArr[i] floatValue]*_perValue); - [dataMArr addObject:[NSValue valueWithCGPoint:p]]; - } - - for (NSInteger i = 0; i<[_xLineDataArr[1] count]; i++) { - p = P_M(self.chartOrigin.x+i*_perXLen, self.chartOrigin.y-[valueArr[i+[_xLineDataArr[0] count]] floatValue]*_perValue); - [dataMArr addObject:[NSValue valueWithCGPoint:p]]; - - } - + + + CGPoint p ; + for (NSInteger i = 0; i<[_xLineDataArr[0] count]; i++) { + p = P_M(self.contentInsets.left + kXandYSpaceForSuperView+i*_perXLen, self.chartOrigin.y-[valueArr[i] floatValue]*_perValue); + [dataMArr addObject:[NSValue valueWithCGPoint:p]]; + } + + for (NSInteger i = 0; i<[_xLineDataArr[1] count]; i++) { + p = P_M(self.chartOrigin.x+i*_perXLen, self.chartOrigin.y-[valueArr[i+[_xLineDataArr[0] count]] floatValue]*_perValue); + [dataMArr addObject:[NSValue valueWithCGPoint:p]]; - + } + + + [_drawDataArr addObject:[dataMArr copy]]; } - + }break; default: break; } - - - + + + } //执行动画 - (void)drawAnimation{ - [_shapeLayer removeFromSuperlayer]; _shapeLayer = [CAShapeLayer layer]; if (_drawDataArr.count==0) { return; } - - - + //第一、UIBezierPath绘制线段 [self configPerXAndPerY]; - for (NSInteger i = 0;i<_drawDataArr.count;i++) { - NSArray *dataArr = _drawDataArr[i]; - [self drawPathWithDataArr:dataArr andIndex:i]; - } - - - } - (CGPoint)centerOfFirstPoint:(CGPoint)p1 andSecondPoint:(CGPoint)p2{ - - return P_M((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0); } - - - (void)drawPathWithDataArr:(NSArray *)dataArr andIndex:(NSInteger )colorIndex{ UIBezierPath *firstPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 0, 0)]; - UIBezierPath *secondPath = [UIBezierPath bezierPath]; for (NSInteger i = 0; i 0) { [shapeLayer addAnimation:ani forKey:NSStringFromSelector(@selector(strokeEnd))]; - }else{ + } + else { ani = nil; } @@ -1042,22 +1009,19 @@ - (void)drawPathWithDataArr:(NSArray *)dataArr andIndex:(NSInteger )colorIndex{ weakSelf(weakSelf) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ani.duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - CAShapeLayer *shaperLay = [CAShapeLayer layer]; shaperLay.frame = weakself.bounds; shaperLay.path = secondPath.CGPath; - if (weakself.contentFillColorArr.count == weakself.drawDataArr.count) { - + if (weakself.contentFillColorArr.count >= weakself.drawDataArr.count) { shaperLay.fillColor = [weakself.contentFillColorArr[colorIndex] CGColor]; - }else{ + } + else { shaperLay.fillColor = [UIColor clearColor].CGColor; } [weakself.layer addSublayer:shaperLay]; [_layerArr addObject:shaperLay]; }); - - } @@ -1088,13 +1052,13 @@ - (void)drawPositionLineWithContext:(CGContextRef)context{ positionLineColor = _positionLineColorArr[m]; }else positionLineColor = [UIColor orangeColor]; - + if (_showValueLeadingLine) { [self drawLineWithContext:context andStarPoint:P_M(self.chartOrigin.x, p.y) andEndPoint:p andIsDottedLine:YES andColor:positionLineColor]; [self drawLineWithContext:context andStarPoint:P_M(p.x, self.chartOrigin.y) andEndPoint:p andIsDottedLine:YES andColor:positionLineColor]; } - + if (!_showPointDescription) { continue; } @@ -1102,7 +1066,7 @@ - (void)drawPositionLineWithContext:(CGContextRef)context{ UIColor *pointNumberColor = (_pointNumberColorArr.count == _valueArr.count?(_pointNumberColorArr[m]):([UIColor orangeColor])); switch (_lineChartQuadrantType) { - + case JHLineChartQuadrantTypeFirstQuardrant: { @@ -1153,7 +1117,7 @@ - (void)drawPositionLineWithContext:(CGContextRef)context{ } } - _isEndAnimation = NO; + _isEndAnimation = NO; } @@ -1167,9 +1131,9 @@ -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ if (flag) { - + [self drawPoint]; - + } @@ -1230,3 +1194,4 @@ - (void)drawPoint{ @end + diff --git a/JHChartDemo/JHChart/JHRowChart.h b/JHChartDemo/JHChart/JHRowChart.h new file mode 100644 index 0000000..feec321 --- /dev/null +++ b/JHChartDemo/JHChart/JHRowChart.h @@ -0,0 +1,100 @@ +// +// JHRowChart.h +// JHChartDemo +// +// Created by Mayqiyue on 30/11/2017. +// Copyright © 2017 JH. All rights reserved. +// + +#import "JHChart.h" + +@class JHRowItem,JHIndexPath,JHRowChart; +@protocol JHRowChartDelegate + +@optional +- (void)rowChart:(JHRowChart *)chart rowItem:(UIView *)item didClickAtIndexRow:(NSIndexPath *)indexPath; //1.2.0 +- (void)rowChart:(JHRowChart *)chart rowItem:(JHRowItem *)item didClickAtIndexPath:(JHIndexPath *)indexPath;//1.2.1 +@end + +@interface JHRowChart : JHChart + +/** + * Each histogram of the background color, if you do not set the default value for green. Setup must ensure that the number and type of the data source array are the same, otherwise the default is not set. + */ +@property (nonatomic, strong) NSArray *rowBGcolorsArr; + +@property (nonatomic , assign)id delegate; + +/** + * Data source array + */ +@property (nonatomic, strong) NSArray *valueArr; + +/** + * X axis classification of each icon + */ +@property (nonatomic, strong) NSArray *xShowInfoText; + +/** + * The background color of the content view + */ +@property (nonatomic, strong) UIColor *bgVewBackgoundColor; + +/** + * Row spacing, non continuous, default is 5 + */ +@property (nonatomic, assign) CGFloat rowSpacing; + +/** + * The height of the Row, the default is 40 + */ +@property (nonatomic, assign) CGFloat rowHeight; + +/** + * Whether the need for Y, X axis, the default YES + */ +@property (nonatomic, assign) BOOL needXandYLine; + +/** + * Y, X axis line color + */ +@property (nonatomic, strong) UIColor *colorForXYLine; + +/** + * X, Y axis text description color + */ +@property (nonatomic, strong) UIColor *drawTextColorForX_Y; + +/** + * Dotted line guide color + */ +@property (nonatomic, strong) UIColor *dashColor; + +/** + * Whether this chart show Y line or not .Default is Yes + */ +@property (nonatomic,assign) BOOL isShowYLine; + +/** + * Whether this chart show line or not.Default is NO; + */ +@property (nonatomic,assign) BOOL isShowLineChart; + +/** + * If isShowLineChart proprety is YES,we need this value array to draw chart + */ +@property (nonatomic,strong)NSArray *lineValueArray; + +/** + * If isShowLineChart proprety is Yes,we will draw path of this linechart with this color + * Default is blue + */ +@property (nonatomic,strong)UIColor *lineChartPathColor; + +/** + * if isShowLineChart proprety is Yes,we will draw this linechart valuepoint with this color + * Default is yellow + */ +@property (nonatomic,strong)UIColor *lineChartValuePointColor; + +@end diff --git a/JHChartDemo/JHChart/JHRowChart.m b/JHChartDemo/JHChart/JHRowChart.m new file mode 100644 index 0000000..1026719 --- /dev/null +++ b/JHChartDemo/JHChart/JHRowChart.m @@ -0,0 +1,403 @@ +// +// JHRowChart.m +// JHChartDemo +// +// Created by Mayqiyue on 30/11/2017. +// Copyright © 2017 JH. All rights reserved. +// + +#import "JHRowChart.h" +#import +#import "JHRowItem.h" + +@interface JHRowChart () + +//背景图 +@property (nonatomic,strong)UIScrollView *scrollView; + +//峰值 +@property (nonatomic,assign) CGFloat maxHeight; + +//横向最大值 +@property (nonatomic,assign) CGFloat maxWidth; + +//Y轴辅助线数据源 +@property (nonatomic,strong)NSMutableArray * yLineDataArr; + +//所有的图层数组 +@property (nonatomic,strong)NSMutableArray * layerArr; + +//所有的柱状图数组 +@property (nonatomic,strong)NSMutableArray * showViewArr; + +@property (nonatomic,assign) CGFloat perWidth; + +@property (nonatomic , strong) NSMutableArray * drawLineValue; + +@end + +@implementation JHRowChart + +-(NSMutableArray *)drawLineValue{ + if (!_drawLineValue) { + _drawLineValue = [NSMutableArray array]; + } + return _drawLineValue; +} + +-(NSMutableArray *)showViewArr{ + if (!_showViewArr) { + _showViewArr = [NSMutableArray array]; + } + + return _showViewArr; +} + +-(NSMutableArray *)layerArr{ + if (!_layerArr) { + _layerArr = [NSMutableArray array]; + } + return _layerArr; +} + +-(UIScrollView *)scrollView{ + if (!_scrollView) { + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; + _scrollView.showsHorizontalScrollIndicator = NO; + _scrollView.backgroundColor = [UIColor clearColor]; + _scrollView.clipsToBounds = YES; + [self addSubview:_scrollView]; + + } + return _scrollView; +} + +-(void)setBgVewBackgoundColor:(UIColor *)bgVewBackgoundColor{ + _bgVewBackgoundColor = bgVewBackgoundColor; + self.backgroundColor = _bgVewBackgoundColor; +} + +-(NSMutableArray *)yLineDataArr{ + if (!_yLineDataArr) { + _yLineDataArr = [NSMutableArray array]; + } + return _yLineDataArr; +} + +-(instancetype)initWithFrame:(CGRect)frame{ + if (self = [super initWithFrame:frame]) { + + _needXandYLine = YES; + _isShowYLine = YES; + _lineChartPathColor = [UIColor blueColor]; + _lineChartValuePointColor = [UIColor yellowColor]; + self.clipsToBounds = YES; + } + return self; +} + +-(void)setLineValueArray:(NSArray *)lineValueArray{ + if (!_isShowLineChart) { + return; + } + + _lineValueArray = lineValueArray; + CGFloat max = 0; + + for (id number in _lineValueArray) { + CGFloat currentNumber = [NSString stringWithFormat:@"%@",number].floatValue; + max = MAX(max, currentNumber); + } + + if (max<5.0) { + max = 5.0; + } else if(max<10){ + max = 10; + } + max += 4; + _maxWidth = MAX(_maxWidth, max); + + _perWidth = (CGRectGetWidth(self.frame) - 30 - self.chartOrigin.x - self.contentInsets.right)/_maxWidth; +} + +-(void)setValueArr:(NSArray *)valueArr{ + _valueArr = valueArr; + CGFloat max = 0; + + for (NSArray *arr in _valueArr) { + CGFloat total= 0; + for (NSNumber *number in arr) { + total += number.floatValue; + } + max = MAX(total, max); + } + + if (max<5.0) { + max = 5.0; + } + else if(max<10) { + max = 10; + } + max += 4; + + _maxWidth = MAX(_maxWidth, max); + _perWidth = (CGRectGetWidth(self.frame) - 30 - self.chartOrigin.x)/_maxWidth; +} + +-(void)showAnimation{ + + [self clear]; + + _rowHeight = (_rowHeight<=0?30:_rowHeight); + _rowSpacing = (_rowSpacing<=0?15:_rowSpacing); + _maxHeight = self.chartOrigin.y + _valueArr.count * _rowHeight + (_valueArr.count +1) * _rowSpacing + 10; + self.scrollView.frame = CGRectMake(0, self.chartOrigin.y, self.bounds.size.width, self.bounds.size.height - self.chartOrigin.y); + self.scrollView.contentSize = CGSizeMake(_maxWidth, _maxHeight); + self.scrollView.backgroundColor = _bgVewBackgoundColor; + + /* 绘制X、Y轴 可以在此改动X、Y轴字体大小 */ + if (_needXandYLine) { + + UIBezierPath *bezier = [UIBezierPath bezierPath]; + if (self.isShowYLine) { + [bezier moveToPoint:self.chartOrigin]; + [bezier addLineToPoint:P_M(G_W(self.frame), self.chartOrigin.y)]; + } + [bezier moveToPoint:self.chartOrigin]; + [bezier addLineToPoint:P_M(self.chartOrigin.x, _maxHeight)]; + + CAShapeLayer *layer = [CAShapeLayer layer]; + layer.path = bezier.CGPath; + layer.strokeColor = (_colorForXYLine==nil?([UIColor blackColor].CGColor):_colorForXYLine.CGColor); + + /* + CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + basic.duration = self.isShowYLine?1.5:0.75; + basic.fromValue = @(0); + basic.toValue = @(1); + basic.autoreverses = NO; + basic.fillMode = kCAFillModeForwards; + [layer addAnimation:basic forKey:nil]; + */ + + [self.layerArr addObject:layer]; + [self.layer addSublayer:layer]; + + /* 设置虚线辅助线 */ + UIBezierPath *second = [UIBezierPath bezierPath]; + for (NSInteger i = 0; i<5; i++) { + NSInteger pace = (_maxWidth) / 5; + CGFloat width = _perWidth * (i+1)*pace; + [second moveToPoint:P_M(self.chartOrigin.x + width, self.chartOrigin.y)]; + [second addLineToPoint:P_M(self.chartOrigin.x + width, _maxHeight)]; + + CATextLayer *textLayer = [CATextLayer layer]; + textLayer.contentsScale = [UIScreen mainScreen].scale; + NSString *text =[NSString stringWithFormat:@"%zd",(i + 1) * pace]; + CGSize size = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:text]; + textLayer.frame = CGRectMake(self.chartOrigin.x + width - size.width/2.0, 0, self.chartOrigin.y - size.height/2.0, size.height); + + UIFont *font = [UIFont systemFontOfSize:self.yDescTextFontSize]; + CFStringRef fontName = (__bridge CFStringRef)font.fontName; + CGFontRef fontRef = CGFontCreateWithFontName(fontName); + textLayer.font = fontRef; + textLayer.fontSize = font.pointSize; + CGFontRelease(fontRef); + + textLayer.string = text; + + textLayer.foregroundColor = (_drawTextColorForX_Y==nil?[UIColor blackColor].CGColor:_drawTextColorForX_Y.CGColor); + [self.layer addSublayer:textLayer]; + [self.layerArr addObject:textLayer]; + } + + CAShapeLayer *shapeLayer = [CAShapeLayer layer]; + + shapeLayer.path = second.CGPath; + + shapeLayer.strokeColor = (_dashColor==nil?([UIColor darkGrayColor].CGColor):_dashColor.CGColor); + + shapeLayer.lineWidth = 0.5; + + [shapeLayer setLineDashPattern:@[@(3),@(3)]]; + + CABasicAnimation *basic2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + basic2.duration = 1.5; + basic2.fromValue = @(0); + basic2.toValue = @(1); + basic2.autoreverses = NO; + basic2.fillMode = kCAFillModeForwards; + [shapeLayer addAnimation:basic2 forKey:nil]; + + [self.layer addSublayer:shapeLayer]; + [self.layerArr addObject:shapeLayer]; + } + + if (_xShowInfoText.count == _valueArr.count&&_xShowInfoText.count>0) { + for (NSInteger i = 0; i<_xShowInfoText.count; i++) { + CATextLayer *textLayer = [CATextLayer layer]; + textLayer.frame = [_xShowInfoText[i] boundingRectWithSize:CGSizeMake(MAXFLOAT, _rowHeight) + options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine + attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:self.xDescTextFontSize]} + context:nil]; + textLayer.position = P_M(self.chartOrigin.x - textLayer.frame.size.width/2.0 -5, self.chartOrigin.y + (i + 1) * (_rowHeight + _rowSpacing) - 0.5 * _rowHeight); + textLayer.string = _xShowInfoText[i]; + textLayer.contentsScale = [UIScreen mainScreen].scale; + UIFont *font = [UIFont systemFontOfSize:self.xDescTextFontSize]; + + textLayer.fontSize = font.pointSize; + textLayer.foregroundColor = _drawTextColorForX_Y.CGColor; + textLayer.alignmentMode = kCAAlignmentCenter; + + [_scrollView.layer addSublayer:textLayer]; + + [self.layerArr addObject:textLayer]; + } + } + + /* 动画展示 */ + for (NSInteger j = 0; j<_valueArr.count; j++) { + NSArray *arr = _valueArr[j]; + + NSArray *colors = nil; + CGFloat width = 0; + for (NSNumber *num in arr) { + width += num.floatValue; + } + if (j >= _rowBGcolorsArr.count) { + colors = _rowBGcolorsArr.lastObject; + } + else { + colors = _rowBGcolorsArr[j]; + } + + JHRowItem *itemsView = [[JHRowItem alloc] initWithFrame:CGRectMake(self.chartOrigin.x+1, (_rowSpacing + _rowHeight) *j, width * _perWidth, _rowHeight) + perWidth:_perWidth + valueArray:arr + colors:colors]; + itemsView.clipsToBounds = YES; + itemsView.delegate = self; + [self.showViewArr addObject:itemsView]; + itemsView.frame = CGRectMake(self.chartOrigin.x+1, _rowSpacing + (_rowSpacing + _rowHeight) *j, 0, _rowHeight); + + if (_isShowLineChart) { + NSString *value = [NSString stringWithFormat:@"%@",_lineValueArray[j]]; + NSValue *lineValue = [NSValue valueWithCGPoint:P_M(self.chartOrigin.x+_perWidth *value.floatValue, itemsView.center.y)]; + [self.drawLineValue addObject:lineValue]; + } + [self.scrollView addSubview:itemsView]; + + [UIView animateWithDuration:1 animations:^{ + itemsView.frame = CGRectMake(self.chartOrigin.x+1, _rowSpacing + (_rowSpacing + _rowHeight) * j, width * _perWidth, _rowHeight); + } completion:^(BOOL finished) { + /* 动画结束后添加提示文字 */ + if (finished) { + + CATextLayer *textLayer = [CATextLayer layer]; + + [self.layerArr addObject:textLayer]; + NSString *str = [NSString stringWithFormat:@"%0.2f", width]; + + CGSize size = [str boundingRectWithSize:CGSizeMake(MAXFLOAT, 20) + options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine + attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:9]} + context:nil].size; + textLayer.frame = CGRectMake(CGRectGetMaxX(itemsView.frame), CGRectGetMidY(itemsView.frame)-size.height/2.0f, size.width, size.height); + textLayer.string = str; + textLayer.fontSize = 9.0; + textLayer.alignmentMode = kCAAlignmentCenter; + textLayer.contentsScale = [UIScreen mainScreen].scale; + textLayer.foregroundColor = itemsView.backgroundColor.CGColor; + + [_scrollView.layer addSublayer:textLayer]; + + //添加折线图 + if (j==_valueArr.count - 1 && _isShowLineChart) { + UIBezierPath *path = [UIBezierPath bezierPath]; + + for (int32_t m=0;m<_lineValueArray.count;m++) { + NSLog(@"%@",_drawLineValue[m]); + if (m==0) { + [path moveToPoint:[_drawLineValue[m] CGPointValue]]; + + }else{ + [path addLineToPoint:[_drawLineValue[m] CGPointValue]]; + [path moveToPoint:[_drawLineValue[m] CGPointValue]]; + } + + } + + CAShapeLayer *shaper = [CAShapeLayer layer]; + shaper.path = path.CGPath; + shaper.frame = self.bounds; + shaper.lineWidth = 2.5; + shaper.strokeColor = _lineChartPathColor.CGColor; + + [self.layerArr addObject:shaper]; + + CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))]; + + basic.fromValue = @0; + basic.toValue = @1; + basic.duration = 1; + basic.delegate = self; + [shaper addAnimation:basic forKey:@"stokentoend"]; + [self.scrollView.layer addSublayer:shaper]; + } + } + }]; + } +} + +- (void)itemClick:(UITapGestureRecognizer *)sender{ +// if ([_delegate respondsToSelector:@selector(columnChart:columnItem:didClickAtIndexRow:)]) { +// [_delegate columnChart:self columnItem:sender.view didClickAtIndexRow:objc_getAssociatedObject(sender.view, "indexPath")]; +// } +} + +-(void)clear{ + for (CALayer *lay in self.layerArr) { + [lay removeAllAnimations]; + [lay removeFromSuperlayer]; + } + + for (UIView *subV in self.showViewArr) { + [subV removeFromSuperview]; + } +} + +-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ + + + if (flag) { + + if (_isShowLineChart) { + + + for (int32_t m=0;m<_lineValueArray.count;m++) { + NSLog(@"%@",_drawLineValue[m]); + + CAShapeLayer *roundLayer = [CAShapeLayer layer]; + UIBezierPath *roundPath = [UIBezierPath bezierPathWithArcCenter:[_drawLineValue[m] CGPointValue] radius:4.5 startAngle:M_PI_2 endAngle:M_PI_2 + M_PI * 2 clockwise:YES]; + roundLayer.path = roundPath.CGPath; + roundLayer.fillColor = _lineChartValuePointColor.CGColor; + [self.layerArr addObject:roundLayer]; + [self.scrollView.layer addSublayer:roundLayer]; + } + } + } +} + +-(void)rowItem:(JHRowItem *)item didClickAtIndexPath:(JHIndexPath *)indexPath { + if (_delegate) { + if ([_delegate respondsToSelector:@selector(rowChart:rowItem:didClickAtIndexRow:)]) { + [_delegate rowChart:self rowItem:item didClickAtIndexPath:indexPath]; + } + + if ([_delegate respondsToSelector:@selector(rowChart:rowItem:didClickAtIndexRow:)]) { + [_delegate rowChart:self rowItem:item didClickAtIndexRow:item.index]; + } + } +} +@end + diff --git a/JHChartDemo/JHChart/JHRowItem.h b/JHChartDemo/JHChart/JHRowItem.h new file mode 100644 index 0000000..020f81f --- /dev/null +++ b/JHChartDemo/JHChart/JHRowItem.h @@ -0,0 +1,30 @@ +// +// JHRowItem.h +// JHChartDemo +// +// Created by Mayqiyue on 30/11/2017. +// Copyright © 2017 JH. All rights reserved. +// + +#import +@class JHIndexPath; +@class JHRowItem; + +@protocol JHRowItemActionDelegate + +- (void)rowItem:(JHRowItem *)item didClickAtIndexPath:(JHIndexPath *)indexPath; + +@end + +@interface JHRowItem : UIView + +@property (nonatomic , strong)NSIndexPath * index;//为兼容老版本所留 +@property (nonatomic , strong)JHIndexPath * indexPath; +@property (nonatomic , assign)id delegate; + +- (instancetype)initWithFrame:(CGRect)frame + perWidth:(CGFloat)perWidth + valueArray:(id)values + colors:(id)colors; + +@end diff --git a/JHChartDemo/JHChart/JHRowItem.m b/JHChartDemo/JHChart/JHRowItem.m new file mode 100644 index 0000000..2f98bad --- /dev/null +++ b/JHChartDemo/JHChart/JHRowItem.m @@ -0,0 +1,70 @@ +// +// JHRowItem.m +// JHChartDemo +// +// Created by Mayqiyue on 30/11/2017. +// Copyright © 2017 JH. All rights reserved. +// + +#import "JHRowItem.h" +#import "JHIndexPath.h" + +@interface JHRowItem() +@property(nonatomic,strong)NSArray *valueArray; + +@property (nonatomic , strong)id colors; + +@property (nonatomic , assign)CGFloat perWidth; + +@end + +@implementation JHRowItem + +-(instancetype)initWithFrame:(CGRect)frame perWidth:(CGFloat)perWidth valueArray:(id)values colors:(id)colors { + if (self = [super initWithFrame:frame]) { + if ([values isKindOfClass:[NSArray class]]) { + _valueArray = values; + _colors = colors; + _perWidth = perWidth; + [self configBaseView]; + }else{ + self.backgroundColor = colors; + self.tag = 0 ; + [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(itemsClick:)]]; + + } + } + return self; +} + + +- (void)configBaseView { + UIView *last = nil; + for (int i = 0; i < _valueArray.count; i++) { + UIView *item = [[UIView alloc] init]; + CGFloat width = [NSString stringWithFormat:@"%@",_valueArray[i]].floatValue * _perWidth; + item.translatesAutoresizingMaskIntoConstraints = NO; + [item addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(itemsClick:)]]; + item.tag = i; + if (!last) { + item.frame = CGRectMake(0, 0, width, CGRectGetHeight(self.frame)); + } + else { + item.frame = CGRectMake(CGRectGetMaxX(last.frame), 0, width, CGRectGetHeight(self.frame)); + } + last = item; + item.backgroundColor = _colors[i]; + [self addSubview:item]; + } +} + +- (void)itemsClick:(UITapGestureRecognizer *)sender{ + if (_delegate) { + if ([_delegate respondsToSelector:@selector(rowItem:didClickAtIndexPath:)]) { + JHIndexPath *index = [JHIndexPath indexPathWithSection:self.indexPath.section row:self.indexPath.row index:sender.view.tag]; + [_delegate rowItem:self didClickAtIndexPath:index]; + } + } +} +@end + diff --git a/JHChartDemo/JHShowController.m b/JHChartDemo/JHShowController.m index 41eae8e..006e60a 100644 --- a/JHChartDemo/JHShowController.m +++ b/JHChartDemo/JHShowController.m @@ -68,12 +68,17 @@ - (void)viewDidLoad { { [self showScatterChart]; }break; + case 10: + { + [self showRowChart]; + }break; + case 11: { + [self showDualBarChart]; + } + break; default: break; } - - - } @@ -116,9 +121,9 @@ - (void)showFirstQuardrant{ /* Dotted line color of the coordinate point */ lineChart.positionLineColorArr = @[[UIColor blueColor],[UIColor greenColor]]; /* Set whether to fill the content, the default is False */ - lineChart.contentFill = NO; + lineChart.contentFill = YES; /* Set whether the curve path */ - lineChart.pathCurve = YES; + lineChart.pathCurve = NO; /* Set fill color array */ lineChart.contentFillColorArr = @[[UIColor colorWithRed:0 green:1 blue:0 alpha:0.468],[UIColor colorWithRed:1 green:0 blue:0 alpha:0.468]]; [self.view addSubview:lineChart]; @@ -279,19 +284,19 @@ - (void)showColumnView{ JHColumnChart *column = [[JHColumnChart alloc] initWithFrame:CGRectMake(0, 64, k_MainBoundsWidth, 320)]; /* Create an array of data sources, each array is a module data. For example, the first array can represent the average score of a class of different subjects, the next array represents the average score of different subjects in another class */ column.valueArr = @[ - @[@[@15,@10]],//第一组元素 如果有多个元素,往该组添加,每一组只有一个元素,表示是单列柱状图| | | | | - @[@[@15,@20]],//第二组元素 - @[@[@10,@5]],//第三组元素 - @[@[@21,@12]], - @[@19], - @[@12], - @[@15], - @[@9], - @[@8], - @[@6], - @[@9], - @[@18], - @[@11], + @[@[@15,@10], @[@5]],//第一组元素 如果有多个元素,往该组添加,每一组只有一个元素,表示是单列柱状图| | | | | + @[@[@15,@20], @[@5]],//第二组元素 + @[@[@10,@5], @[@5]],//第三组元素 + @[@[@21,@12], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], + @[@[@19], @[@5]], ]; /* This point represents the distance from the lower left corner of the origin. */ column.originSize = CGPointMake(30, 20); @@ -310,7 +315,7 @@ - (void)showColumnView{ /* X, Y axis line color */ column.colorForXYLine = [UIColor darkGrayColor]; /* Each module of the color array, such as the A class of the language performance of the color is red, the color of the math achievement is green */ - column.columnBGcolorsArr = @[@[[UIColor redColor],[UIColor greenColor]],@[[UIColor redColor],[UIColor greenColor]],@[[UIColor redColor],[UIColor greenColor]]];//如果为复合型柱状图 即每个柱状图分段 需要传入如上颜色数组 达到同时指定复合型柱状图分段颜色的效果 + column.columnBGcolorsArr = @[@[[UIColor redColor],[UIColor greenColor],[UIColor redColor], [UIColor blueColor]],@[[UIColor redColor],[UIColor blueColor]],@[[UIColor redColor],[UIColor greenColor]]];//如果为复合型柱状图 即每个柱状图分段 需要传入如上颜色数组 达到同时指定复合型柱状图分段颜色的效果 /* Module prompt */ column.xShowInfoText = @[@"A班级",@"B班级",@"C班级",@"D班级",@"E班级",@"F班级",@"G班级",@"H班级",@"i班级",@"J班级",@"L班级",@"M班级",@"N班级"]; column.isShowLineChart = YES; @@ -514,6 +519,93 @@ - (void)showScatterChart{ [self.view addSubview:scatterChart]; } +- (void)showRowChart { + JHRowChart *column = [[JHRowChart alloc] initWithFrame:CGRectMake(0, 64, k_MainBoundsWidth, 320)]; + /* Create an array of data sources, each array is a module data. For example, the first array can represent the average score of a class of different subjects, the next array represents the average score of different subjects in another class */ + column.valueArr = @[ + @[@15,@10,@8,@7],//第一组元素 如果有多个元素,往该组添加,每一组只有一个元素,表示是单列柱状图| | | | | + @[@15,@20],//第二组元素 + @[@10,@5],//第三组元素 + @[@21,@12], + @[@19], + @[@12], + @[@15], + @[@9], + @[@8], + @[@6], + @[@9], + @[@18], + @[@11], + ]; + column.rowBGcolorsArr=@[@[[UIColor redColor],[UIColor greenColor],[UIColor redColor], [UIColor blueColor]], + @[[UIColor redColor],[UIColor blueColor]], + @[[UIColor redColor],[UIColor greenColor]]];//如果为复合型柱状图 即每个柱状图分段 需要传入如上颜色数组 达到同时指定复合型柱状图分段颜色的效果 + /* This point represents the distance from the lower left corner of the origin. */ + column.chartOrigin = CGPointMake(30, 20); + /* The first column of the distance from the starting point */ + column.backgroundColor = [UIColor grayColor]; + column.rowSpacing = 10; + column.isShowYLine = YES; + column.contentInsets = UIEdgeInsetsMake(5, 0, 0, 0); + /* Column width */ + column.rowHeight = 30; + /* Column backgroundColor */ + column.bgVewBackgoundColor = [UIColor grayColor]; + /* X, Y axis font color */ + column.drawTextColorForX_Y = [UIColor blackColor]; + /* X, Y axis line color */ + column.colorForXYLine = [UIColor darkGrayColor]; + /* Each module of the color array, such as the A class of the language performance of the color is red, the color of the math achievement is green */ + /* Module prompt */ + column.xShowInfoText = @[@"A班级",@"B班级",@"C班级",@"D班级",@"E班级",@"F班级",@"G班级",@"H班级",@"i班级",@"J班级",@"L班级",@"M班级",@"N班级"]; + column.isShowLineChart = YES; + column.lineValueArray = @[ + @6, + @12, + @10, + @1, + @9, + @5, + @9, + @9, + @5, + @6, + @4, + @8, + @11 + ]; + + column.delegate = self; + /* Start animation */ + [column showAnimation]; + [self.view addSubview:column]; +} + +- (void)showDualBarChart { + JHDualBarChart *chart = [[JHDualBarChart alloc] initWithFrame:CGRectMake(0, 64, k_MainBoundsWidth, 320)]; + chart.yLeftRadix = 25; + chart.yRightRadix = 50; + chart.levelLineNum = 6; + chart.leftBarValues = @[@(20),@(30),@(89),@(45),@(57)]; + chart.rightBarValues = @[@(100),@(200),@(287),@(34),@(30)]; + chart.leftLineValues = @[@(20),@(30),@(89),@(45),@(57)]; + chart.rightBarValues = @[@(100),@(200),@(287),@(34),@(30)]; + chart.rightLineValues = @[@(100),@(200),@(287),@(34),@(30)]; + chart.xTexts = @[@"first",@"second",@"third", @"fourth", @"fiveth"]; + chart.leftBarBGColors = @[[UIColor colorWithRed:23/255.0 green:93.0/255.0 blue:180.0/255.0 alpha:1]]; + chart.rightBarBGColors = @[[UIColor colorWithRed:191/255.0 green:215.0/255.0 blue:242.0/255.0 alpha:1]]; + chart.leftLinePathColor = [UIColor redColor]; + chart.rightLinePathColor = [UIColor yellowColor]; + chart.backgroundColor = [UIColor grayColor]; + chart.chartBackgroundColor = [UIColor grayColor]; + chart.showLineChart = true; + chart.rotateForXAxisText = YES; + chart.yLeftDetailText = @"Number of photos"; + chart.yRightDetailText = @"Engagement per photo"; + + [self.view addSubview:chart]; + [chart showAnimation]; +} -(void)columnChart:(JHColumnChart*)chart columnItem:(UIView *)item didClickAtIndexRow:(NSIndexPath *)indexPath{ NSLog(@"%@",indexPath); @@ -551,13 +643,4 @@ -(UIView *)tableChart:(JHTableChart*)chart viewForTableHeaderWithContentSize:(CG } - - - - - - - - - @end diff --git a/JHChartDemo/ViewController.m b/JHChartDemo/ViewController.m index 2ac664b..da07792 100644 --- a/JHChartDemo/ViewController.m +++ b/JHChartDemo/ViewController.m @@ -22,8 +22,8 @@ - (void)viewDidLoad { self.view.backgroundColor = [UIColor whiteColor]; - _itemsArr = @[@"折线图-第一象限",@"折线图-第一二象限",@"折线图第一四象限",@"折线图-全象限",@"饼图",@"环状图",@"柱状图",@"表格",@"雷达图",@"散点图"]; - + _itemsArr = @[@"折线图-第一象限",@"折线图-第一二象限",@"折线图第一四象限",@"折线图-全象限",@"饼图",@"环状图",@"柱状图",@"表格",@"雷达图",@"散点图", @"横向柱状图", @"双列柱状图"]; + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,self.view.frame.size.height - 64) style:UITableViewStylePlain]; _tableView.dataSource = self; _tableView.delegate =self;