iOS开发示例————使用CAShapeLayer&UIBezierPath绘制数据饼图

原创 2016年06月02日 10:17:40

前言借鉴标哥的博客部分文章:http://www.henishuo.com/ios-cashapelayer-learning/

CAShapeLayer和drawRect的比较:


drawRect:属于CoreGraphics框架,占用CPU,性能消耗大,不建议重写
CAShapeLayer:属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存,这两者各有各的用途,而不是说有了CAShapeLayer就不需要drawRect。

温馨提示:drawRect只是一个方法而已,是UIView的方法,重写此方法可以完成我们的绘制图形功能。

CAShapeLayer与UIBezierPath的关系:

CAShapeLayer中shape代表形状的意思,所以需要形状才能生效
贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装
贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape,用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线


示例简介:

在饼图上显示数组中几个数据各占有的百分比,SliceLayer是CAShapeLayer的子类,用于构造饼图的各个扇面和选中某扇面的动画效果,PieChart是UIView的子类,用于根据数组的数据情况来设置饼图的各个扇面和触摸方法,最后在VC中调用即可。


示例代码:

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface SliceLayer : CAShapeLayer

@property (nonatomic, assign) CGFloat startAngle;
@property (nonatomic, assign) CGFloat endAngle;
@property (nonatomic, assign) CGPoint centerPoint;
@property (nonatomic, assign) CGFloat radius;
@property (nonatomic, assign) BOOL selected;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, assign) NSInteger tag;

- (void)create;

@end

#define RandomColor [UIColor colorWithRed:arc4random() % 255 / 255.0 green:arc4random() % 255 / 255.0 blue:arc4random() % 255 / 255.0 alpha:1.0]

#import "SliceLayer.h"

@implementation SliceLayer

- (void)create {
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:_centerPoint];
    [path addArcWithCenter:_centerPoint radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    [path closePath];
    self.path = path.CGPath;
    self.strokeColor = [UIColor cyanColor].CGColor;
    self.fillColor = RandomColor.CGColor;
}

- (void)setSelected:(BOOL)selected {
    _selected = selected;
    CGPoint newCenterPoint = _centerPoint;
    if (selected) {
        newCenterPoint = CGPointMake(_centerPoint.x + cosf((_startAngle + _endAngle) / 2) * 30, _centerPoint.y + sinf((_startAngle + _endAngle) / 2) * 30);
    }
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:newCenterPoint];
    [path addArcWithCenter:newCenterPoint radius:_radius startAngle:_startAngle endAngle:_endAngle clockwise:YES];
    [path closePath];
    self.path = path.CGPath;
    
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.keyPath = @"path";
    animation.toValue = path;
    animation.duration = 0.5;
    [self addAnimation:animation forKey:nil];
}

@end

#import <UIKit/UIKit.h>
//typedef void(^MyBlock)(CGFloat);

@interface PieChart : UIView

@property (nonatomic, strong) NSArray *datas;
@property (nonatomic, strong) NSMutableArray *sliceLayerArray;
//@property (nonatomic, strong) MyBlock angleBlock;

@end

#import "PieChart.h"
#import "SliceLayer.h"

@implementation PieChart {
    CGFloat percentage;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.sliceLayerArray = @[].mutableCopy;
    }
    return self;
}

- (void)setDatas:(NSArray *)datas {
    _datas = datas;
    CGFloat startAngle = 0;
    CGFloat endAngle = 0;
    for (int i = 0; i < datas.count; i++) {
        percentage = [datas[i] floatValue];
        CGFloat angle = percentage * M_PI * 2;
        endAngle = angle + startAngle;
        
        SliceLayer *sliceLayer = [[SliceLayer alloc] init];
        sliceLayer.startAngle = startAngle;
        sliceLayer.endAngle = endAngle;
        sliceLayer.radius = 100.0f;
        sliceLayer.centerPoint = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
        sliceLayer.tag = i;
        [sliceLayer create];
        [self.layer addSublayer:sliceLayer];
        [self.sliceLayerArray addObject:sliceLayer];
        
        CATextLayer *textLayer = [CATextLayer layer];
        textLayer.frame = CGRectMake(sliceLayer.centerPoint.x + cosf((startAngle + endAngle) / 2) * 50 - 15, sliceLayer.centerPoint.y + sinf((startAngle + endAngle) / 2) * 50 - 10, 40, 20);
        textLayer.string = [NSString stringWithFormat:@"%1.f%%", percentage * 100];
        textLayer.fontSize = 17;
        textLayer.contentsScale = 2;
        
        [sliceLayer addSublayer:textLayer];
        
        startAngle = endAngle;
        
    }
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    CGPoint touchPoint = [[touches anyObject] locationInView:self];
    for (SliceLayer *slice in _sliceLayerArray) {
        //判断选择区域
        if (CGPathContainsPoint(slice.path, 0, touchPoint, YES)) {
            slice.selected = YES;
//            self.angleBlock((slice.endAngle - slice.startAngle) / 2 / M_PI);
        } else {
            slice.selected = NO;
        }
    }
}

#import "ViewController.h"
#import "PieChart.h"
@class PieChart;

@interface ViewController () {
    CAShapeLayer *shapeLayer;
    NSTimer *timer;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor blackColor];
    
    PieChart *pieChart = [[PieChart alloc] initWithFrame:self.view.bounds];
    pieChart.datas = @[@0.1, @0.2, @0.3, @0.25, @0.1, @0.05];
    pieChart.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:pieChart];
}


IOS之以UIBezierPath绘制饼状图

1.绘制bing'zhu
  • xyybaozhen
  • xyybaozhen
  • 2014年10月27日 10:07
  • 3428

UIBezierPath + CAShapeLayer (弧形 + 线条)

最近又再次 折腾了一下   UIBezierPath + CAShapeLayer 绘图。 图形是这样的    (灰色部分)。 然后有人建议 找美工切图,然后我感觉这个 应该可以 绘图出来, 毕竟能不...
  • liwenjie0912
  • liwenjie0912
  • 2015年08月29日 12:04
  • 2412

ios饼图

AppDelegate默认ViewController.h默认ViewController.m#import "ViewController.h" #import "KMView.h"@interfa...
  • dujianjunqwer
  • dujianjunqwer
  • 2017年12月28日 14:21
  • 35

iOS使用Charts框架绘制—饼状图

首先先看一下效果: 饼状图 一、创建饼状图对象 创建饼状图对象用到类是PieChartView.h, 代码如下: self.pieChartView = [[PieChartView ...
  • qq_30513483
  • qq_30513483
  • 2016年06月16日 19:15
  • 6095

ios 程序绘制饼图的demo

  • 2013年06月21日 14:36
  • 718KB
  • 下载

iOS绘图 - 自定义饼图的绘制

如何画一个饼图, 来实现数据展示的可视化PieChartView.h #import @interface PieChartView : UIView@end PieChartView.m #impo...
  • chinnyman
  • chinnyman
  • 2016年04月07日 14:29
  • 1436

使用CAShapeLayer与UIBezierPath画动态柱状图

// // TextView.m // 练习 // // Created by 王文杰 on 16/9/20. // Copyright © 2016年 王文杰. All rights res...
  • qq_26362407
  • qq_26362407
  • 2016年09月22日 08:37
  • 601

柱状图的实现

在实现柱状图的过程中,主要是用到了UIBezierPath和CAShapeLayer 1、新建UIBezierPath对象bezierPath 2、新建CAShapeLayer对象caShap...
  • u012927973
  • u012927973
  • 2016年08月05日 16:53
  • 392

iOS饼状图实现

饼状图实现1.基于画圆 1.每一个扇形的起始值和结束值确定就可以实现 2.其它注意点,用不同的颜色充满各个所占的区域 3.效果图 2.代码简单的说明“`objcpragma mark - drawAr...
  • u011252234
  • u011252234
  • 2016年06月28日 09:35
  • 1174

iOS实现折线图、柱状图、圆饼图

iOS常用的折线图、柱状图、 饼状图、环形图,其中折线图、柱状图支持tap手势缩放、pan手势缩放。代码地址:https://github.com/Rochang/LCChartView...
  • Qqing__
  • Qqing__
  • 2017年10月23日 17:43
  • 281
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS开发示例————使用CAShapeLayer&UIBezierPath绘制数据饼图
举报原因:
原因补充:

(最多只允许输入30个字)