Skip to content

Instantly share code, notes, and snippets.

@yuiseki
Created August 13, 2012 08:09
Show Gist options
  • Save yuiseki/3338120 to your computer and use it in GitHub Desktop.
Save yuiseki/3338120 to your computer and use it in GitHub Desktop.
UIImageViewにタコメーター風の円弧描画 by CoreGraphics
// 与えられた正方形のImageViewと1から0のパーセント値に対して、タコメーター風の円弧を描くメソッド
- (void)drawArcToUIImageView:(UIImageView *)targetImageView withPercntage:(CGFloat)percnt
{
targetImageView.layer.needsDisplayOnBoundsChange=YES;
UIGraphicsBeginImageContext(targetImageView.frame.size);
struct CGContext *context = UIGraphicsGetCurrentContext();
CGPoint arcCenter = CGPointMake(targetImageView.frame.size.width/2, targetImageView.frame.size.height/2);
CGFloat outerRadius = (targetImageView.frame.size.width/2.0f)-1.0f;
CGFloat innerRadius = (targetImageView.frame.size.width/2.0f)-4.0f;
// radianは0のときの開始位置が3時の位置 なので、-90して0時の位置にする
CGFloat startRadian = 0-(0.5f * M_PI);
CGFloat angle = 360*percnt;
CGFloat endRadian = ( angle * (M_PI / 180.0f) ) -(0.5f * M_PI);
CGFloat minRadian = (M_PI / 180.0f);
CGContextBeginPath(context);
CGContextSetLineWidth(context, 3.0f);
// 常に円弧の先端に位置する三角形の頂点はendRadianの座標を求める
CGPoint inwardPoint = CGPointMake( arcCenter.x + ( (innerRadius) * cos(endRadian) ) ,
arcCenter.y + ( (innerRadius) * sin(endRadian) ) );
CGContextMoveToPoint(context, inwardPoint.x, inwardPoint.y);
CGContextAddLineToPoint(context, inwardPoint.x, inwardPoint.y);
// 円弧の内側に位置することになる三角形の各頂点の座標も毎回計算する必要がある
// より狭い半径=内側で endRadian角度の前後の座標を得る 正三角形になるように角度調節する
CGPoint secondPoint = CGPointMake(arcCenter.x + ( (innerRadius-7) * cos(endRadian+(4*minRadian)) ) ,
arcCenter.y + ( (innerRadius-7) * sin(endRadian+(4*minRadian)) ) );
CGContextAddLineToPoint(context, secondPoint.x, secondPoint.y);
CGPoint thirdPoint = CGPointMake(arcCenter.x + ( (innerRadius-7) * cos(endRadian-(4*minRadian)) ) ,
arcCenter.y + ( (innerRadius-7) * sin(endRadian-(4*minRadian)) ) );
CGContextAddLineToPoint(context, thirdPoint.x, thirdPoint.y);
CGContextClosePath(context);
// 上記三点を結ぶバスに対する描画パターンの指定
UIColor *aColor = [UIColor redColor];
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 1.0f, [aColor CGColor]);
CGContextSetFillColorWithColor(context, [aColor CGColor]);
CGContextFillPath(context);
CGContextBeginPath(context);
CGContextSetLineWidth(context, 3.0f);
CGContextAddArc(context, arcCenter.x, arcCenter.y,
innerRadius, startRadian, endRadian, 0);
CGContextAddArc(context, arcCenter.x, arcCenter.y,
outerRadius, endRadian, startRadian, 1);
CGContextClosePath(context);
UIColor *bColor = [UIColor blueColor];
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 0.0f), 4.0f, [bColor CGColor]);
CGContextFillPath(context);
// 円弧のパスを描画する 切り抜くためにパスが閉じてないといけないので二重に書く。書く方向も影響するので一筆書きに書く
CGContextBeginPath(context);
CGContextSetLineWidth(context, 3.0f);
// 内枠円弧 0時位置から始まりendRadianまで描く
CGContextAddArc(context, arcCenter.x, arcCenter.y,
innerRadius, startRadian, endRadian, 0);
// 外枠円弧を終点から始点に、逆時計回りに描く
CGContextAddArc(context, arcCenter.x, arcCenter.y,
outerRadius, endRadian, startRadian, 1);
CGContextClosePath(context);
// 以降のシェイプを上記のパスで切り抜くぞという宣言
CGContextClip(context);
// 矩形グラデーションの描画(これが切り抜かれる)
struct CGColorSpace *rgbColor = CGColorSpaceCreateDeviceRGB();
CGFloat locations[2] = {0.0, 1.0};
CGFloat components[8] = {0.549, 0.941, 100, 1,
0.00, 0.502, 1.0, 1};
struct CGGradient *gradient = CGGradientCreateWithColorComponents(rgbColor, components, locations, 2);
CGRect currentBounds = targetImageView.bounds;
CGPoint rightUp = CGPointMake(CGRectGetMaxX(currentBounds), 0.0f);
CGPoint leftBottom = CGPointMake(0.0f, CGRectGetMaxY(currentBounds));
CGContextDrawLinearGradient(context, gradient, rightUp, leftBottom, 0);
targetImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment