Created
February 25, 2015 01:38
-
-
Save hirokim/a9c1748d0542ed1b5e39 to your computer and use it in GitHub Desktop.
iOSで棒グラフ描画
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "BarGraphView.h" | |
#define kOffsetX 10 | |
#define kStepX 30 | |
#define kGraphTop 0 | |
#define kStepY 50 | |
#define kOffsetY 10 | |
#define kBarTop 10 | |
#define kBarWidth 10 | |
#define kFactor 0.005 | |
@interface BarGraphView () | |
{ | |
float factor; | |
float maxBarHeight; | |
} | |
@property (nonatomic) NSArray *dataArray; | |
@end | |
@implementation BarGraphView | |
/** | |
* 画面初期化 | |
* | |
*/ | |
- (id)initWithCoder:(NSCoder *)aDecoder | |
{ | |
self = [super initWithCoder:aDecoder]; | |
if (self) { | |
[self initGraph]; | |
} | |
return self; | |
} | |
/** | |
* グラフ初期化 | |
* | |
*/ | |
- (void)initGraph | |
{ | |
factor = 0; | |
// データ | |
self.dataArray = @[@0.5, @0.5, @0.5, @1.0, @1.0, @1.0, @0.7, @0.7, @0.7, @0.8, @0.8]; | |
} | |
/** | |
* グラフ描画 | |
* | |
*/ | |
- (void)drawWithData:(NSArray *)data animated:(BOOL)animated | |
{ | |
self.dataArray = data; | |
[self redraw:animated]; | |
} | |
/** | |
* グラフ再描画 | |
* | |
*/ | |
- (void)redraw:(BOOL)animated | |
{ | |
if (animated) { | |
factor = 0; | |
[self drawAnimation]; | |
} else { | |
factor = 1; | |
[self setNeedsDisplay]; | |
} | |
} | |
/** | |
* アニメーションでグラフ描画 | |
* | |
*/ | |
- (void)drawAnimation | |
{ | |
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ | |
if (factor > 1) { | |
return; | |
} | |
[self drawAnimation]; | |
[self setNeedsDisplay]; | |
factor = factor + kFactor; | |
}); | |
} | |
/** | |
* 描画 | |
* | |
*/ | |
- (void)drawRect:(CGRect)rect | |
{ | |
CGContextRef context = UIGraphicsGetCurrentContext(); | |
CGContextSaveGState(context); | |
// 背景描画 | |
[self drawBackground:rect context:context]; | |
// 棒の最大高さ | |
maxBarHeight = rect.size.height - kBarTop - kOffsetY; | |
for (int i = 0; i < self.dataArray.count; i++) { | |
// 棒のX位置 | |
float barX = kOffsetX + kStepX + i * kStepX - kBarWidth / 2; | |
// 棒のY位置 | |
float barY = kBarTop + maxBarHeight - maxBarHeight * [self.dataArray[i] floatValue] * factor; | |
// 棒の高さ | |
float barHeight = maxBarHeight * [self.dataArray[i] floatValue] * factor; | |
// 棒の矩形 | |
CGRect barRect = CGRectMake(barX, barY, kBarWidth, barHeight); | |
// 棒の描画 | |
[self drawBar:barRect context:context]; | |
} | |
CGContextRestoreGState(context); | |
} | |
/** | |
* 背景描画 | |
* | |
*/ | |
- (void)drawBackground:(CGRect)rect context:(CGContextRef)context | |
{ | |
// 線の太さ | |
CGContextSetLineWidth(context, 0.6); | |
// 線の色 | |
CGContextSetStrokeColorWithColor(context, [[UIColor lightGrayColor] CGColor]); | |
// 縦線の本数 | |
int howMany = (rect.size.width - kOffsetX) / (2 * kStepX); | |
// 縦線を作成 | |
for (int i = 0; i < howMany; i++) { | |
CGContextMoveToPoint (context, kOffsetX + i * 2 * kStepX, kGraphTop); | |
CGContextAddLineToPoint(context, kOffsetX + i * 2 * kStepX, rect.size.height); | |
} | |
// 横線の本数 | |
int howManyHorizontal = (rect.size.height - kGraphTop - kOffsetY) / kStepY; | |
// 横線を作成 | |
for (int i = 0; i <= howManyHorizontal; i++) { | |
CGContextMoveToPoint (context, kOffsetX, rect.size.height - kOffsetY - i * kStepY); | |
CGContextAddLineToPoint(context, rect.size.width, rect.size.height - kOffsetY - i * kStepY); | |
} | |
// 点線にする | |
CGFloat dash[] = {2.0, 2.0}; | |
CGContextSetLineDash(context, 0.0, dash, 2); | |
// 線を描画 | |
CGContextStrokePath(context); | |
} | |
/** | |
* グラフ描画 | |
* | |
*/ | |
- (void)drawBar:(CGRect)rect context:(CGContextRef)context | |
{ | |
// グラデーションのHSB色 | |
float rate = rect.size.height / maxBarHeight; | |
float bottomHue = 0.3; | |
float topHue = rate > bottomHue ? (rate / 2) + bottomHue : bottomHue; | |
float middleHue = topHue > bottomHue ? (topHue + bottomHue) / 2 : bottomHue; | |
float saturation = 1.0; | |
float brightness = 1.0; | |
CGColorRef topColor = [UIColor colorWithHue:(topHue > bottomHue ? topHue : bottomHue) | |
saturation:saturation | |
brightness:brightness | |
alpha:1].CGColor; | |
CGColorRef middleColor = [UIColor colorWithHue:middleHue | |
saturation:saturation | |
brightness:brightness | |
alpha:1].CGColor; | |
CGColorRef bottomColor = [UIColor colorWithHue:bottomHue | |
saturation:saturation | |
brightness:brightness | |
alpha:1].CGColor; | |
NSArray* colors = @[(__bridge id)topColor, | |
(__bridge id)middleColor, | |
(__bridge id)bottomColor]; | |
// グラデーションの相対位置 | |
CGFloat locations[] = {0.0, 0.5, 1.0}; | |
// グラデーション情報作成 | |
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); | |
CGGradientRef gradient = CGGradientCreateWithColors(colorspace, (CFArrayRef)colors, locations); | |
// グラデーション開始位置 | |
CGPoint startPoint = rect.origin; | |
// グラデーション終了位置 | |
CGPoint endPoint = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height); | |
// 棒のパスを作成 | |
CGContextBeginPath (context); | |
CGContextSetGrayFillColor (context, 0.2, 0.7); | |
CGContextMoveToPoint (context, CGRectGetMinX(rect), CGRectGetMinY(rect)); | |
CGContextAddLineToPoint (context, CGRectGetMaxX(rect), CGRectGetMinY(rect)); | |
CGContextAddLineToPoint (context, CGRectGetMaxX(rect), CGRectGetMaxY(rect)); | |
CGContextAddLineToPoint (context, CGRectGetMinX(rect), CGRectGetMaxY(rect)); | |
CGContextClosePath (context); | |
// コンテキスト設定を一時保存 | |
CGContextSaveGState(context); | |
// コンテキストをクリップ | |
CGContextClip(context); | |
// グラデーション塗りつぶし | |
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0); | |
// 一時保存したコンテキスト設定に戻す | |
CGContextRestoreGState(context); | |
// 解放処理 | |
CGColorSpaceRelease(colorspace); | |
CGGradientRelease(gradient); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment