1

以下のような画像を描くにはどうすればよいですか?これは写真編集ツールで作成しました。しかし、iOSではそれをうまくやってのけることはできません。

  • 楕円
  • 「ソフトコーナー」は、ある意味、円形ではないことだけが放射状のグラデーションのようなものです。

ここに画像の説明を入力

https://stackoverflow.com/a/12665177/129202は私を良い方向に導きますが、実際にはアフィン変換の効果は 100% ではありません。

使用したコード:

+(UIImage*)createGradientOval2:(const CGSize)SIZECONTEXT {
    const CGFloat SCALE = 2.0f;
    UIGraphicsBeginImageContextWithOptions(SIZECONTEXT, NO, SCALE);
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // Create gradient
    CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();

    const CGFloat colors [] = {
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 1.00, // green
        0.0, 1.0, 0.0, 0.00, // transparent
    };
    //CGGradientRef gradient = CGGradientCreateWithColors(baseSpace, (CFArrayRef)colors, locations);
    CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 10);
    CGColorSpaceRelease(baseSpace), baseSpace = NULL;

    // Scaling transformation and keeping track of the inverse
    CGAffineTransform scaleT = CGAffineTransformMakeScale(1, 2.0);
    CGAffineTransform invScaleT = CGAffineTransformInvert(scaleT);

    // Extract the Sx and Sy elements from the inverse matrix
    // (See the Quartz documentation for the math behind the matrices)
    CGPoint invS = CGPointMake(invScaleT.a, invScaleT.d);

    const CGRect RECT = CGRectMake(0, 0, SIZECONTEXT.width / 2, SIZECONTEXT.height / 2);

    // Transform center and radius of gradient with the inverse
    CGPoint center = CGPointMake((RECT.size.width / 2) * invS.x, (RECT.size.height / 2) * invS.y);
    CGFloat radius = (RECT.size.width / 2) * invS.x;

    // Draw the gradient with the scale transform on the context
    CGContextScaleCTM(ctx, scaleT.a, scaleT.d);
    CGContextDrawRadialGradient(ctx, gradient, center, 0, center, radius, kCGGradientDrawsBeforeStartLocation);

    // Reset the context
    CGContextScaleCTM(ctx, invS.x, invS.y);

    // Continue to draw whatever else ...

    // Clean up the memory used by Quartz
    CGGradientRelease(gradient);

    return UIGraphicsGetImageFromCurrentImageContext();
}
4

1 に答える 1

1

わかりました、新しいものを手に入れました... ずっと良くなったと思います。滑らかさなどは などにハードコードされていSTROKECOUNTますMAXSTROKEWIDTH。これにより、実際には楕円形が少し外側に大きくなります。楕円形の四角形の中にとどまるように強制するには、微調整が必​​要です。

+(UIImage*)ellipseWithSmoothEdges:(const CGSize)SIZECONTEXT oval:(const CGRect)RECTFOROVAL {
    const CGFloat SCALE = 2.0f;

    UIColor* colorPaint = [UIColor greenColor];

    UIGraphicsBeginImageContextWithOptions(SIZECONTEXT, NO, SCALE);
    CGContextRef context = UIGraphicsGetCurrentContext();

    UIBezierPath* pathEllipseForClippingto = [UIBezierPath bezierPathWithOvalInRect:RECTFOROVAL];
    const int STROKECOUNT = 70;
    const CGFloat BASEALPHA = 1.0f / (CGFloat)STROKECOUNT;
    const CGFloat MAXSTROKEWIDTH = 50;
    UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect:RECTFOROVAL];

    CGContextSaveGState(context); {
        [pathEllipseForClippingto addClip];
        [colorPaint setFill];
        [path fill];
        CGContextRestoreGState(context);
    }
    for (int i = 0; i < STROKECOUNT; i++) {
        [[UIColor colorWithRed:0 green:1 blue:0 alpha:BASEALPHA * i] setStroke];
        path.lineWidth = MAXSTROKEWIDTH - i;
        [path stroke];
    }

    UIImage* imageGenerated = UIGraphicsGetImageFromCurrentImageContext();

    return imageGenerated;
}
于 2013-02-26T09:31:41.217 に答える