Skip to content

Instantly share code, notes, and snippets.

@hirokim
Created February 25, 2015 01:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hirokim/a9c1748d0542ed1b5e39 to your computer and use it in GitHub Desktop.
Save hirokim/a9c1748d0542ed1b5e39 to your computer and use it in GitHub Desktop.
iOSで棒グラフ描画
#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