iOS UIBezierPath、CAShapeLayer绘制柱

2020-03-21  本文已影响0人  Joymerry
柱状图——数据筛选 只要明白贝塞尔曲线的原理,样式随便变动

主要介绍如何实现柱状图功能
.h实现

@property (nonatomic,assign) double leftMargin;//左右边距
@property (nonatomic,assign) double bottomMargin;//上下边距
@property (nonatomic,assign) double horizontalMargin;//水平间距
@property (nonatomic,assign) double verticalMargin;//竖直间距
@property (nonatomic,assign) double priceLabelWidth;//y轴label宽度
@property (nonatomic,assign) double priceLabelHeight;//y轴label的高度
@property (nonatomic,assign) double columnWidth;//柱宽
@property (nonatomic,strong) NSArray * verticalArray;//y轴数组
@property (nonatomic,assign) double valuesMargin;//y轴数值间隔

@property (nonatomic,strong) NSArray * dateArray;//日期数组
@property (nonatomic,strong) NSArray * priceArray;//价格数组
@property (nonatomic,strong) NSArray * weightArray;//成交量数组

/**
 *  画柱状图
 *  @param x_names      x轴值的所有值名称
 *  @param targetValues 所有目标值(用于计算坐标)
 *  @param realValues 真实目标值
 */
-(void)drawBarChartViewWithX_Value_Names:(NSMutableArray *)x_names TargetValues:(NSMutableArray *)targetValues ;

.m实现代码

/**
 *  画柱状图
 */
-(void)drawBarChartViewWithX_Value_Names:(NSMutableArray *)x_names TargetValues:(NSMutableArray *)targetValues
{
    //1.画坐标轴
    [self drawXYLine:x_names];
    
    //2.每一个目标值点坐标
    for (int i=0; i < targetValues.count; i++) {
        //10为坐标间距
        CGFloat doubleValue = [targetValues[i] floatValue]/self.valuesMargin*self.verticalMargin; //目标值放大
        CGFloat X = self.leftMargin + self.priceLabelWidth + (self.horizontalMargin+self.columnWidth)*I;
        //CGFloat X = self.leftMargin + self.horizontalMargin*(i+1)+5;
        CGFloat Y = CGRectGetHeight(myFrame)-self.bottomMargin-doubleValue;
        
        UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(X, Y, self.columnWidth, doubleValue)];
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];
        shapeLayer.path = path.CGPath;
        shapeLayer.strokeColor = [UIColor clearColor].CGColor;
        shapeLayer.fillColor = XYQColor(0, 124, 104).CGColor;
        shapeLayer.borderWidth = 2.0;
        [self.subviews[0].layer addSublayer:shapeLayer];
        
        //新建一个按钮,透明 覆盖shapeLayer
        UIButton * btn = [[UIButton alloc]init];
        btn.frame = CGRectMake(X, Y, self.columnWidth, doubleValue);
        btn.backgroundColor = [UIColor clearColor];
        btn.tag = 1000 + I;
        [btn addTarget:self action:@selector(targetButtonClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:btn];
        if (i == targetValues.count - 1 && _dateArray.count > 0)
        {
            btn.backgroundColor = RGBA(255, 255, 255, 0.5);
            lastTag = 1000 + I;

            NSString * titleOne = [NSString stringWithFormat:@"%@",_dateArray[I]];
            NSString * titleTwo = [NSString stringWithFormat:@"%ld",[_priceArray[i] longValue]];
            NSString * titleThree = [NSString stringWithFormat:@"%ld",[_weightArray[i] longValue]];


            NSString *str1 = [titleOne substringToIndex:10];//截取掉下标10之前的字符串
            NSString *str2 = [str1 substringFromIndex:8];//截取掉下标8之后的字符串
            NSString * str3 = [str1 substringToIndex:7];
            NSString * str4 = [str3 substringFromIndex:5];
            NSString * dateStr = [NSString stringWithFormat:@"%@月%@日",str4,str2];

            NSString * title = [NSString stringWithFormat:@"%@ # %.2f元/吨 成交量%.3f吨",dateStr,[titleTwo doubleValue],[titleThree doubleValue]];
            titleLabel.hidden = NO;
            titleLabel.text = title;
        }
    }
}

/**
 *  画坐标轴
 */
-(void)drawXYLine:(NSMutableArray *)x_names{
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    
    UILabel * priceLabel = [[UILabel alloc]init];
    priceLabel.frame = CGRectMake(self.leftMargin, 5, 35, 15);
    priceLabel.text = @"价格:¥";
    priceLabel.textColor = [UIColor whiteColor];
    priceLabel.font = [UIFont systemFontOfSize:8.0];
    [self addSubview:priceLabel];
    
    
    UILabel * firstLabel = [[UILabel alloc]init];
    firstLabel.frame = CGRectMake(self.leftMargin,CGRectGetHeight(myFrame)-self.bottomMargin, self.priceLabelWidth, 20);
    firstLabel.text = @"最近一周";
    firstLabel.textColor = [UIColor whiteColor];
    firstLabel.font = [UIFont systemFontOfSize:8.0];
    firstLabel.adjustsFontSizeToFitWidth = YES;
    [self addSubview:firstLabel];
    
    
    //1.Y轴、X轴的直线
    [path moveToPoint:CGPointMake(self.leftMargin, CGRectGetHeight(myFrame)-self.bottomMargin)];
    [path addLineToPoint:CGPointMake(self.leftMargin+CGRectGetWidth(myFrame)-2*self.leftMargin, CGRectGetHeight(myFrame)-self.bottomMargin)];
    
    //2.添加箭头
//    [path moveToPoint:CGPointMake(MARGIN, MARGIN)];
//    [path addLineToPoint:CGPointMake(MARGIN-5, MARGIN+5)];
//    [path moveToPoint:CGPointMake(MARGIN, MARGIN)];
//    [path addLineToPoint:CGPointMake(MARGIN+5, MARGIN+5)];
//
//    [path moveToPoint:CGPointMake(MARGIN+CGRectGetWidth(myFrame)-2*MARGIN, CGRectGetHeight(myFrame)-MARGIN)];
//    [path addLineToPoint:CGPointMake(MARGIN+CGRectGetWidth(myFrame)-2*MARGIN-5, CGRectGetHeight(myFrame)-MARGIN-5)];
//    [path moveToPoint:CGPointMake(MARGIN+CGRectGetWidth(myFrame)-2*MARGIN, CGRectGetHeight(myFrame)-MARGIN)];
//    [path addLineToPoint:CGPointMake(MARGIN+CGRectGetWidth(myFrame)-2*MARGIN-5, CGRectGetHeight(myFrame)-MARGIN+5)];

    //3.添加索引格
    //X轴
    for (int i=0; i<x_names.count; i++) {
        CGFloat X = self.leftMargin + self.priceLabelWidth + (self.horizontalMargin+self.columnWidth)*I;
        CGPoint point = CGPointMake(X,CGRectGetHeight(myFrame)-self.bottomMargin);
        [path moveToPoint:point];
        [path addLineToPoint:CGPointMake(point.x, point.y-3)];
    }
    //Y轴(实际长度为200,此处比例缩小一倍使用)
    for (int i=0; i < self.verticalArray.count; i++) {
        CGFloat Y = CGRectGetHeight(myFrame)-self.bottomMargin-self.verticalMargin*I;
        CGPoint point = CGPointMake(self.leftMargin,Y);
        [path moveToPoint:point];
        [path addLineToPoint:CGPointMake(point.x+CGRectGetWidth(myFrame)-2*self.leftMargin, point.y)];
    }
    
    
    //4.添加索引格文字
    //X轴
    for (int i=0; i<x_names.count; i++) {
        CGFloat X = self.leftMargin + self.priceLabelWidth + (self.horizontalMargin+self.columnWidth)*i - self.horizontalMargin/2.0 + self.columnWidth/2.0;
        UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(X, CGRectGetHeight(myFrame)-self.bottomMargin, self.horizontalMargin, 20)];
        textLabel.text = x_names[I];
        textLabel.font = [UIFont systemFontOfSize:8];
        textLabel.textAlignment = NSTextAlignmentCenter;
        textLabel.textColor = XYQColor(244, 244, 244);
        [self addSubview:textLabel];
    }
    //Y轴
    for (int i=0; i < self.verticalArray.count; i++) {
        CGFloat Y = CGRectGetHeight(myFrame)-self.bottomMargin-self.verticalMargin*I;
        UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.leftMargin, Y-10,self.priceLabelWidth, 10)];
        textLabel.text = [NSString stringWithFormat:@"%@",self.verticalArray[I]];
        textLabel.font = [UIFont systemFontOfSize:8.0];
        textLabel.textAlignment = NSTextAlignmentLeft;
        textLabel.textColor = XYQColor(204, 204, 204);
        [self addSubview:textLabel];
    }
    
    //5.渲染路径
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = path.CGPath;
    shapeLayer.lineWidth = 0.2;
    shapeLayer.strokeColor = [UIColor whiteColor].CGColor;
    shapeLayer.fillColor = [UIColor clearColor].CGColor;
    shapeLayer.borderWidth = 0.5;
    [self.subviews[0].layer addSublayer:shapeLayer];
    
    
    //
    titleLabel = [[UILabel alloc]init];
    titleLabel.frame = CGRectMake(priceLabel.right, 5, self.width - self.leftMargin - priceLabel.right, 20);
    titleLabel.layer.masksToBounds = YES;
    titleLabel.layer.cornerRadius = titleLabel.height / 2.0;
    titleLabel.backgroundColor = kMainColor;
    titleLabel.hidden = YES;
    titleLabel.font = [UIFont systemFontOfSize:12.0];
    titleLabel.textAlignment = NSTextAlignmentCenter;
    titleLabel.textColor = [UIColor whiteColor];
    titleLabel.adjustsFontSizeToFitWidth = YES;
    [self addSubview:titleLabel];
}

这是主要实现的逻辑,而真正用到的也就是UIBezierPath、CAShapeLayer。
我们主要讲讲这两个类的作用。

上一篇下一篇

猜你喜欢

热点阅读