前些天由于需求自定义了K线图,由于效果变更,现将此K线图记录一下。
请先看效果图:
自定义label
KLineViewLabel.h:
#import <UIKit/UIKit.h>
@interface KLineViewLabel : UIView
@property(nonatomic,strong)UIImage *image;
@property(nonatomic,copy)NSString *title;
@property(nonatomic,assign)CGPoint centerPoint;
@end
KLineViewLabel.m文件:
#import "KLineViewLabel.h"
static CGFloat pointHeight = 10;
@interface KLineViewLabel()
@property(nonatomic,strong)UIView* pointView;
@property(nonatomic,strong)UIImageView* paopaoView;
@property(nonatomic,strong)UILabel *paopaoLabel;
@end
@implementation KLineViewLabel
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.pointView];
[self addSubview:self.paopaoView];
[self.pointView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(0);
}];
[self.paopaoView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.pointView);
make.bottom.mas_equalTo(self.pointView.mas_top).mas_offset(AdapterH(-3));
}];
}
return self;
}
- (UIView*)pointView{
if (!_pointView) {
_pointView = [[UIView alloc]init];
_pointView.layer.cornerRadius = pointHeight/2;
_pointView.layer.borderWidth = 3;
_pointView.layer.borderColor = UIColorFromRGB(0xff6639).CGColor;
_pointView.backgroundColor = [UIColor whiteColor];
}
return _pointView;
}
- (UIImageView*)paopaoView{
if (!_paopaoView) {
_paopaoView = [[UIImageView alloc]init];
[_paopaoView addSubview:self.paopaoLabel];
[self.paopaoLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(_paopaoView);
make.top.mas_equalTo(_paopaoView);
make.height.mas_equalTo(AdapterH(15));
}];
}
return _paopaoView;
}
- (UILabel*)paopaoLabel{
if (!_paopaoLabel) {
_paopaoLabel = [[UILabel alloc]init];
_paopaoLabel.textColor = [UIColor whiteColor];
_paopaoLabel.font = [UIFont systemFontOfSize:AdapterF(10)];
_paopaoLabel.textAlignment = NSTextAlignmentCenter;
}
return _paopaoLabel;
}
- (void)setImage:(UIImage *)image{
_image = image;
self.paopaoView.image = image;
}
- (void)setTitle:(NSString *)title{
_title = title;
self.paopaoLabel.text = title;
}
- (void)setCenterPoint:(CGPoint)centerPoint{
_centerPoint = centerPoint;
self.frame = CGRectMake(centerPoint.x- (pointHeight/2), centerPoint.y- (pointHeight/2), pointHeight, pointHeight);
}
@end
// KLineView.h 文件
#import <UIKit/UIKit.h>
@interface KLineView : UIView
/**
maxValue Y轴最大值
*/
@property(nonatomic,assign)CGFloat maxValue;
/**
minValue Y轴最小值
*/
@property(nonatomic,assign)CGFloat minValue;
/**
Y轴数据
*/
@property(nonatomic,strong)NSArray *horDataArr;
/**
X轴数据
*/
@property(nonatomic,strong)NSArray *VerDataArr;
@end
KLineView.m文件:
#import "KLineView.h"
#import "KLineViewLabel.h"
static CGFloat increment = 0.4;//增量因子,可自行配置
@interface KLineView()
/**
自定义label
*/
@property(nonatomic,strong)KLineViewLabel *pointLabel;
/**
点集合
*/
@property(nonatomic,strong)NSMutableArray *pointArr;
@end
@implementation KLineView
{
}
- (NSMutableArray*)pointArr{
if (!_pointArr) {
_pointArr = [[NSMutableArray alloc]init];
}
return _pointArr;
}
- (KLineViewLabel*)pointLabel {
if (!_pointLabel) {
_pointLabel = [[KLineViewLabel alloc]init];
_pointLabel.image = [UIImage imageNamed:@"pricePoint"];
[_pointLabel setHidden:YES];
}
return _pointLabel;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapHandle:)];
[self addGestureRecognizer:gesture];
[self addSubview:self.pointLabel];
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
//绘制坐标系
CGContextSetLineWidth(context, 0.5);
CGContextSetRGBStrokeColor(context, (CGFloat)196/255, (CGFloat)196/255, (CGFloat)196/255, 1);
CGContextMoveToPoint(context, AdapterW(39), AdapterH(129));
CGContextAddLineToPoint(context, AdapterW(39), AdapterH(16));
CGPoint arrowPoint[3];
arrowPoint[0] = CGPointMake(AdapterW(39-3), AdapterH(16+3));
arrowPoint[1] = CGPointMake(AdapterW(39), AdapterH(16));
arrowPoint[2] = CGPointMake(AdapterW(39+3), AdapterH(16+3));
CGContextAddLines(context, arrowPoint, 3);
CGContextMoveToPoint(context, AdapterW(39), AdapterH(129));
CGContextAddLineToPoint(context, AdapterW(359), AdapterH(129));
CGPoint arrowPoint2[3];
arrowPoint2[0] = CGPointMake(AdapterW(359-3), AdapterH(129-3));
arrowPoint2[1] = CGPointMake(AdapterW(359), AdapterH(129));
arrowPoint2[2] = CGPointMake(AdapterW(359-3), AdapterH(129+3));
CGContextAddLines(context, arrowPoint2, 3);
CGContextStrokePath(context);
CGFloat length[]={1,1};
CGContextSetLineDash(context, 0, length, 2);
CGContextMoveToPoint(context, AdapterW(43), AdapterH(29));
CGContextAddLineToPoint(context, AdapterW(359), AdapterH(29));
CGContextMoveToPoint(context, AdapterW(43), AdapterH(49));
CGContextAddLineToPoint(context, AdapterW(359), AdapterH(49));
CGContextMoveToPoint(context, AdapterW(43), AdapterH(69));
CGContextAddLineToPoint(context, AdapterW(359), AdapterH(69));
CGContextMoveToPoint(context, AdapterW(43), AdapterH(89));
CGContextAddLineToPoint(context, AdapterW(359), AdapterH(89));
CGContextMoveToPoint(context, AdapterW(43), AdapterH(109));
CGContextAddLineToPoint(context, AdapterW(359), AdapterH(109));
CGContextStrokePath(context);
CGFloat addBuf = (self.maxValue-self.minValue+increment*2)/5;
NSString* verStr1 = [NSString stringWithFormat:@"%.2f",self.minValue-increment];
NSString* verStr2 = [NSString stringWithFormat:@"%.2f",self.minValue-increment+addBuf];
NSString* verStr3 = [NSString stringWithFormat:@"%.2f",self.minValue-increment+ (addBuf*2)];
NSString* verStr4 = [NSString stringWithFormat:@"%.2f",self.minValue-increment+ (addBuf*3)];
CGFloat textMidWidth = [[APPManager defaultManager]getTextWidth:_horDataArr[0] setHeight:CGFLOAT_MAX setFont:[UIFont systemFontOfSize:AdapterF(8)]]/2;
NSDictionary* attribute = @{
NSForegroundColorAttributeName:UIColorFromRGB(0x322f2f),//设置文字颜色
NSFontAttributeName:[UIFont systemFontOfSize:AdapterF(8)],//设置文字的字体
};
//绘制Y轴数据及单位
[@"(元/m²/天)" drawAtPoint:CGPointMake(AdapterW(43), AdapterH(13)) withAttributes:attribute];
[verStr1 drawAtPoint:CGPointMake(AdapterW(12), AdapterH(102)) withAttributes:attribute];
[verStr2 drawAtPoint:CGPointMake(AdapterW(12), AdapterH(82)) withAttributes:attribute];
[verStr3 drawAtPoint:CGPointMake(AdapterW(12), AdapterH(62)) withAttributes:attribute];
[verStr4 drawAtPoint:CGPointMake(AdapterW(12), AdapterH(42)) withAttributes:attribute];
//绘制X轴数据
for (int i=0; i<_horDataArr.count; i++) {
[_horDataArr[i] drawAtPoint:CGPointMake(AdapterW(65*(i+1)), AdapterH(136)) withAttributes:attribute];
}
//添加Line
CGContextSetRGBStrokeColor(context, 1, (float)99/255, (float)38/255, 1);
CGContextSetRGBFillColor(context, 1, 1, 1, 1);
CGFloat length1[]={1};
CGContextSetLineDash(context, 0, length1, 0);
CGPoint sPoint[_VerDataArr.count];
for (int i=0; i<_VerDataArr.count; i++) {
CGFloat verHeight = AdapterH(20)/addBuf*([_VerDataArr[i] floatValue] - self.minValue+increment);
sPoint[i] = CGPointMake(AdapterW(65)*(i+1)+textMidWidth, AdapterH(109)-verHeight);
}
CGContextAddLines(context, sPoint, _VerDataArr.count);
CGContextStrokePath(context);
CGContextSetRGBFillColor(context, 1, 1, 1, 1);
//添加point
for (int i=0; i<_VerDataArr.count; i++) {
CGFloat verHeight = AdapterH(20)/addBuf*([_VerDataArr[i] floatValue] - self.minValue+increment);
CGContextAddArc(context, AdapterW(65)*(i+1)+textMidWidth, AdapterH(109)-verHeight, 3, 0, M_PI*2, NO);
CGContextDrawPath(context, kCGPathFillStroke);
CGPoint point = CGPointMake(AdapterW(65)*(i+1)+textMidWidth, AdapterH(109)-verHeight);
[self.pointArr addObject:[NSValue valueWithCGPoint:point]];
}
}
/**
点击区域位置,显示制定label
@param gesture label gesture
*/
- (void)tapHandle:(UITapGestureRecognizer*)gesture{
CGPoint point = [gesture locationInView:self];
NSInteger index = [self getClickPoint:point];
if (index >= 0) {
CGPoint currenPoint = [self.pointArr[index] CGPointValue];
self.pointLabel.centerPoint = currenPoint;
self.pointLabel.title = _VerDataArr[index];
[self.pointLabel setHidden:NO];
}
}
/**
获取点击坐标点
@param point 当前点击坐标
@return CGPoint 返回KLine显示坐标
*/
- (NSInteger)getClickPoint:(CGPoint)point{
for (int i=0; i<[self.pointArr count]; i++) {
CGPoint value = [self.pointArr[i] CGPointValue];
if (point.x<value.x+AdapterW(65/2)) {
return i;
}
}
return -1;
}
@end
由于需求简单,只做了这个满足需求的KLine,并没有复杂的交互,点击KLine区域 显示坐标值。
使用时自定义最大最小值,并传入data 即可