iOS 统计图绘制 - 柱状图、圆环图

绘制柱状统计图

柱状统计图

把 SSTMonthColumnChart 添加到 View 上

@property (nonatomic, strong) SSTMonthColumnChart *knownColumnChart;

self.knownColumnChart = [self createColumnView];

self.knownColumnChart.valueArr = @[chineseDataArr,mathDataArr,englishDataArr];
[self.knownColumnChart showAnimation];

//柱状图
- (SSTMonthColumnChart *)createColumnView{
    SSTMonthColumnChart *column = [[SSTMonthColumnChart alloc] initWithFrame:CGRectMake(0, -20, kFullScreenWidth, 125 + 20)];
    /*        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],
//                        ];
    /*       This point represents the distance from the lower left corner of the origin.         */
    column.originSize = CGPointMake(50, 20);
    /*    The first column of the distance from the starting point     */
    column.drawFromOriginX = 30;
//    column.backgroundColor = [UIColor purpleColor];
    column.typeSpace = (kFullScreenWidth - 100 - 60 - 120)/2; //25;
    column.isShowYLine = NO;
    column.contentInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    /*        Column width         */
    column.columnWidth = 10;
    /*        Column backgroundColor         */
    column.bgVewBackgoundColor =  [UIColor clearColor]; // UIColorFromHex(COLOR_F1F3FA); //
    /*        X, Y axis font color         */
    column.drawTextColorForX_Y = [UIColor xy_createWithLightColor:UIColorFromHex(COLOR_393939) darkColor:UIColorFromHex(COLOR_FFFFFF)];
    /*        X, Y axis line color         */
    column.colorForXYLine = [UIColor xy_createWithLightColor:UIColorFromHex(COLOR_D0D5E6) darkColor:UIColorFromHex(COLOR_494F57)];
    /*    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 blueColor],[UIColor blueColor]],@[[UIColor yellowColor],[UIColor brownColor]]];//如果为复合型柱状图 即每个柱状图分段 需要传入如上颜色数组 达到同时指定复合型柱状图分段颜色的效果
//    column.columnBGcolorsArr = @[@[[UIColor redColor]],@[[UIColor blueColor]],@[[UIColor yellowColor]]];//如果为复合型柱状图 即每个柱状图分段 需要传入如上颜色数组 达到同时指定复合型柱状图分段颜色的效果
    //column.xDescTextFontSize = 12;
    column.columnBGcolorsArr = @[_dotColorArr,_dotColorArr,_dotColorArr];//@[[UIColor redColor],[UIColor blueColor],[UIColor yellowColor]];//如果为复合型柱状图 即每个柱状图分段 需要传入如上颜色数组 达到同时指定复合型柱状图分段颜色的效果
    /*        Module prompt         */
    column.xShowInfoText = @[@"语文",@"数学",@"英语"];
    column.isShowLineChart = NO;
//    column.lineValueArray =  @[
//                               @6,
//                               @12,
//                               @10,
//                               @1,
//                               @9,
//                               @5,
//                               @9,
//                               @9,
//                               @5,
//                               @6,
//                               @4,
//                               @8,
//                               @11
//                               ];

//    column.delegate = self;
    /*       Start animation        */
//    [column showAnimation];
    [self.chartBgView addSubview:column];
    return column;
}

自定义柱状统计图 SSTMonthColumnChart

//设置数据
-(void)setValueArr:(NSArray<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;
                };
            }else{
                currentNumber = [NSString stringWithFormat:@"%@",number].floatValue;
            }
            if (currentNumber>max) {
                max = currentNumber;
            }
        }
    }
    //找出数据中的最大值,重新设定最大值;当次max为3的倍数的时候,就是当前max;当不是的时候,取把max加到3的倍数就是新的max值;
    int maxInt = ceilf(max*1.0);
    int remNum = maxInt%3; // 1
    if (remNum == 0) {
        _maxHeight = maxInt;
    }else {
        _maxHeight = max+3-remNum;
    }
    _perHeight = (CGRectGetHeight(self.frame) - 30 - _originSize.y - self.contentInsets.top)/_maxHeight;
}
//显示动画
-(void)showAnimation{

    [self clear];
    
    _columnWidth = (_columnWidth<=0?30:_columnWidth); // 每个柱状图的宽度;
    _columnSpace = (_columnSpace<=0?5:_columnSpace); // 每个柱状图之间的间隔;

    NSInteger count = _valueArr.count * [_valueArr[0] count]; // 总共有9个柱状图
    _typeSpace = (_typeSpace<=0?15:_typeSpace); // 两个类型数组之间的距离
    if (count > _valueArr.count) { // 一个类型有多个数据的情况;drawFromOriginX 从x点开始绘制图;_maxWidth最大的绘制区域;
        _maxWidth = count * _columnWidth + (_valueArr.count - 1) * _typeSpace  + _drawFromOriginX * 2 + (count - _valueArr.count) * _columnSpace + self.originSize.x * 2;
    }else {
        _maxWidth = count * _columnWidth + (_valueArr.count - 1) * _typeSpace + _drawFromOriginX * 2 + self.originSize.x * 2;
    }
    self.BGScrollView.contentSize = CGSizeMake(_maxWidth, 0); // 图表绘制背景;
    self.BGScrollView.backgroundColor = _bgVewBackgoundColor;
    
    /*        绘制X、Y轴  可以在此改动X、Y轴字体大小       */
    if (_needXandYLine) {
        
        CAShapeLayer *layer = [CAShapeLayer layer];
        [self.layerArr addObject:layer];
        UIBezierPath *bezier = [UIBezierPath bezierPath];
        if (self.isShowYLine) {
            [bezier moveToPoint:CGPointMake(self.originSize.x, CGRectGetHeight(self.frame) - self.originSize.y)]; // 开始绘制线的地方 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 - self.originSize.x, CGRectGetHeight(self.frame) - self.originSize.y)]; // X 轴
        layer.lineWidth = 0.5;
        [layer setLineDashPattern:@[@(3),@(3)]]; // 绘制虚线
        layer.path = bezier.CGPath;
        //layer.strokeColor = (_colorForXYLine==nil?([UIColor blackColor].CGColor):_colorForXYLine.CGColor);
        layer.strokeColor = (_dashColor==nil?([UIColor darkGrayColor].CGColor):_dashColor.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.BGScrollView.layer addSublayer:layer];
        
        /*        设置虚线辅助线         */  //        _maxHeight += 4;
        UIBezierPath *second = [UIBezierPath bezierPath];
        NSInteger dottedLineNum = 3; //虚线的条数
        for (NSInteger i = 0; i<dottedLineNum; i++) {
            NSInteger pace = (_maxHeight) / dottedLineNum;
            CGFloat height = _perHeight * (i+1)*pace; // 每个刻度之间的高度;
            [second moveToPoint:P_M(_originSize.x, CGRectGetHeight(self.frame) - _originSize.y - height)]; // 是从下往上画的
            [second addLineToPoint:P_M(_maxWidth - _originSize.x, CGRectGetHeight(self.frame) - _originSize.y - height)]; // 绘制虚线
           
            CATextLayer *textLayer = [CATextLayer layer]; // Y 刻度值
            textLayer.contentsScale = [UIScreen mainScreen].scale;
            NSString *text =[NSString stringWithFormat:@"%ld",(i + 1) * pace];
            CGFloat be = [self sizeOfStringWithMaxSize:XORYLINEMAXSIZE textFont:self.yDescTextFontSize aimString:text].width;
            textLayer.frame = CGRectMake(self.originSize.x - be - 3, CGRectGetHeight(self.frame) - _originSize.y -height - 5, be, 15);
            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);
            // Y 轴刻度,暂时不用了;
            //textLayer.string = text;
            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) {
        NSInteger count = [_valueArr[0] count];
        for (NSInteger i = 0; i<_xShowInfoText.count; i++) {
            CATextLayer *textLayer = [CATextLayer layer];
            CGFloat wid =  count * _columnWidth + (count-1)*_columnSpace; // 整个数据模块的宽度;
            CGSize size = [_xShowInfoText[i] boundingRectWithSize:CGSizeMake(wid, MAXFLOAT) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:FONTBOLD(self.xDescTextFontSize)} context:nil].size;
            textLayer.frame = CGRectMake( wid*i + i*_typeSpace + _originSize.x + _drawFromOriginX + wid/2 - size.width/2, CGRectGetHeight(self.frame) - _originSize.y+5,size.width,size.height);
            textLayer.string = _xShowInfoText[i]; // 显示X轴的提示
            textLayer.contentsScale = [UIScreen mainScreen].scale;
            textLayer.backgroundColor = [UIColor clearColor].CGColor;
            UIFont *font = FONTBOLD(self.xDescTextFontSize);
            textLayer.fontSize = font.pointSize;
            textLayer.foregroundColor = UIColorFromHex(0x7C819C).CGColor;
            textLayer.alignmentMode = kCAAlignmentCenter;
            [_BGScrollView.layer addSublayer:textLayer];
            [self.layerArr addObject:textLayer];
        }
    }
    
    /*        动画展示         */
    for (NSInteger i = 0; i<_valueArr.count; i++) {
        // valueArr 每个柱形图具体的值;
        NSArray *arr = _valueArr[i];
        for (NSInteger j = 0; j<arr.count; j++) { // j代表某个柱形图中的第几个值
            CGFloat height = 0; // 柱状图的高度;
            id colors = nil;
            if ([arr[j] isKindOfClass:[NSArray class]]) { // 这个是一个柱形图有多个数据的;
                NSAssert([_columnBGcolorsArr[j] isKindOfClass:[NSArray class]] &&_columnBGcolorsArr.count >= arr.count , @"when current columnItem is  component,you must offer a NSArray type for item's color");
                id colorssArr = _columnBGcolorsArr[i];
                if ([colorssArr isKindOfClass:[NSArray class]]) {
                    NSArray *colorItemArr = (NSArray *)colorssArr;
                    colors = [colorItemArr objectOrNilAtIndex:j];
                }
                for (id obj in arr[j]) {
                    height += [obj floatValue];
                }
                height = height * _perHeight;
            }else{ // 一个X只有一个柱形图的
                height =[arr[j] floatValue] *_perHeight;
                colors = (_columnBGcolorsArr.count<arr.count?[UIColor greenColor]:_columnBGcolorsArr[i]); //要用i来获取颜色才对;
                NSArray *colorArr = (NSArray *)colors;
                if ([colors isKindOfClass:[NSArray class]] && [colorArr count] > 0) {
                    colors = colors[0];
                }
            }
            //colors 柱形图的颜色
            
            id valueTempArr = arr[j]; // 这个已经取到了一个类型数据里的某一个元素;
            id valueToArr;
            if ([valueTempArr isKindOfClass:[NSArray class]]) {
                NSArray *tempArr = (NSArray *)valueTempArr;
                valueToArr = [tempArr objectOrNilAtIndex:0]; // 取到具体的值
            }else {
                valueToArr = arr[j];
            }
            
            __block CGRect columnItemRect = CGRectMake((i * arr.count + j)*(_columnWidth+_columnSpace) + i*_typeSpace + _originSize.x + _drawFromOriginX - i*_columnSpace, CGRectGetHeight(self.frame) - height - _originSize.y - 1, _columnWidth, height);
            
            JHColumnItem *itemsView = [[JHColumnItem alloc] initWithFrame:columnItemRect perHeight:_perHeight valueArray:valueToArr colors:colors];
            itemsView.clipsToBounds = YES;
            //itemsView.delegate = self;
            NSIndexPath *path = [NSIndexPath indexPathForRow:j inSection:i];
            itemsView.index = path;
            [self.showViewArr addObject:itemsView];
            itemsView.frame = CGRectMake(columnItemRect.origin.x, columnItemRect.origin.y, _columnWidth, 0);

            if (_isShowLineChart) { // 绘制折线
                NSString *value = [NSString stringWithFormat:@"%@",_lineValueArray[i]];
                float valueFloat =[value floatValue];
                NSValue *lineValue = [NSValue valueWithCGPoint:P_M(CGRectGetMaxX(itemsView.frame) - _columnWidth / 2, CGRectGetHeight(self.frame) - valueFloat * _perHeight - _originSize.y -1)];
                [self.drawLineValue addObject:lineValue];
            }
            [self.BGScrollView addSubview:itemsView];
            
            WS(weakSelf); // weakSelf.columnSpace
            [UIView animateWithDuration:1 animations:^{
                itemsView.frame = CGRectMake(columnItemRect.origin.x, columnItemRect.origin.y, weakSelf.columnWidth, height);
            } completion:^(BOOL finished) {
                /*        动画结束后添加提示文字         */
                if (finished) {
                    CATextLayer *textLayer = [CATextLayer layer];
                    [self.layerArr addObject:textLayer];
                    NSString *str = [NSString stringWithFormat:@"%0.0f",height / weakSelf.perHeight];
                    CGSize size = [str boundingRectWithSize:CGSizeMake(MAXFLOAT, 20) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:9]} context:nil].size;
                    textLayer.frame = CGRectMake(CGRectGetMinX(itemsView.frame), CGRectGetMinY(itemsView.frame) - size.height - 5,size.width, size.height);
                    CGPoint center = textLayer.position;
                    center.x = itemsView.center.x;
                    textLayer.position = center;
                    textLayer.string = str;
                    textLayer.fontSize = 9.0;
                    textLayer.alignmentMode = kCAAlignmentCenter;
                    textLayer.contentsScale = [UIScreen mainScreen].scale;
                    //textLayer.foregroundColor = itemsView.backgroundColor.CGColor;
                    textLayer.foregroundColor = weakSelf.drawTextColorForX_Y.CGColor;
                    [weakSelf.BGScrollView.layer addSublayer:textLayer];
                    
                    //添加折线图
                    if (i==weakSelf.valueArr.count - 1&&j == arr.count-1 && weakSelf.isShowLineChart) {
                        
                        UIBezierPath *path = [UIBezierPath bezierPath];
                        for (int32_t m=0;m<weakSelf.lineValueArray.count;m++) { // _lineValueArray    NSArray *    nil    0x0000000000000000
                            NSLog(@"%@",weakSelf.drawLineValue[m]);
                            if (m==0) {
                                [path moveToPoint:[weakSelf.drawLineValue[m] CGPointValue]];
                            }else{
                                [path addLineToPoint:[weakSelf.drawLineValue[m] CGPointValue]];
                                [path moveToPoint:[weakSelf.drawLineValue[m] CGPointValue]];
                            }
                        }
                        CAShapeLayer *shaper = [CAShapeLayer layer];
                        shaper.path = path.CGPath;
                        shaper.frame = self.bounds;
                        shaper.lineWidth = 2.5;
                        shaper.strokeColor = weakSelf.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.BGScrollView.layer addSublayer:shaper];
                        
                    }
                    
                }
                
            }];

        }
        
    }
}

绘制圆环比例图

圆环统计图

把 SSTRingChart 添加到 View 上

@property (strong, nonatomic)SSTRingChart *ring; /** 圆环图*/

[self.ring removeFromSuperview];
self.ring.backgroundColor = [UIColor generateDynamicColor:UIColorFromHex(COLOR_FFFFFF) darkColor:UIColorFromHex(COLOR_000000)];
self.ring.desColor = [UIColor generateDynamicColor:UIColorFromHex(COLOR_393939) darkColor:UIColorFromHex(COLOR_FFFFFF)];
self.ring.desDataArr = [knowledgeNameArr copy];
self.ring.ringWidth = 20.0;
self.ring.fillColorArray = [fillCorlorArr copy];
self.ring.valueDataArr = [valueArr copy];
self.ring.desNumArr = [knowNumArr copy];
[self.ring showAnimation];
[self.trainRingBackView addSubview: self.ring];

-(SSTRingChart *)ring{
    if (!_ring) {
        _ring = [[SSTRingChart alloc] initWithFrame:CGRectMake(0,0,200,200)];
        _ring.xl_centerX = kFullScreenWidth/2;
        _ring.xl_centerY = 125/2;
        _ring.canClick = NO;
    }
    return _ring;
}

自定义圆环统计图 SSTRingChart

//开始动画
- (void)showAnimation {

    [self.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; // 清除
    [pieShapeLayerArray removeAllObjects];
    CGFloat lastBegin = -M_PI/2; // -0.7 从X轴上方,顺时针绘制;
    CGFloat totloL = 0; // 百分比的累加
    NSInteger  i = 0;
    //_valueDataArr = @[@(0.73),@(0.04),@(0.04),@(0.04),@(0.04),@(0.04),@(0.04),@(0.03)];
    for (id obj in _valueDataArr) {
        //初始化Layer
        CustomShapeLayer *layer = [CustomShapeLayer layer];
        //CAShapeLayer *layer = [CAShapeLayer layer] ;
        UIBezierPath *path = [UIBezierPath bezierPath];
        layer.strokeColor = [UIColor clearColor].CGColor;
        CGFloat cuttentpace = [obj floatValue] / _totolCount * (M_PI * 2 - _itemsSpace * _valueDataArr.count); // itemsSpace 空隙的大小
        totloL += [obj floatValue] / _totolCount;
        [path moveToPoint:self.chartOrigin];
        //圆弧 默认最右端为0,YES时为顺时针。NO时为逆时针。
        [path addArcWithCenter:self.chartOrigin radius:_redius startAngle:lastBegin endAngle:lastBegin  + cuttentpace clockwise:YES];
        [path addArcWithCenter:self.chartOrigin radius:_redius-_ringWidth startAngle:lastBegin  + cuttentpace endAngle:lastBegin clockwise:NO];
        //添加到圆心直线
        [path addLineToPoint:self.chartOrigin];
        //路径闭合
        [path closePath];
        
        layer.centerPoint = self.chartOrigin;
        layer.startAngle = lastBegin;
        layer.endAngle = lastBegin+cuttentpace;
        layer.radius = _redius;
        layer.innerRadius = _redius-_ringWidth;
        layer.innerColor = [UIColor whiteColor];
        layer.path = path.CGPath;
        [pieShapeLayerArray addObject:layer];
        [self.layer addSublayer:layer]; // 一个一个比例模块的添加;
        layer.lineWidth = _ringWidth;
        if (i<_fillColorArray.count) {
            layer.fillColor =[_fillColorArray[i] CGColor];
        }else{
            layer.fillColor =[k_COLOR_STOCK[i%k_COLOR_STOCK.count] CGColor];
        }
        CABasicAnimation *basic = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        basic.fromValue = @(0);
        basic.toValue = @(1);
        basic.duration = 0.25;
        basic.fillMode = kCAFillModeForwards;
        [layer addAnimation:basic forKey:@"basic"];
        lastBegin += (cuttentpace+_itemsSpace);
        i++;
    }
}

//绘制方法
-(void)drawRect:(CGRect)rect{ // 绘制线条和文字;
    
    CGContextRef contex = UIGraphicsGetCurrentContext();
    
    CGFloat lastBegin = 0; // -0.7
    CGFloat longLen = _redius +15; // *k_Width_Scale 30
    for (NSInteger i = 0; i<_valueDataArr.count; i++) {
        id obj = _valueDataArr[i];
        CGFloat currentSpace = [obj floatValue] / _totolCount * (M_PI * 2 - _itemsSpace * _valueDataArr.count); // _totolCount    CGFloat    1.0000000298023224
        NSLog(@"%f",currentSpace); //3.4906585664064949
        CGFloat midSpace = lastBegin + currentSpace / 2; // sin(midSpace) 0.98480774759283585   po cos(midSpace) -0.17364820840171452
        CGPoint begin = CGPointMake(self.chartOrigin.x + sin(midSpace) * _redius, self.chartOrigin.y - cos(midSpace)*_redius);
        CGPoint endx = CGPointMake(self.chartOrigin.x + sin(midSpace) * longLen, self.chartOrigin.y - cos(midSpace)*longLen);
        NSLog(@"%@%@",NSStringFromCGPoint(begin),NSStringFromCGPoint(endx));
        lastBegin += _itemsSpace + currentSpace;
        UIColor *color;
        if (_fillColorArray.count<_valueDataArr.count) {
            color = k_COLOR_STOCK[i%k_COLOR_STOCK.count];
        }else{
            color = _fillColorArray[i];
        }
        [self drawLineWithContext:contex andStarPoint:begin andEndPoint:endx andIsDottedLine:NO andColor:color];
        
        CGPoint secondP = CGPointZero;
        CGFloat secondP_W = 40;
        NSString *desText = (NSString *)_desDataArr[i];
        NSString *desNumText = (NSString *)[self.desNumArr objectOrNilAtIndex:i];
        
        CGSize size = [desText boundingRectWithSize:CGSizeMake(200, 100) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:FONTBOLD(9)} context:nil].size;
        CGSize sizeNum = [desNumText boundingRectWithSize:CGSizeMake(200, 100) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:FONTBOLD(11)} context:nil].size;

        if (midSpace<M_PI) { // 右边的文字
            
            secondP =CGPointMake(endx.x + secondP_W, endx.y); // *k_Width_Scale
            
            NSMutableAttributedString *attributeDesStr = [[NSMutableAttributedString alloc] initWithString:desText];
            NSDictionary *attributeDesDic = @{NSFontAttributeName:FONTBOLD(9)};
            [attributeDesStr addAttributes:attributeDesDic range:NSMakeRange(0,desText.length)];
            [attributeDesStr addAttribute:NSForegroundColorAttributeName value:self.desColor range:NSMakeRange(0,desText.length)];
            
            CGFloat w;
            if (secondP.x + 3 + size.width > [UIScreen mainScreen].bounds.size.width) {
                w = [UIScreen mainScreen].bounds.size.width - secondP.x + 3;
            }else{
                w = size.width;
            }
            
            CGFloat des_X = secondP.x - w; // secondP.x + 3
            CGFloat des_Y = secondP.y + size.height / 2; // secondP.y - size.height / 2
            
            [attributeDesStr drawInRect:CGRectMake(des_X, des_Y, w, size.height)];
            
            // 知识点个数
            if (desNumText.length > 0) {
                NSMutableAttributedString *attributeNumStr = [[NSMutableAttributedString alloc] initWithString:desNumText];
                NSDictionary *attributeNumDic = @{NSFontAttributeName:FONTBOLD(11)};
                [attributeNumStr addAttributes:attributeNumDic range:NSMakeRange(0,desNumText.length-1)];
                NSDictionary *attributeNumDic1 = @{NSFontAttributeName:FONTBOLD(9)};
                [attributeNumStr addAttributes:attributeNumDic1 range:NSMakeRange(desNumText.length-1,1)];
                [attributeNumStr addAttribute:NSForegroundColorAttributeName value:self.desColor range:NSMakeRange(0,desNumText.length)];
                CGFloat desN_X = secondP.x - sizeNum.width; // secondP.x + 3
                CGFloat desN_Y = secondP.y - sizeNum.height - 3; // secondP.y - size.height / 2
                [attributeNumStr drawInRect:CGRectMake(desN_X, desN_Y, sizeNum.width, sizeNum.height)];
            }
            
        }else{ //左边的文字
            
            secondP =CGPointMake(endx.x - secondP_W, endx.y);
            
            NSMutableAttributedString *attributeDesStr = [[NSMutableAttributedString alloc] initWithString:desText];
            NSDictionary *attributeDesDic = @{NSFontAttributeName:FONTBOLD(9)};
            [attributeDesStr addAttributes:attributeDesDic range:NSMakeRange(0,desText.length)];
            [attributeDesStr addAttribute:NSForegroundColorAttributeName value:self.desColor range:NSMakeRange(0,desText.length)];
            
            CGFloat w = size.width;
            CGFloat des_X = secondP.x + 3; // secondP.x + 3
            CGFloat des_Y = secondP.y + size.height / 2; // secondP.y - size.height / 2
            
            [attributeDesStr drawInRect:CGRectMake(des_X, des_Y,w, size.height)];
            
            // 知识点个数
            if (desNumText.length > 0) {
                NSMutableAttributedString *attributeNumStr = [[NSMutableAttributedString alloc] initWithString:desNumText];
                NSDictionary *attributeNumDic = @{NSFontAttributeName:FONTBOLD(11)};
                [attributeNumStr addAttributes:attributeNumDic range:NSMakeRange(0,desNumText.length-1)];
                NSDictionary *attributeNumDic1 = @{NSFontAttributeName:FONTBOLD(9)};
                [attributeNumStr addAttributes:attributeNumDic1 range:NSMakeRange(desNumText.length-1,1)];
                [attributeNumStr addAttribute:NSForegroundColorAttributeName value:self.desColor range:NSMakeRange(0,desNumText.length)];
                CGFloat desN_X = secondP.x + 3; // secondP.x + 3
                CGFloat desN_Y = secondP.y - sizeNum.height - 3; // secondP.y - size.height / 2
                [attributeNumStr drawInRect:CGRectMake(desN_X, desN_Y, sizeNum.width, sizeNum.height)];
            }
            
        }
        [self drawLineWithContext:contex andStarPoint:endx andEndPoint:secondP andIsDottedLine:NO andColor:color];
        [self drawPointWithRedius:3*k_Width_Scale andColor:color andPoint:secondP andContext:contex];
        
    }
}

部分方法实现

//触摸事件处理
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //不能点击则不做处理了
    if (!self.canClick) {
        return;
    }
    CGPoint touchPoint = [[touches anyObject] locationInView:self];
    for (CustomShapeLayer *shapeLayer in pieShapeLayerArray) {
        //如果只有一个模块,那么动画就要变化了,不是简单的偏移了
        if (self.valueDataArr.count == 1) {
            shapeLayer.isOneSection = YES;
        }
        //判断选择区域
        shapeLayer.clickOffset =  [self preferGetUserSetValue:self.clickOffsetSpace withDefaultValue:15];
        if (CGPathContainsPoint(shapeLayer.path, 0, touchPoint, YES)) {
            //修改选中状态
            if (shapeLayer.isSelected) {
                shapeLayer.isSelected = NO;
            }else{
                shapeLayer.isSelected = YES;
            }
            NSInteger index = [pieShapeLayerArray indexOfObject:shapeLayer];
            if (shapeLayer.isSelected) {
                self.isExpand = YES;
            }else{
                self.isExpand = NO;
            }
            if (self.clickBlock) {
                self.clickBlock(index,self.isExpand);
            }
            NSLog(@"点击了第几个 --- %zd\n选中 --- %d",index,self.isExpand);
        } else {
            shapeLayer.isSelected = NO;
        }
    }
}
//点击处理
-(void)setIsSelected:(BOOL)isSelected
{
    _isSelected = isSelected;
    CGPoint newCenterPoint = _centerPoint;
    CGFloat offset = [self preferGetUserSetValue:self.clickOffset withDefaultValue:15];

    if (self.isOneSection) {
        [self dealOneSectionWithSelected:isSelected withOffset:offset];
        return;
    }
    
    if (isSelected) {
        //center 往外围移动一点 使用cosf跟sinf函数
        newCenterPoint = CGPointMake(_centerPoint.x + cosf((_startAngle + _endAngle) / 2) * offset, _centerPoint.y + sinf((_startAngle + _endAngle) / 2) * offset);
    }
    //创建一个path
    UIBezierPath *path = [UIBezierPath bezierPath];
    //起始中心点改一下
    [path moveToPoint:newCenterPoint];
    [path addArcWithCenter:newCenterPoint radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    [path addArcWithCenter:newCenterPoint radius:_innerRadius startAngle:_endAngle endAngle:_startAngle clockwise:NO];
    [path closePath];
    self.path = path.CGPath;
    
    //添加动画
    CABasicAnimation *animation = [CABasicAnimation animation];
    //keyPath内容是对象的哪个属性需要动画
    animation.keyPath = @"path";
    //所改变属性的结束时的值
    animation.toValue = path;
    //动画时长
    animation.duration = 0.25;
    //添加动画
    [self addAnimation:animation forKey:nil];
    
}

//单个圆饼的处理
- (void)dealOneSectionWithSelected:(BOOL)isSelected withOffset:(CGFloat)offset
{
    //创建一个path
    UIBezierPath *originPath = [UIBezierPath bezierPath];
    //起始中心点改一下
    [originPath moveToPoint:_centerPoint];
    [originPath addArcWithCenter:_centerPoint radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    [originPath addArcWithCenter:_centerPoint radius:_innerRadius startAngle:_endAngle endAngle:_startAngle clockwise:NO];
    [originPath closePath];
    
    //再创建一个path
    UIBezierPath *path = [UIBezierPath bezierPath]; // 把圆放大就行了;
    //起始中心点改一下
    [path moveToPoint:_centerPoint];
    [path addArcWithCenter:_centerPoint radius:_radius+offset startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    [path addArcWithCenter:_centerPoint radius:_innerRadius startAngle:_endAngle endAngle:_startAngle clockwise:NO];
    [path closePath];
    
    if (!isSelected) {
        self.path = originPath.CGPath;
        //添加动画
        CABasicAnimation *animation = [CABasicAnimation animation];
        //keyPath内容是对象的哪个属性需要动画
        animation.keyPath = @"path";
        animation.fromValue = path;
        //所改变属性的结束时的值
        animation.toValue = originPath;
        //动画时长
        animation.duration = 0.25;
        //添加动画
        [self addAnimation:animation forKey:nil];
    }else{
        self.path = path.CGPath;
        //添加动画
        CABasicAnimation *animation = [CABasicAnimation animation];
        //keyPath内容是对象的哪个属性需要动画
        animation.keyPath = @"path";
        animation.fromValue = originPath;
        //所改变属性的结束时的值
        animation.toValue = path;
        //动画时长
        animation.duration = 0.25;
        //添加动画
        [self addAnimation:animation forKey:nil];
    }

}
//绘制直线或虚线
- (void)drawLineWithContext:(CGContextRef )context andStarPoint:(CGPoint )start andEndPoint:(CGPoint)end andIsDottedLine:(BOOL)isDotted andColor:(UIColor *)color{
    CGContextMoveToPoint(context, start.x, start.y);
    CGContextAddLineToPoint(context, end.x, end.y);
    CGContextSetLineWidth(context, 0.3);
    [color setStroke];
    if (isDotted) {
        CGFloat ss[] = {1.5,2};
        CGContextSetLineDash(context, 0, ss, 2);
    }
    CGContextMoveToPoint(context, end.x, end.y);
    CGContextDrawPath(context, kCGPathStroke);
}
//绘制圆圈
- (void)drawPointWithRedius:(CGFloat)redius andColor:(UIColor *)color andPoint:(CGPoint)p andContext:(CGContextRef)contex{
    CGContextAddArc(contex, p.x, p.y, redius, 0, M_PI * 2, YES);
    [color setFill];
    CGContextDrawPath(contex, kCGPathFill);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值