参考文章:
https://www.jianshu.com/p/303ecfab6f20
运行效果
1.折线图数据源
@protocol XLChartViewDataSource <NSObject>
@optional
/**
描点是否显示小圆点
@param chartView <#chartView description#>
@return <#return value description#>
*/
-(BOOL)showCirclePointChartView:(XLChartView *)chartView;
/**
描点颜色
@param chartView <#chartView description#>
@return <#return value description#>
*/
-(UIColor *)circlePointColorInChartView:(XLChartView *)chartView;
/**
阴影颜色
@param chartView <#chartView description#>
@return <#return value description#>
*/
-(UIColor *)shadowColorInChartView:(XLChartView *)chartView;
@required
/**
数据源数量
@param chartView <#chartView description#>
@return <#return value description#>
*/
-(NSInteger)numberOfItemsInChartView:(XLChartView *)chartView;
/**
X 轴最大值
@param chartView <#chartView description#>
@return <#return value description#>
*/
-(CGFloat)maxAxisXValueInChartView:(XLChartView *)chartView;
/**
X 轴坐标值
@param chartView <#chartView description#>
@param index <#index description#>
@return <#return value description#>
*/
-(CGFloat)chartView:(XLChartView *)chartView axisXAtIndex:(NSInteger)index;
/**
Y 坐标显示标题
@param chartView <#chartView description#>
@param yIndex <#yIndex description#>
@return <#return value description#>
*/
-(NSString *)chartView:(XLChartView *)chartView bottomTitleAtIndex:(NSInteger)yIndex;
/**
点击时显示标题
@param chartView <#chartView description#>
@param yIndex <#yIndex description#>
@return <#return value description#>
*/
-(NSString *)chartView:(XLChartView *)chartView titleForSelectAtIndex:(NSInteger)yIndex;
@end
2.折线图主要方法说明
a.折线图需要使用如下方法初始化
- (instancetype)initWithFrame:(CGRect)frame
b.计算折线区域大小,记录阴影起始、终点位置
-(void)initViewDisplayWithFrame:(CGRect)frame{
// 计算折线区域
CGFloat totalHeight = frame.size.height;
_drawHeight = totalHeight - XLTopSpaceHeight - XLBottomTitleHeight;
_drawWidth = frame.size.width - XLHorSpace * 2;
CGFloat datHeight = self.drawHeight / XLMaxLineNumber;
// 绘制折线区域
_chartView = [[UIView alloc] initWithFrame:CGRectMake(XLHorSpace, XLTopSpaceHeight, self.drawWidth, self.drawHeight)];
[self addSubview:_chartView];
// 添加点击手势
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(chartViewTapGesture:)];
[_chartView addGestureRecognizer:tapGesture];
// 起始、终点描点位置
CGFloat datY = self.drawHeight;
self.xstartPoint = CGPointMake(0, datY);
self.xendPoint = CGPointMake(self.drawWidth, datY);
// 底部横线
_bottomLineView = [[UIView alloc] initWithFrame:CGRectMake(0, totalHeight - XLBottomTitleHeight, frame.size.width, 0.5)];
_bottomLineView.backgroundColor = [UIColor colorWithWhite:0.4 alpha:0.5];
[self addSubview:_bottomLineView];
// 折线区域划线
for (NSInteger index = 0; index < XLMaxLineNumber; index ++) {
CGPoint startPoint = CGPointMake(0, index * datHeight);
CGPoint endPoint = CGPointMake(self.drawWidth, index * datHeight);
UIBezierPath *linePath = [[UIBezierPath alloc] init];
[linePath moveToPoint:startPoint];
[linePath addLineToPoint:endPoint];
CAShapeLayer *contentLineLayer = [[CAShapeLayer alloc] init];
contentLineLayer.strokeColor = [UIColor colorWithWhite:0.5 alpha:0.2].CGColor;
contentLineLayer.lineWidth = 0.5f;
contentLineLayer.fillColor = [UIColor clearColor].CGColor;
contentLineLayer.path = linePath.CGPath;
[self.chartView.layer addSublayer:contentLineLayer];
[self.contentLineLayers addObject:contentLineLayer];
}
// 点击标签
[self.chartView addSubview:self.tagLabel];
}
c.注意:在调用绘制方法前,需先设置数据源
CGRect frame = CGRectMake(XLHorzMargin, 330.0f, XLScreenWidth - XLHorzMargin * 2, 240.0f);
XLChartView *chartView = [[XLChartView alloc] initWithFrame:frame];
chartView.xlDelegate = self;
[chartView drawChartView];
d.绘制折线
绘制前先清理已绘制信息,主要是为处理在UITableview中使用时Cell复用,折线图会根据折线中最大值及折线图绘制区域高度自试应处理
/**
绘制折线图
*/
-(void)drawChartView{
[self clearAllViewData];
if(![self hasPointData]){
return;
}
NSInteger itemCount = [self.xlDelegate numberOfItemsInChartView:self];
CGFloat maxValue = [self.xlDelegate maxAxisXValueInChartView:self];
CGFloat topSpace = self.drawHeight / (XLMaxLineNumber + 1);
// 单位内高度值
CGFloat unitHeight = (self.drawHeight - topSpace) / maxValue;
CGFloat datX = self.drawWidth / (itemCount - 1);
CGFloat firstValue = [self.xlDelegate chartView:self axisXAtIndex:0];
CGPoint firstPoint = CGPointMake(0, self.drawHeight - firstValue * unitHeight);
// 阴影起点
[self.shadowPath moveToPoint:self.xstartPoint];
// 显示描点
BOOL showCirclePoint = NO;
if(self.xlDelegate &&
[self.xlDelegate respondsToSelector:@selector(showCirclePointChartView:)]){
showCirclePoint = [self.xlDelegate showCirclePointChartView:self];
}
// 绘制折线图
for (NSInteger index = 0; index < itemCount; index ++) {
CGFloat value = [self.xlDelegate chartView:self axisXAtIndex:index];
CGFloat height = value * unitHeight;
// 坐标转换
CGPoint point = CGPointMake(index * datX, self.drawHeight - height);
[self drawTimeLine:firstPoint toPoint:point];
firstPoint = point;
[self.pointYArray addObject:[NSString stringWithFormat:@"%.2f", point.y]];
[self.pointXArray addObject:[NSString stringWithFormat:@"%.2f", point.x]];
if(showCirclePoint){
[self setupCircleLayer:point tag:index];
}
NSString *title = [self.xlDelegate chartView:self bottomTitleAtIndex:index];
UILabel *label = [self bottomLabelWithTitle:title atIndex:index datX:datX];
[self.bottomTitleLabels addObject:label];
}
// 阴影终点
[self.shadowPath addLineToPoint:self.xendPoint];
// 阴影终点链接起点
[self.shadowPath addLineToPoint:self.xstartPoint];
// 绘制阴影路径
if(self.xlDelegate &&
[self.xlDelegate respondsToSelector:@selector(shadowColorInChartView:)]){
UIColor *color = [self.xlDelegate shadowColorInChartView:self];
self.shadowColorLayer.fillColor = color.CGColor;
}
self.shadowColorLayer.path = self.shadowPath.CGPath;
[self.chartView.layer insertSublayer:self.shadowColorLayer atIndex:0];
}
// 绘制折现
- (void)drawTimeLine:(CGPoint)point toPoint:(CGPoint)toPoint {
[self.chartLinePath moveToPoint:point];
[self.chartLinePath addLineToPoint:toPoint];
// 添加阴影描点
[self.shadowPath addLineToPoint:toPoint];
self.chartLineLayer.path = self.chartLinePath.CGPath;
[self.chartView.layer addSublayer:self.chartLineLayer];
}
e.点击时描点显示处理
/**
显示标签
@param point <#point description#>
*/
- (void)showTagLabel:(CGPoint)point {
NSInteger count = [self.xlDelegate numberOfItemsInChartView:self];
if (count == 0) {
return;
}
// 1.点击位置处理:取间隔的一半值作为计算单位
CGFloat datX = self.drawWidth / (count - 1) / 2;
// 2.去除首位的一个计算单位
NSInteger datCount = (point.x - datX) / datX;
NSInteger index = 0;
if (point.x - datX < 0) {
// 小于 0 点击位置为首位
index = 0;
} else {
// 之后每两个计算单位则下标增加1,下标从1开始计算
index = datCount / 2 + 1;
}
NSString *title = [self.xlDelegate chartView:self titleForSelectAtIndex:index];
if (!title || title.length == 0) {
return;
}
// 取描点坐标
NSString *whichY = self.pointYArray[index];
NSString *whichX = self.pointXArray[index];
self.tagLabel.center = CGPointMake(whichX.floatValue, whichY.floatValue - 25);
self.tagLabel.text = title;
self.tagLabel.hidden = NO;
[self.chartView bringSubviewToFront:self.tagLabel];
}
----------------------分割线--------------------------------
GitHub地址:
XLChartView
如您看到这篇文章中有任何疑问或者错误的地方欢迎随时留言指正,我会及时改正,谢谢。