iOS绘制收益柱状图
项目需求,参考了其他绘图demo,自己绘制出来了,不过代码改得有点乱,添加了很多变量,时间关系没用太合适的命名,逻辑处理也没进行优化。
看看效果图(虚线区域都是画的,其他区域添加的都是控件),附上源码




#import <UIKit/UIKit.h>
typedef enum : NSUInteger {
CSYieldTypeWeek = 0, //周收益
CSYieldTypeMonth = 1, //月收益
CSYieldTypeYear = 2, //年收益
} CSYieldType; //收益类型
typedef enum : NSUInteger {
CSTimePointJanuary = 0, //一月份
CSTimePointFebruary,
CSTimePointMarch,
CSTimePointApril,
CSTimePointMay, //.
CSTimePointJun, //.
CSTimePointJuly, //.
CSTimePointAugust,
CSTimePointSeptember,
CSTimePointOctober,
CSTimePointNovember,
CSTimePointDecember, //十二月份
CSTimePointThisWeek, //本周
CSTimePointLastWeek, //上周
} CSTimePoint;
@interface CSYieldChartView : UIView
@property (nonatomic,assign)CSYieldType yieldType; //收益类型
@property (nonatomic,assign)CSTimePoint timePoint; //时间点
@property (nonatomic,strong) NSArray *yields; //收益数组
@property (nonatomic,strong) NSArray *dayPoints; //时间点数组
//刷新图表
- (void)refreshChartWithYields:(NSArray *)yields dayPoints:(NSArray *)dayPoints yieldType:(CSYieldType)yieldType timePoint:(CSTimePoint)timePoint;
@end
#define yieldLineSpace 4
#define lineLeftMargin 40
#define lineRightMargin 10
#define lineTopMargin 10
#define lineBottomMargin 30
#define lineWidth 0.5f
#define itemLeftMargin 16
#define itemRightMargin 16
#define itemSpace 6
#define itemWidthRatio (5/12.f)
#define positiveItemHexColor 0xe83846 //正收益条颜色值
#define negativeItemHexColor 0x17c7ba //负收益条颜色值
#import "CSYieldChartView.h"
#import "UIColor+Addition.h"
@implementation CSYieldChartView
-(void)refreshChartWithYields:(NSArray *)yields dayPoints:(NSArray *)dayPoints yieldType:(CSYieldType)yieldType timePoint:(CSTimePoint)timePoint
{
self.yields = yields;
self.dayPoints = dayPoints;
self.yieldType = yieldType;
self.timePoint = timePoint;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
//声明最大的收益
float maxYield = 0;
//获取最大的收益绝对值
for (NSNumber *number in _yields) {
if (maxYield < fabs([number floatValue])) {
maxYield = fabs([number floatValue]);
}
}
//若最大收益少于10,则将最大值设为10
if (maxYield < 10.0) {
maxYield = 10.0;
}
//分几段
NSInteger sectionNum = 2;
//平均每段的收益
CGFloat sectionYield = maxYield / 2;
UIColor *currentColor = [UIColor lightGrayColor];
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextBeginPath(contextRef);
CGContextSetLineWidth(contextRef, lineWidth); //设置线粗
CGContextSetStrokeColorWithColor(contextRef, currentColor.CGColor); //设置画笔颜色
//中线的y坐标
CGFloat centerLineY = (self.frame.size.height - lineTopMargin - lineBottomMargin)/2.f + lineTopMargin;
//设置段落风格
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.alignment = NSTextAlignmentRight;
//设置字体颜色
UIColor *textColor = [UIColor lightGrayColor];
//设置字体大小
UIFont *textFont = [UIFont systemFontOfSize:10];
//0收益中线
CGContextMoveToPoint(contextRef, lineLeftMargin, centerLineY);
CGContextAddLineToPoint(contextRef, self.frame.size.width - lineRightMargin, centerLineY);
CGContextStrokePath(contextRef);
//0收益率
[@"0%" drawInRect:CGRectMake(0, centerLineY - 7, lineLeftMargin - yieldLineSpace, lineLeftMargin) withAttributes:@{NSParagraphStyleAttributeName:paragraph,NSForegroundColorAttributeName:textColor,NSFontAttributeName:textFont}];
//线与线的垂直距离
CGFloat lineSpace = (self.frame.size.height - lineTopMargin - lineBottomMargin) / 4.f;
for (int i = 0; i < sectionNum; i++) {
CGFloat topLineY = centerLineY - lineSpace * (i + 1);
CGFloat bottomLineY = centerLineY + lineSpace * (i + 1);
//虚线 线宽与空格宽
CGFloat dashes[] = {2,1};
CGContextSetLineDash(contextRef, 0.0, dashes, 2);
CGContextSetStrokeColorWithColor(contextRef, currentColor.CGColor); //设置画笔颜色
//中线以上
CGContextMoveToPoint(contextRef, lineLeftMargin, topLineY);
CGContextAddLineToPoint(contextRef, self.frame.size.width - lineRightMargin, topLineY);
CGContextStrokePath(contextRef);
//收益率
[[NSString stringWithFormat:@"%.f%%",sectionYield * (i + 1)] drawInRect:CGRectMake(0, topLineY - 7, lineLeftMargin - yieldLineSpace, lineLeftMargin) withAttributes:@{NSParagraphStyleAttributeName:paragraph,NSForegroundColorAttributeName:textColor,NSFontAttributeName:textFont}];
CGContextSetStrokeColorWithColor(contextRef, currentColor.CGColor); //设置画笔颜色
//中线以下
CGContextMoveToPoint(contextRef, lineLeftMargin, bottomLineY);
CGContextAddLineToPoint(contextRef, self.frame.size.width - lineRightMargin, bottomLineY);
CGContextStrokePath(contextRef);
//负收益率
[[NSString stringWithFormat:@"-%.f%%",sectionYield * (i + 1)] drawInRect:CGRectMake(0, bottomLineY - 7, lineLeftMargin - yieldLineSpace, lineLeftMargin) withAttributes:@{NSParagraphStyleAttributeName:paragraph,NSForegroundColorAttributeName:textColor,NSFontAttributeName:textFont}];
}
if (0 == _yields.count) {
paragraph.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = @{NSParagraphStyleAttributeName:paragraph,NSForegroundColorAttributeName:textColor,NSFontAttributeName:[UIFont systemFontOfSize:40]};
CGSize textSize = [@"暂无数据" sizeWithAttributes:attributes];
[@"暂无数据" drawInRect:CGRectMake(lineLeftMargin + itemLeftMargin,centerLineY - textSize.height / 2.f,self.width - lineLeftMargin - itemLeftMargin - lineRightMargin - itemRightMargin,textSize.height) withAttributes:attributes];
return;
}
NSString *lastDay = [_dayPoints lastObject];
//最多有几个柱(如果是月收益,且收益数小于22,按22算,否则按收益数多少算)
NSInteger partNum = (_yields.count < 22 && _yieldType == CSYieldTypeMonth) ? 22 : _yields.count;
paragraph.alignment = NSTextAlignmentLeft;
//绘制柱状图
CGFloat averageSpace = (self.frame.size.width - lineLeftMargin - itemLeftMargin - lineRightMargin - itemRightMargin) / (partNum - 1);
//柱宽
CGFloat itemWidth = averageSpace * itemWidthRatio;
for (int i=0; i<partNum; i++) {
if (i > _yields.count - 1) //后面暂时还没收益就不画柱状条
{
break;
}
if (i % 5 == 0) {
//绘制日期
NSString *dayStr = nil;
if (self.yieldType == CSYieldTypeMonth && 0 == i) {
dayStr = [NSString stringWithFormat:@"%@(日)",_dayPoints[0]];
}
else
{
dayStr = [NSString stringWithFormat:@"%@",_dayPoints[i]];
}
[dayStr drawInRect:CGRectMake(lineLeftMargin + itemLeftMargin - 5 + averageSpace * i, self.frame.size.height - (lineBottomMargin - 6), 50, 15)withAttributes:@{NSParagraphStyleAttributeName:paragraph,NSForegroundColorAttributeName:textColor,NSFontAttributeName:textFont}];
}
else if (i == _yields.count - 1) //最后一个柱状图日期
{
[[NSString stringWithFormat:@"%@",lastDay] drawInRect:CGRectMake(lineLeftMargin + itemLeftMargin - 5 + averageSpace * i, self.frame.size.height - (lineBottomMargin - 6), 50, 15)withAttributes:@{NSParagraphStyleAttributeName:paragraph,NSForegroundColorAttributeName:textColor,NSFontAttributeName:textFont}];
}
//绘制柱状图
float yield = [_yields[i] floatValue];
float radius = itemWidth/2.f; //柱状末尾的半圆半径
//虚线 线宽与空格宽 (之前设了虚线,现在把虚线的间隙变为0)
CGFloat dashes[] = {1,0};
CGContextSetLineDash(contextRef, 0.0, dashes, 2);
CGFloat itemX = lineLeftMargin + itemLeftMargin + averageSpace * i - itemWidth/2.f;
CGFloat itemY = centerLineY - (lineSpace * sectionNum) * yield / maxYield;
//是否要画半圆(如果收益高度低于宽度,就不画半圆)
BOOL shouldDrawCircle = (fabs(itemY - centerLineY) > itemWidth/2.f) ? YES : NO;
if (yield >= 0) {
if (shouldDrawCircle) {
itemY += radius;
}
//正收益颜色
CGContextSetStrokeColorWithColor(contextRef, [UIColor colorWithHex:positiveItemHexColor].CGColor);
CGContextSetFillColorWithColor(contextRef, [UIColor colorWithHex:positiveItemHexColor].CGColor);
}
else
{
if (shouldDrawCircle) {
itemY -= radius;
}
//负收益颜色
CGContextSetStrokeColorWithColor(contextRef, [UIColor colorWithHex:negativeItemHexColor].CGColor);
CGContextSetFillColorWithColor(contextRef, [UIColor colorWithHex:negativeItemHexColor].CGColor);
}
// CGContextSetShadow(contextRef,CGSizeMake(2, 0) , 2); //阴影效果
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathMoveToPoint(pathRef, NULL, itemX, centerLineY);
CGPathAddLineToPoint(pathRef, NULL, itemX, itemY);
CGPathAddLineToPoint(pathRef, NULL, itemX + itemWidth, itemY);
CGPathAddLineToPoint(pathRef, NULL, itemX + itemWidth, centerLineY);
CGPathCloseSubpath(pathRef);
CGContextAddPath(contextRef, pathRef);
CGContextFillPath(contextRef);
CGContextAddPath(contextRef, pathRef);
CGContextStrokePath(contextRef);
if (shouldDrawCircle) {
//画线末圆角
CGPathMoveToPoint(pathRef, NULL, itemX + itemWidth/2.f, itemY);
if (yield >= 0) {
CGPathAddArc(pathRef, NULL, itemX + itemWidth/2.f, itemY, itemWidth/2.f, M_PI, 0, NO);
}
else
{
CGPathAddArc(pathRef, NULL, itemX + itemWidth/2.f, itemY, itemWidth/2.f, 0, M_PI, NO);
}
CGPathCloseSubpath(pathRef);
CGContextAddPath(contextRef, pathRef);
CGContextFillPath(contextRef);
CGContextAddPath(contextRef, pathRef);
CGContextStrokePath(contextRef);
}
}
}
@end
iOS绘制收益柱状图的更多相关文章
- C# 绘制统计图(柱状图, 折线图, 扇形图)【转载】
统计图形种类繁多, 有柱状图, 折线图, 扇形图等等, 而统计图形的绘制方法也有很多, 有Flash制作的统计图形, 有水晶报表生成统计图形, 有专门制图软件制作, 也有编程语言自己制作的:这里我们用 ...
- C# 绘制统计图(柱状图, 折线图, 扇形图)
统计图形种类繁多, 有柱状图, 折线图, 扇形图等等, 而统计图形的绘制方法也有很多, 有Flash制作的统计图形, 有水晶报表生成统计图形, 有专门制图软件制作, 也有编程语言自己制作的:这里我们用 ...
- ASP.NET Core +Highchart+ajax绘制动态柱状图
一.项目介绍利用前端Highchart,以及ajax向后台获取数据,绘制动态柱状图.hightchart其他实例可查看官网文档.[Highchart](https://www.highcharts.c ...
- echarts —— 绘制横向柱状图(圆角、无坐标轴)
UI给了设计图,看了一眼觉得简单,不就是无序列表布局嘛(ul,li),后来才知道那是echarts图,好吧,样式如下: 代码如下:(渐变色没做) <!DOCTYPE html> <h ...
- 【转】使用DevExpress的WebChartControl控件绘制图表(柱状图、折线图、饼图)
第一次写博,没什么经验,主要是把最近自己对Dev的一些研究贴出来大家共同探讨,有不足之处望大家帮忙斧正. WebChartControl是DevExpress控件群下的一个Web图表控件,它使用非常的 ...
- ios 绘制wav波形图
最近研究了如何在iOS上绘制wav波形图.查了很多资料,都没能找到一个很完整的介绍,我这里总结一下一些经验. 首先需要了解wav的这3个重要指标:采样率.采样位数.声道数.下面以16KHz, 16Bi ...
- iOS绘制坐标图,折线图-Swift
坐标图,经常会在各种各样的App中使用,最常用的一种坐标图就是折线图,根据给定的点绘制出对应的坐标图是最基本的需求.由于本人的项目需要使用折线图,第一反应就是搜索已经存在的解决方案,因为这种需求应该很 ...
- 转:iOS绘制一个UIView
绘制一个UIView 绘制一个UIVIew最灵活的方式就是由它自己完成绘制.实际上你不是绘制一个UIView,你只是子类化了UIView并赋予子类绘制自己的能力.当一个UIVIew需要执行绘图操作的时 ...
- iOS 绘制1像素的线
一.Point Vs Pixel iOS中当我们使用Quartz,UIKit,CoreAnimation等框架时,所有的坐标系统采用Point来衡量.系统在实际渲染到设置时会帮助我们处理Point到P ...
随机推荐
- CRL快速开发框架系列教程七(使用事务)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- ASP.NET Core: You must add a reference to assembly mscorlib, version=4.0.0.0
ASP.NET Core 引用外部程序包的时候,有时会出现下面的错误: The type 'Object' is defined in an assembly that is not referenc ...
- node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法
1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...
- 【知识必备】一文让你搞懂design设计的CoordinatorLayout和AppbarLayout联动,让Design设计更简单~
一.写在前面 其实博主在之前已经对design包的各个控件都做了博文说明,无奈个人觉得理解不够深入,所以有了这篇更加深入的介绍,希望各位看官拍砖~ 二.从是什么开始 1.首先我们得知道Coordina ...
- js从数组中随机取出不同的元素
前言 上午处理个需求需要从一个总数组中随机取出不同的元素.共使用两个方法.第一种方法较常规,经测试有bug,数据量大以后随机几次返回的对象直接是function而不是object. 当然简单数据类型应 ...
- UVA, 10336 Rank the Languages
难点在于:递归函数和输出: #include <iostream> #include <vector> #include <algorithm> #include ...
- BPM配置故事之案例3-参与者与数据自动加载
这才过了两天,阿海又来了. 阿海:公司决定改进管理方式,以后物资申请的申请人和申请部门要写具体使用人的名字和部门了. 小明:不是要让我改回去吧? 阿海:那太麻烦了,你能不能把申请人改成选择,选好人自动 ...
- Android中AlarmManager使用示例(持续更新,已经更改)
现在普遍的手机都会有一个闹钟的功能,如果使用Android来实现一个闹钟可以使用AtarmManager来实现.AtarmManager提供了一种系统级的提示服务,允许你安排在将来的某个时间执行一个服 ...
- 驱动01.LED
1.写出leds_open,leds_write函数2.1告诉内核这几个函数的存在?定义一个结构体file_operations2.2把这个结构体告诉内核?用register_chrdev(major ...
- win10系统下连接无线网络掉线问题解决办法
打开驱动精灵----系统诊断 找一个可修复的驱动点击 选择连不上网中的查看更多 有连不上网络,网络连接受限,解决无线间歇性掉网问题 进入计算机管理----设备管理 修改无线网络属性(名称含有wirel ...