項目需求,參考了其餘繪圖demo,本身繪製出來了,不過代碼改得有點亂,添加了不少變量,時間關係沒用太合適的命名,邏輯處理也沒進行優化。數組
看看效果圖(虛線區域都是畫的,其餘區域添加的都是控件),附上源碼
字體
#import <UIKit/UIKit.h>優化
typedef enum : NSUInteger {atom
CSYieldTypeWeek = 0, //周收益spa
CSYieldTypeMonth = 1, //月收益orm
CSYieldTypeYear = 2, //年收益blog
} CSYieldType; //收益類型源碼
typedef enum : NSUInteger {string
CSTimePointJanuary = 0, //一月份it
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