我想在 iOS 中使用核心图形绘制一个形状,如附图所示。这可能吗。如果可能,请提供示例代码。
我希望在形状上至少有 3 种颜色渐变。
最佳答案
渐变不会自然地沿着路径绘制。你必须模拟它。该代码使用了 NSBezierPath、NSView 和 CGContext,但将其移植到 iOS 应该不难。
我做了一组梯形。
这是绘制渐变的 NSView 的 drawRect:
@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);
}
}
这看起来像这样,具有 subdiv
和 r
(内部半径)的各种组合,并且具有不同的比例。
带 block 的新版本,iOS 就绪
此版本使用 Objective-C block 来实现颜色和轮廓函数。只需在一个 block 中传递一个函数,该函数返回 0 到 1 之间的任何数字的内半径、外半径和颜色。其他参数是起始角度、结束角度、分割数、中心和用于调试目的的比例,以及一个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
例子:
关于iphone - 在 iOS 中使用核心图形绘制带渐变的外半圆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11783114/