iOS开发示例————使用CAShapeLayer&UIBezierPath绘制数据饼图
2016-06-02 10:17
519 查看
前言借鉴标哥的博客部分文章: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
#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];
}
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];
}
相关文章推荐
- Gifski:一个跨平台的高质量 GIF 编码器
- 模仿动画的放大缩小容器
- jQuery 1.9.1源码分析系列(十五)动画处理之缓动动画核心Tween
- Android实现定制返回按钮动画效果的方法
- Android中ViewFlipper的使用及设置动画效果实例详解
- jQuery实现美观的多级动画效果菜单代码
- C#实现图形位置组合转换的方法
- php判断GIF图片是否为动画的方法
- C#实现判断图形文件格式的方法
- C#实现图形路径变换的方法
- jQuery实现动画效果circle实例
- HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
- 浅析JavaScript动画
- js排序动画模拟-插入排序
- javascript+HTML5的Canvas实现Lab单车动画效果
- 基于javascript实现漂亮的页面过渡动画效果附源码下载
- js实现按钮颜色渐变动画效果
- 超赞的jQuery图片滑块动画特效代码汇总
- jQuery实现连续动画效果实例分析
- 利用jquery制作滚动到指定位置触发动画