i want to draw a shape like in the attached image using core graphics in iOS. Is this possible. Please provide sample code if it possible.
I want at least 3 color gradient over the shape.
Gradients don't naturally draw along path. You have to simulate it. The code is using NSBezierPath, NSView and CGContext but it should not be hard to port it to iOS.
I did with an assembly of trapezoids.
Here is the drawRect of the NSView drawing the gradients:
@implementation grad
-(void)drawRect:(NSRect)dirtyRect {
[[NSColor whiteColor]set];
NSRectFill([self bounds]);
float dim = MIN(self.bounds.size.width, self.bounds.size.height);
int subdiv=512;
float r=dim/4;
float R=dim/2;
float halfinteriorPerim = M_PI*r;
float halfexteriorPerim = M_PI*R;
float smallBase= halfinteriorPerim/subdiv;
float largeBase= halfexteriorPerim/subdiv;
NSBezierPath * cell = [NSBezierPath bezierPath];
[cell moveToPoint:NSMakePoint(- smallBase/2, r)];
[cell lineToPoint:NSMakePoint(+ smallBase/2, r)];
[cell lineToPoint:NSMakePoint( largeBase /2 , R)];
[cell lineToPoint:NSMakePoint(-largeBase /2, R)];
[cell closePath];
float incr = M_PI / subdiv;
CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
CGContextTranslateCTM(ctx, +self.bounds.size.width/2, +self.bounds.size.height/2);
CGContextScaleCTM(ctx, 0.9, 0.9);
CGContextRotateCTM(ctx, M_PI/2);
CGContextRotateCTM(ctx,-incr/2);
for (int i=0;i<subdiv;i++) {
// replace this color with a color extracted from your gradient object
[[NSColor colorWithCalibratedHue:(float)i/subdiv saturation:1 brightness:1 alpha:1] set];
[cell fill];
[cell stroke];
CGContextRotateCTM(ctx, -incr);
}
}
This looks like this, with various combinations of subdiv
and r
(interior radius), and at different scales.
This version uses Objective-C blocks for color and contour functions. Just pass in a block a function that returns the inner radius, outer radius, and color for any number between 0 and 1. Other parameters are start angle, end angle, number of subdivisions, center, and a scale for debugging purpose, and a CGContextRef.
#import "GradientView.h"
@implementation GradientView
typedef void (^voidBlock)(void);
typedef float (^floatfloatBlock)(float);
typedef UIColor * (^floatColorBlock)(float);
-(CGPoint) pointForTrapezoidWithAngle:(float)a andRadius:(float)r forCenter:(CGPoint)p{
return CGPointMake(p.x + r*cos(a), p.y + r*sin(a));
}
-(void)drawGradientInContext:(CGContextRef)ctx startingAngle:(float)a endingAngle:(float)b intRadius:(floatfloatBlock)intRadiusBlock outRadius:(floatfloatBlock)outRadiusBlock withGradientBlock:(floatColorBlock)colorBlock withSubdiv:(int)subdivCount withCenter:(CGPoint)center withScale:(float)scale
{
float angleDelta = (b-a)/subdivCount;
float fractionDelta = 1.0/subdivCount;
CGPoint p0,p1,p2,p3, p4,p5;
float currentAngle=a;
p4=p0 = [self pointForTrapezoidWithAngle:currentAngle andRadius:intRadiusBlock(0) forCenter:center];
p5=p3 = [self pointForTrapezoidWithAngle:currentAngle andRadius:outRadiusBlock(0) forCenter:center];
CGMutablePathRef innerEnveloppe=CGPathCreateMutable(),
outerEnveloppe=CGPathCreateMutable();
CGPathMoveToPoint(outerEnveloppe, 0, p3.x, p3.y);
CGPathMoveToPoint(innerEnveloppe, 0, p0.x, p0.y);
CGContextSaveGState(ctx);
CGContextSetLineWidth(ctx, 1);
for (int i=0;i<subdivCount;i++)
{
float fraction = (float)i/subdivCount;
currentAngle=a+fraction*(b-a);
CGMutablePathRef trapezoid = CGPathCreateMutable();
p1 = [self pointForTrapezoidWithAngle:currentAngle+angleDelta andRadius:intRadiusBlock(fraction+fractionDelta) forCenter:center];
p2 = [self pointForTrapezoidWithAngle:currentAngle+angleDelta andRadius:outRadiusBlock(fraction+fractionDelta) forCenter:center];
CGPathMoveToPoint(trapezoid, 0, p0.x, p0.y);
CGPathAddLineToPoint(trapezoid, 0, p1.x, p1.y);
CGPathAddLineToPoint(trapezoid, 0, p2.x, p2.y);
CGPathAddLineToPoint(trapezoid, 0, p3.x, p3.y);
CGPathCloseSubpath(trapezoid);
CGPoint centerofTrapezoid = CGPointMake((p0.x+p1.x+p2.x+p3.x)/4, (p0.y+p1.y+p2.y+p3.y)/4);
CGAffineTransform t = CGAffineTransformMakeTranslation(-centerofTrapezoid.x, -centerofTrapezoid.y);
CGAffineTransform s = CGAffineTransformMakeScale(scale, scale);
CGAffineTransform concat = CGAffineTransformConcat(t, CGAffineTransformConcat(s, CGAffineTransformInvert(t)));
CGPathRef scaledPath = CGPathCreateCopyByTransformingPath(trapezoid, &concat);
CGContextAddPath(ctx, scaledPath);
CGContextSetFillColorWithColor(ctx,colorBlock(fraction).CGColor);
CGContextSetStrokeColorWithColor(ctx, colorBlock(fraction).CGColor);
CGContextSetMiterLimit(ctx, 0);
CGContextDrawPath(ctx, kCGPathFillStroke);
CGPathRelease(trapezoid);
p0=p1;
p3=p2;
CGPathAddLineToPoint(outerEnveloppe, 0, p3.x, p3.y);
CGPathAddLineToPoint(innerEnveloppe, 0, p0.x, p0.y);
}
CGContextSetLineWidth(ctx, 10);
CGContextSetLineJoin(ctx, kCGLineJoinRound);
CGContextSetStrokeColorWithColor(ctx, [UIColor blackColor].CGColor);
CGContextAddPath(ctx, outerEnveloppe);
CGContextAddPath(ctx, innerEnveloppe);
CGContextMoveToPoint(ctx, p0.x, p0.y);
CGContextAddLineToPoint(ctx, p3.x, p3.y);
CGContextMoveToPoint(ctx, p4.x, p4.y);
CGContextAddLineToPoint(ctx, p5.x, p5.y);
CGContextStrokePath(ctx);
}
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor whiteColor] set];
UIRectFill(self.bounds);
CGRect r = self.bounds;
r=CGRectInset(r, 60, 60);
if (r.size.width > r.size.height)
r.size.width=r.size.height;
else r.size.height=r.size.width;
float radius=r.size.width/2;
[self drawGradientInContext:ctx startingAngle:M_PI/16 endingAngle:2*M_PI-M_PI/16 intRadius:^float(float f) {
// return 0*f + radius/2*(1-f);
return 200+10*sin(M_PI*2*f*7);
// return 50+sqrtf(f)*200;
// return radius/2;
} outRadius:^float(float f) {
// return radius *f + radius/2*(1-f);
return radius;
// return 300+10*sin(M_PI*2*f*17);
} withGradientBlock:^UIColor *(float f) {
// return [UIColor colorWithHue:f saturation:1 brightness:1 alpha:1];
float sr=90, sg=54, sb=255;
float er=218, eg=0, eb=255;
return [UIColor colorWithRed:(f*sr+(1-f)*er)/255. green:(f*sg+(1-f)*eg)/255. blue:(f*sb+(1-f)*eb)/255. alpha:1];
} withSubdiv:256 withCenter:CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r)) withScale:1];
}
@end
Examples:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With