object-c折線,效果如圖
折線圖
- (void)viewDidLoad {
[super viewDidLoad];
//x y 軸上的標注數(shù)值
NSArray *xArr = @[@"0",@"5",@"10",@"15",@"20",@"25",@"30",];
NSArray *yArr = @[@"0",@"2",@"4",@"6",@"8",@"10",@"12",];
//要畫的折線圖的各個點
NSMutableArray *pointArr = [NSMutableArray array];
for (int i=0; i<=20; i++)
{
CGPoint point = CGPointMake(i*1.5, random()%12);
NSValue *value = [NSValue valueWithCGPoint:point];
[pointArr addObject:value];
}
//傳入數(shù)值,畫折線圖
BrokenLineDemo *demo = [[BrokenLineDemo alloc]initWithFrame:CGRectMake(50, 100, 300, 300) andXValue:xArr YValueArr:yArr andPointArr:pointArr];
[self.view addSubview:demo];
}
主要其實就是畫線白修。重寫drawRect,再用CGContextRef重斑。
#define kChartLineColor [UIColor grayColor]
#define kLightFrayColor [UIColor colorWithWhite:0.8 alpha:1]
#define kChartTextColor [UIColor lightGrayColor]
#define k_Space 10
#import "BrokenLineDemo.h"
@interface BrokenLineDemo()
@property(nonatomic,strong)NSArray *xValueArr;//x軸上的標注值
@property(nonatomic,strong)NSArray *yValueArr;//y軸上的標注值
@property(nonatomic,assign)float xSpace;//x軸每個標注之間相隔的frame距離
@property(nonatomic,assign)float ySpace;//y軸每個標注之間相隔的frame距離
@property(nonatomic,assign)float xValueSpace;//x軸每個標注之間相隔的數(shù)值 0 5 10 15
@property(nonatomic,assign)float yValueSpace;//y軸每個標注之間相隔的數(shù)值 0 2 4 6 8
@property(nonatomic,assign)CGPoint startPoint;//坐標起始點
@property(nonatomic,strong)NSMutableArray *pointArr;//要畫的點的數(shù)組
@property(nonatomic,strong)NSMutableArray *lastPointArr;//將要畫的點轉(zhuǎn)化為此坐標軸上的點(傳過來的點的坐標軸原點在左上方兵睛,轉(zhuǎn)為此坐標軸的原點在左下方)
@end
重寫init
-(instancetype)initWithFrame:(CGRect)frame andXValue:(NSArray *)xValueArr YValueArr:(NSArray *)yValueArr andPointArr:(NSMutableArray *)pointArr
{
if (self=[super initWithFrame:frame])
{
self.xValueArr = xValueArr;//x軸的標注
self.yValueArr = yValueArr;//y軸的標注
self.pointArr = pointArr;//要畫的點的數(shù)值
self.lastPointArr = [NSMutableArray array];//存放轉(zhuǎn)化坐標軸之后的點
float xMin = [[xValueArr firstObject]floatValue];
float xMax = [[xValueArr lastObject]floatValue];
float yMin = [[yValueArr firstObject]floatValue];
float yMax = [[yValueArr lastObject]floatValue];
// x y 軸上每格的frame間距
self.xSpace = (frame.size.width-k_Space*3)/(xValueArr.count-1);
self.ySpace = (frame.size.height-k_Space*3)/(yValueArr.count-1);
// x y 軸上每格的標注間隔數(shù)值,此x軸為5窥浪,y軸為2
self.xValueSpace = (xMax-xMin)/(self.xValueArr.count-1);
self.yValueSpace = (yMax-yMin)/(self.yValueArr.count-1);
//畫圖的起點祖很,原點
self.startPoint = CGPointMake(k_Space*2, frame.size.height-k_Space*2);
//轉(zhuǎn)化坐標 例:傳入數(shù)值是(0,0)漾脂,原點在左上方假颇;轉(zhuǎn)化后因為原點在左下方上面一點點,因此點要畫在(k_Space*2, frame.size.height-k_Space*2)處
for (int i=0; i<self.pointArr.count; i++)
{
NSValue *value = self.pointArr[i];
CGPoint point = value.CGPointValue;
CGPoint lastPoint = CGPointMake((point.x/_xValueSpace)*(_xSpace)+_startPoint.x, _startPoint.y-(point.y/_yValueSpace)*(_ySpace));
[_lastPointArr addObject:[NSValue valueWithCGPoint:lastPoint]];
}
}
return self;
}
畫線其實很簡單骨稿,調(diào)用CGContextRef的方法就好笨鸡,難點在于坐標的轉(zhuǎn)化。傳入的數(shù)值坦冠,都是以原點在左上方的坐標軸為標準的數(shù)值形耗。如圖,(0辙浑,0)激涤,(0,1)判呕,(0倦踢,2)等,你要是直接用此數(shù)值佛玄,那點就直接畫在最上邊的那條線上硼一,顯然是不對的累澡。如圖傳入數(shù)值的坐標原點
我們要以左下方的那個點為坐標原點梦抢,進行轉(zhuǎn)換坐標。假如傳入的坐標是(10愧哟,6)奥吩,顯然x軸上標注數(shù)值相隔為5哼蛆,y軸標注數(shù)值相隔為2;設x軸每小格frame的間距為xSpace(即:x軸上每單元格在屏幕上的長度)霞赫,y軸上每小格的間距為ySpace(這兩個值都可以計算出來腮介,請看源碼);現(xiàn)原點(0端衰,0)距離重寫的view左邊間距為為20叠洗,下邊距為20;則
傳入為(10旅东,6)應該畫在屏幕上的點為:
X為
x
Y為(frame是重寫的view的frame)
y
以下方為坐標原點
坐標轉(zhuǎn)化后就可以直接畫點了灭抑,再講所有的點連線,over抵代。
思路就是這樣下面貼drawRect重寫腾节。(源碼地址:https://pan.baidu.com/s/1qYwrpBA)
重寫drawRect
- (void)drawRect:(CGRect)rect
{
CGContextRef context =UIGraphicsGetCurrentContext();
//x軸上的值
for (int i=0; i<_xValueArr.count; i++)
{
//x軸上的值
NSString *xTitle = _xValueArr[i];
[[UIColor blackColor]set];
NSDictionary *attr =@{NSFontAttributeName:[UIFont systemFontOfSize:10]};
CGSize labelSize = [xTitle sizeWithAttributes:attr];
float originX = k_Space*2+(_xSpace)*i;
CGRect xTitleRect = CGRectMake(originX-labelSize.width/2, rect.size.height-k_Space-5, labelSize.width, labelSize.height);
[self drawStr:xTitle withRect:xTitleRect textFontSize:10 textColor:kChartTextColor];
//x軸上的豎線
[self drawLine:context
startPoint:CGPointMake(originX, rect.size.height-k_Space*2)
endPoint:CGPointMake(originX, rect.size.height-k_Space*2-5)
lineColor:kChartLineColor
lineWidth:1];
}
//X軸
[self drawLine:context
startPoint:CGPointMake(k_Space*2, rect.size.height-k_Space*2)
endPoint:CGPointMake(self.frame.size.width, rect.size.height-k_Space*2)
lineColor:kChartLineColor
lineWidth:1];
for (int i=0; i<_yValueArr.count; i++)
{
//y軸上的值
NSString *yTitle = _yValueArr[i];
[[UIColor blackColor]set];
NSDictionary *attr =@{NSFontAttributeName:[UIFont systemFontOfSize:10]};
CGSize labelSize = [yTitle sizeWithAttributes:attr];
float yOrigin = _startPoint.y-(_ySpace*i);
CGRect yTitleRect = CGRectMake(k_Space, yOrigin-labelSize.height/2, labelSize.width, labelSize.height);
[self drawStr:yTitle withRect:yTitleRect textFontSize:10 textColor:kChartTextColor];
//畫y軸上的橫線
if (i>0)
{
[self drawLine:context
startPoint:CGPointMake(_startPoint.x,yOrigin)
endPoint:CGPointMake(rect.size.width,yOrigin)
lineColor:kLightFrayColor
lineWidth:1];
}
}
//y軸
[self drawLine:context
startPoint:_startPoint
endPoint:CGPointMake(_startPoint.x,0)
lineColor:kChartLineColor
lineWidth:1];
//畫point
for (int i=0; i<self.pointArr.count; i++)
{
NSValue *value = self.lastPointArr[i];
CGPoint point = value.CGPointValue;
//畫點
[self drawPointWithContext:context point:point color:[UIColor lightGrayColor]];
//畫點上的值
NSValue *oldValue = self.pointArr[i];
CGPoint oldPoint = oldValue.CGPointValue;
NSString *valueStr = [NSString stringWithFormat:@"%.2f",oldPoint.y];
CGSize labelSize = [valueStr sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10]}];
CGRect valueStrRect = CGRectMake(point.x-labelSize.width/2, point.y-5-labelSize.height, labelSize.width, labelSize.height);
[self drawStr:valueStr withRect:valueStrRect textFontSize:10 textColor:kChartTextColor];
//畫折線
if (i<_lastPointArr.count-1)
{
NSValue * endValaue = _lastPointArr[i+1];
CGPoint endPoint =[endValaue CGPointValue];
//畫折線
[self drawLine:context startPoint:point endPoint:endPoint lineColor:[UIColor colorWithRed:26/255.0 green:135/255.0 blue:254/255.0 alpha:1] lineWidth:1];
}
}
}
//畫文字
- (void)drawStr:(NSString *)titleStr withRect:(CGRect)rect textFontSize:(float)fontSize textColor:(UIColor *)textColor
{
UIFont *font = [UIFont systemFontOfSize:fontSize];
[titleStr drawInRect:rect withAttributes:@{NSFontAttributeName :font,NSForegroundColorAttributeName:textColor}];
}
//畫點
-(void)drawPointWithContext:(CGContextRef)context point:(CGPoint )point color:(UIColor *)pointColor
{
CGContextSetFillColorWithColor(context, pointColor.CGColor);//填充顏色
CGContextAddArc(context, point.x, point.y, 2, 0, 2*M_PI, 0); //添加一個圓
CGContextDrawPath(context, kCGPathFill);//繪制填充
}
//畫線
- (void)drawLine:(CGContextRef)context startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint lineColor:(UIColor *)lineColor lineWidth:(CGFloat)width {
CGContextSetShouldAntialias(context, YES ); //抗鋸齒
CGColorSpaceRef Linecolorspace1 = CGColorSpaceCreateDeviceRGB();
CGContextSetStrokeColorSpace(context, Linecolorspace1);
CGContextSetLineWidth(context, width);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextStrokePath(context);
CGColorSpaceRelease(Linecolorspace1);
}