Skip to content

Instantly share code, notes, and snippets.

@pronebird
Last active August 29, 2015 14:05
Show Gist options
  • Save pronebird/c3dde8c25938c35c1ab8 to your computer and use it in GitHub Desktop.
Save pronebird/c3dde8c25938c35c1ab8 to your computer and use it in GitHub Desktop.
Draw arrow with rounded corners using CoreGraphics
@implementation UIImage (Arrow)
+ (UIImage*)arrowImageWithSize:(CGFloat)arrowSize withColor:(UIColor*)arrowColor thickness:(CGFloat)thickness
{
//
// Create bezier path for arrow
//
// +---+-------+-+
// | |
// | +
// | |
// + +-----+-+
// | |
// | |
// + +
// | |
// +--+--+
//
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
// Setup bezier path line width
bezierPath.lineWidth = 0.5f;
// Calculate radius
CGFloat radius = thickness * 0.5f;
// Top left
[bezierPath moveToPoint:CGPointMake(0, radius)];
[bezierPath addQuadCurveToPoint:CGPointMake(radius, 0) controlPoint:CGPointMake(0, 0)];
// Top right
[bezierPath addLineToPoint:CGPointMake(arrowSize - radius, 0)];
[bezierPath addQuadCurveToPoint:CGPointMake(arrowSize, radius) controlPoint:CGPointMake(arrowSize, 0)];
[bezierPath addQuadCurveToPoint:CGPointMake(arrowSize - radius, thickness) controlPoint:CGPointMake(arrowSize, thickness)];
// Middle
[bezierPath addLineToPoint:CGPointMake(thickness + radius, thickness)];
[bezierPath addQuadCurveToPoint:CGPointMake(thickness, thickness + radius) controlPoint:CGPointMake(thickness, thickness)];
// Bottom right
[bezierPath addLineToPoint:CGPointMake(thickness, arrowSize - radius)];
[bezierPath addQuadCurveToPoint:CGPointMake(radius, arrowSize) controlPoint:CGPointMake(thickness, arrowSize)];
// Bottom left
[bezierPath addQuadCurveToPoint:CGPointMake(0, arrowSize - radius) controlPoint:CGPointMake(0, arrowSize)];
// Close path
[bezierPath closePath];
// Rotate bezierPath by 45 deg to get arrow to point north
CGFloat angle = 45 * M_PI/180;
// Create transformation matrix
CGAffineTransform transform = CGAffineTransformIdentity;
// Translate bezier path origin to its center to rotate around its center
transform = CGAffineTransformMakeTranslation(arrowSize * 0.5f, arrowSize * 0.5f);
// Rotate bezier path
transform = CGAffineTransformRotate(transform, angle);
// Apply transformation matrix
// This will calculated new bounds for bezier path
[bezierPath applyTransform:transform];
// Undo translation
[bezierPath applyTransform:CGAffineTransformMakeTranslation(-bezierPath.bounds.origin.x, -bezierPath.bounds.origin.y)];
// Get bounding rect of rotated bezierPath
CGRect arrowRect = CGRectZero;
arrowRect.size.width = ceil(CGRectGetWidth(bezierPath.bounds));
arrowRect.size.height = ceil(CGRectGetHeight(bezierPath.bounds));
// Create image context and draw bezier path
UIGraphicsBeginImageContextWithOptions(arrowRect.size, NO, 0.0f);
// Fill and stroke bezier path
[arrowColor setFill];
[bezierPath fill];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment