iOS-贝塞尔曲线之自定义饼图
项目中需要统计数据展现, 采用了饼图形式展现.
第一步: 了解下贝塞尔曲线相关概念
贝塞尔曲线相关概念:
UIBezierPath
:画贝塞尔曲线的path类
UIBezierPath定义
: 贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度。
曲线的定义有四个点
:起始点、终止点(也称锚点)以及两个相互分离的中间点。
滑动两个中间点
,贝塞尔曲线的形状会发生变化。
UIBezierPath
:对象是CGPathRef数据类型的封装,可以方便的让我们画出矩形 、 椭圆 或者 直线和曲线的组合形状.
使用贝塞尔曲线的基本步骤:
(1)创建一个Bezier path对象。
(2)使用方法moveToPoint:去设置初始线段的起点。
(3)添加line或者curve去定义一个或者多个subpaths。
(4)改变UIBezierPath对象跟绘图相关的属性。
初始化方法:
+ (instancetype)bezierPath;
创建一个矩形:
+ (instancetype)bezierPathWithRect:(CGRect)rect;
创建圆形或者椭圆形:
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
最基本的使用方法是:
// 设置描绘的起点
- (void)moveToPoint:(CGPoint)point;
// 画直线
- (void)addLineToPoint:(CGPoint)point;
// 画曲线
// a.绘制二次贝塞尔曲线 分别对应终点和一个控制点
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
// b.绘制三次贝塞尔曲线 分别对应终点和两个控制点
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
// 画圆弧
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
第二步: 自定义饼图实现相关代码
自定义饼图:
针对上面的饼图, 实现主要思路:
1.初始化画布
2.bezierPath形成闭合的扇形路径
3.自定义饼图填充颜色
4.饼图的引出点及指引线
5.画引出直线
6.添加饼图相对应提示文字
7.空心展示饼图
8.露出方法,在所需控制器里调用即可
1. 初始化画布
+ (instancetype)initWithFrame:(CGRect)frame {
ZLBezierPieView *bezierCurveView = [[NSBundle mainBundle] loadNibNamed:@"ZLBezierPieView" owner:self options:nil].lastObject;
bezierCurveView.frame = frame;
//背景视图
UIView *backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
backView.backgroundColor = [UIColor clearColor];
[bezierCurveView addSubview:backView];
myFrame = frame;
return bezierCurveView;
}
2. bezierPath形成闭合的扇形路径
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithArcCenter:point
radius:radius
startAngle:startAngle endAngle:endAngle
clockwise:YES];
[bezierPath addLineToPoint:point];
[bezierPath closePath];
3. 自定义饼图填充颜色
// 可自定义饼图填充颜色(根据自己需求添加)
NSArray *redArray = @[@"46",@"255",@"62",@"254",@"253",@"153",@"110", @"173",@"223",@"196"];
NSArray *greenArray = @[@"191",@"48",@"209",@"199",@"109",@"208",@"123", @"110",@"142",@"193"];
NSArray *blueArray = @[@"238",@"145",@"185",@"17",@"31",@"60",@"254", @"157",@"36",@"48"];
// 填充色
UIColor *customColor = [UIColor colorWithRed:[[redArray objectAtIndex:i] intValue]/255.0 green:[[greenArray objectAtIndex:i] intValue]/255.0 blue:[[blueArray objectAtIndex:i] intValue]/255.0 alpha:1];
// 渲染
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.lineWidth = 1;
// 填充色
shapeLayer.fillColor = customColor.CGColor;
shapeLayer.path = bezierPath.CGPath;
[self.layer addSublayer:shapeLayer];
4. 饼图的引出点及指引线
// 饼图引出点
CGFloat pieX = point.x + (radius)*cos(startAngle+(endAngle-startAngle)/2);
CGFloat pieY = point.y + (radius)*sin(startAngle+(endAngle-startAngle)/2);
// 指引线引出点
CGFloat X = point.x + (radius+20)*cos(startAngle+(endAngle-startAngle)/2);
CGFloat Y = point.y + (radius+20)*sin(startAngle+(endAngle-startAngle)/2);
CGFloat lineWidth = 80;
// 绘制小圆点
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.frame = CGRectMake(0, 0, 1, 1); // 指定frame,只是为了设置宽度和高度
circleLayer.position = CGPointMake(X, Y); // 设置居中显示
circleLayer.fillColor = [UIColor clearColor].CGColor; // 设置填充颜色
circleLayer.lineWidth = 2.0;
circleLayer.strokeColor = customColor.CGColor;
// 使用UIBezierPath创建路径
CGRect frame = CGRectMake(0, 0, 2, 2);
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
// 设置CAShapeLayer与UIBezierPath关联
circleLayer.path = circlePath.CGPath;
// 将CAShaperLayer放到某个层上显示
[self.layer addSublayer:circleLayer];
5. 画引出直线
// 画第一段直线
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.frame = CGRectMake(0, 0, 1, 1); // 指定frame,只是为了设置宽度和高度
lineLayer.fillColor = [UIColor clearColor].CGColor; // 设置填充颜色
lineLayer.lineWidth = 1.0;
lineLayer.strokeColor = customColor.CGColor;
UIBezierPath *indicatrixLine = [UIBezierPath bezierPath];
[indicatrixLine moveToPoint:CGPointMake(pieX, pieY)];
[indicatrixLine addLineToPoint:CGPointMake(X, Y)];
lineLayer.path = indicatrixLine.CGPath;
lineLayer.lineWidth = 1.0;
lineLayer.strokeColor = customColor.CGColor;
[self.layer addSublayer:lineLayer];
if (X < point.x) { // 饼图左侧
X = X - lineWidth;
}
// 添加指引线(第二段直线)
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(X, Y, lineWidth, 1)];
line.backgroundColor = customColor;
[self.subviews[0] addSubview:line];
6. 添加饼图相对应提示文字
// 添加文字
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(X, Y - 15, lineWidth, 30)];
label.font = [UIFont systemFontOfSize:13];
label.textColor = customColor;
label.numberOfLines = 0;
label.text = type_names[i];
label.attributedText = [self setupAttriLabelWithTitleStr:type_names[i] ValueStr:[NSString stringWithFormat:@"%@", targetValues[i]]];
[self.subviews[0] addSubview:label];
if (X < point.x) { // 饼图左侧
label.textAlignment = NSTextAlignmentLeft;
} else {
label.textAlignment = NSTextAlignmentRight;
}
/**
* label 的富文本布局
*
* titleStr 标题
* ValueStr 值
*/
- (NSMutableAttributedString *)setupAttriLabelWithTitleStr:(NSString *)titleStr ValueStr:(NSString *)valueStr {
NSMutableAttributedString *string = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"%@\n%@", titleStr, valueStr]];
[string addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:12] range:NSMakeRange(titleStr.length+1, valueStr.length)];
return string;
}
7. 空心展示饼图
// 画一个圆, 用来空心(如果满圆则可以不要这块)
UIBezierPath *radiusPath = [UIBezierPath bezierPathWithArcCenter:point radius:radius * 0.3 startAngle:0 endAngle:2*M_PI clockwise:YES];
[radiusPath addLineToPoint:point];
[radiusPath closePath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.lineWidth = 1;
shapeLayer.fillColor = [UIColor whiteColor].CGColor;
shapeLayer.path = radiusPath.CGPath;
[self.layer addSublayer:shapeLayer];
8. 露出方法,在所需控制器里调用即可
/**
* 画饼状图
* @param type_names 分类名称值
* @param targetValues 所有目标值
*/
- (void)drawPieChartViewWithType_Names:(NSMutableArray *)type_names TargetValues:(NSMutableArray *)targetValues;
初始化:
// 饼图相关
@property (strong, nonatomic) ZLBezierPieView *pieChartView;
@property (strong, nonatomic) NSMutableArray *type_names; // 类型名称
@property (strong, nonatomic) NSMutableArray *type_values; // 数据值
懒加载:
#pragma mark - 懒加载
// 饼图类型名称
- (NSMutableArray *)type_names {
if (!_type_names) {
_type_names = [NSMutableArray array];
_type_names = [NSMutableArray arrayWithArray:@[@"主粮系列",@"零食世界",@"益智玩具",@"衣服狗窝",@"保健医用",@"活体",@"日用系列"]];
}
return _type_names;
}
// 饼图类型数据
- (NSMutableArray *)type_values {
if (!_type_values) {
_type_values = [NSMutableArray array];
_type_values = [NSMutableArray arrayWithArray:@[@"100",@"100",@"100",@"200",@"200",@"100",@"200"]];
}
return _type_values;
}
饼图画布初始化:
// 饼图画布初始化
_pieChartView = [ZLBezierPieView initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 250)];
_pieChartView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_pieChartView];
// 饼图
[_pieChartView drawPieChartViewWithType_Names:self.type_names TargetValues:self.type_values];
第三步: 项目截图及运行效果截图
项目截图:
运行效果截图:
界面性问题可以根据自己项目需求调整即可, 具体可参考代码, 项目能够直接运行!iOS-贝塞尔曲线之自定义饼图
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
iOS-贝塞尔曲线之自定义饼图的更多相关文章
- iOS贝塞尔曲线(UIBezierPath)的基本使用方法
简介 UIBezierPath是对Core Graphics框架的一个封装,使用UIBezierPath类我们可以画出圆形(弧线)或者多边形(比如:矩形)等形状,所以在画复杂图形的时候会经常用到. 分 ...
- UIBezierPath IOS贝塞尔曲线
//记录 贝塞尔曲线使用 //根据一个矩形画曲线 + (UIBezierPath *)bezierPathWithRect:(CGRect)rect //根据矩形框的内切圆画曲线 + (UIBezi ...
- IOS贝塞尔曲线圆形进度条和加载动画
做项目让做一个加载动画,一个圈圈在转中间加一个图片,网上有好多demo,这里我也自己写了一个,中间的图片可加可不加.其中主要用到贝塞尔曲线.UIBezierPath是对CGContextRef的进一步 ...
- IOS 贝塞尔曲线切割圆角
写一个UIView扩展 1. .h文件 @interface UIView (Corner) - (void)setCornerWithType:(UIRectCorner)type Radius:( ...
- iOS - 贝塞尔曲线,折线,曲线,波浪线
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZHlsYW5fbHdiXw==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- iOS开发 贝塞尔曲线
iOS开发 贝塞尔曲线UIBezierPath - 陌云 时间 2014-03-14 11:04:00 博客园-所有随笔区 原文 http://www.cnblogs.com/moyunmo/p/ ...
- iOS开发 贝塞尔曲线UIBezierPath
最近项目中需要用到用贝塞尔曲线去绘制路径 ,然后往路径里面填充图片,找到这篇文章挺好,记录下来 自己学习! 转至 http://blog.csdn.net/guo_hongjun1611/articl ...
- Unity3d游戏中自定义贝塞尔曲线编辑器[转]
关于贝塞尔曲线曲线我们再前面的文章提到过<Unity 教程之-在Unity3d中使用贝塞尔曲线>,那么本篇文章我们来深入学习下,并自定义实现贝塞尔曲线编辑器,贝塞尔曲线是最基本的曲线,一般 ...
- IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
... 首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Con ...
随机推荐
- [BZOJ4537][Hnoi2016]最小公倍数 奇怪的分块+可撤销并查集
4537: [Hnoi2016]最小公倍数 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1474 Solved: 521[Submit][Stat ...
- 通俗了解TCP/IP三次握手四次挥手
前言: tcp/ip通信机制是计算机中很重要的一个知识点,不是一句两句就能解释清楚的,需要反复推敲其中的玄妙. 通俗理解: 但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我 ...
- CF 1003C Intense Heat【前缀和/精度/双层暴力枚举】
The heat during the last few days has been really intense. Scientists from all over the Berland stud ...
- KMP+差分 文章过滤器 (filter)
Description 给定一些短串,要求你在一个长串中,将这些短串部分变为\(*\) Input 第一行包括一个整数\(n\),表示短串的数量. 接下来的\(n\)行,为\(n\)个短串. 最后一行 ...
- Linux命令之umount
umount [-hV] umount -a [-dflnrv] [-t vfstype] [-O option] umount [-dflnrv] {dir|device} [-t vfstype] ...
- Oracle alter table modify column Syntax example
http://www.dba-oracle.com/t_alter_table_modify_column_syntax_example.htm For complete tips on Oracle ...
- CentOS 7.1 中文正式版下载 - 最流行的免费开源企业级 Linux 服务器操作系统
如果说 Ubuntu 是现今最受桌面用户欢迎的 Linux 操作系统,那么 CentOS 就是最受公司.企业.IDC 喜爱的 Linux 发行版了.得益于极为出色的稳定性,全球范围内无数著名网站均选用 ...
- 【分块】【线段树】bzoj3212 Pku3468 A Simple Problem with Integers
线段树入门题…… 因为poj原来的代码莫名RE,所以丧病地写了区间修改的分块…… 其实就是块上打标记,没有上传下传之类. #include<cstdio> #include<cmat ...
- 杂谈PID控制算法——最终篇:C语言实现51单片机中的PID算法
真遗憾,第二篇章没能够发表到首页上去.趁热打铁.把最终篇——代码篇给发上来. 代码的设计思想请移步前两篇文章 //pid.h #ifndef __PID__ #define __PID__ /*PID ...
- Metesploit使用随笔
平时在工作中真正用到metesploit机会不多,偶尔也会用来做漏洞验证,但是每次使用的时候都需要花点时间回忆一下具体是怎么用的,因此索性记下来方便自己,以使用Nessus扫描YS的某个硬件设备发现的 ...