美文网首页程序员
简单实现扇形图表

简单实现扇形图表

作者: 一誠 | 来源:发表于2017-12-07 18:18 被阅读163次

    Demo地址

    主要代码

    1、遍历所有扇形的比例,计算出每个扇形区域的开始和结束角度,然后绘制FanShapeLayer

    int max = 0;
        for (NSNumber * obj in self.angles) {
            max += [obj intValue];
        }
        
        CGFloat startAngle = self.startAngle;// 起点 0 代表x轴正方向
        
        for (int i = 0; i < self.angles.count; i ++) {
            NSNumber * obj = [self.angles objectAtIndex:i];
            
            CGFloat rate = [obj intValue];
            CGFloat angle = rate / max * M_PI * 2.0;
            
            // 计算绘制角度-终点 绘制的角度 绘制的方向是逆时针的所以是减
            CGFloat endAngle = startAngle - angle;
            
            // 设置颜色
            UIColor * color = randomColor;
            
            // 创建FanShapeLayer
            FanShapeLayer * layer = [[FanShapeLayer alloc]init];
            layer.fillColor = color.CGColor;
            layer.name = [NSString stringWithFormat:@"图层 = %d",i];
            layer.startAngle = startAngle;
            layer.endAngle = endAngle;
            layer.radius = self.radius;
            layer.centerPoint = self.chartPoint;
            // 绘制路径(先设置参数)
            [layer drawPath];
            [self.layer addSublayer:layer];
            [self.fansArray addObject:layer];
            
            // 计算下一次绘制起点
            startAngle -= angle;
        }
    

    2、在设置FanShapeLayer的参数后,先绘制CGMutablePathRef即一个封闭的扇形,然后把CGMutablePathRef赋给FanShapeLayer

    CGMutablePathRef path = CGPathCreateMutable();
        CGAffineTransform transform = CGAffineTransformMakeTranslation(1, 1);
        CGPathMoveToPoint(path, &transform, self.centerPoint.x, self.centerPoint.y);
        CGPathAddArc(path, &transform, self.centerPoint.x, self.centerPoint.y, radius, self.startAngle, self.endAngle, YES);
        CGPathCloseSubpath(path);
    

    3、主要是点击放大,CALyer是不响应点击事件的,这里是通过获得触摸对象的点是否在layer区域内实现的。

    网上查到可以通过下面方法获得点击的图层,但这里得到的是nil,不知道为什么。
    CALayer * layer = [self.layer hitTest:point];

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        // 获取点击的中心点
        UITouch * touch = [touches anyObject];
        CGPoint point = [touch locationInView:self];
        // 获取点击区域 是否包含的CAShapeLayer
        FanShapeLayer * layer = [self touchLayer:point];
        if (layer) {
            NSLog(@"%@", layer.name);
            // 设置选中的为未选中
            NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isSelected = YES"];
            NSArray * selectArray = [self.fansArray filteredArrayUsingPredicate:predicate];
            [selectArray makeObjectsPerformSelector:@selector(setIsSelected:) withObject:@NO];
            if ([selectArray containsObject:layer]) {
                return ;
            }
            // 添加动画
            layer.isSelected = YES;
        }
    }
    
    - (FanShapeLayer *)touchLayer:(CGPoint)point{
        // 获取点击的区域layer
        for (FanShapeLayer * layer in self.fansArray) {
            // 获取inPoint,在layer中的坐标
            CGPoint inPoint = [layer convertPoint:point fromLayer:self.layer];
            
            if (CGPathContainsPoint(layer.path, 0, inPoint, YES)) {
                return layer;
            }
        }
        return nil;
    }
    

    4、最后在点击的时候添加缩放动画

      // 添加动画
            CABasicAnimation *animation = [CABasicAnimation animation];
            // keyPath内容是对象的哪个属性需要动画
            animation.keyPath = @"path";
            // 设置代理
            animation.delegate = self;
            // 所改变属性的结束时的值
            animation.toValue = (__bridge id _Nullable)(self.endPath);
            // 动画时长
            animation.duration = 0.25;
            // 结束后不移除
            animation.removedOnCompletion = NO;
            animation.fillMode = kCAFillModeForwards;
            // 添加动画
            [self addAnimation:animation forKey:nil];
    

    相关文章

      网友评论

        本文标题:简单实现扇形图表

        本文链接:https://www.haomeiwen.com/subject/dhdjixtx.html