【问题标题】:Draw ellipse gradient绘制椭圆渐变
【发布时间】:2013-02-26 08:30:42
【问题描述】:

如何绘制如下图?我在照片编辑工具中创建了这个。但在 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();
}

【问题讨论】:

    标签: ios ellipse radial-gradients


    【解决方案1】:

    好的,我买了一个新的...我认为它好多了。平滑度等是硬编码在STROKECOUNTMAXSTROKEWIDTH 等中的。这实际上使椭圆形向外增长了一点。需要进行一些调整才能强制停留在椭圆形矩形内。

    +(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;
    }
    

    【讨论】:

    • 我不确定这是否是最有效的方法,但如果您不绘制大量这些东西,它肯定足够快。对我来说非常方便。谢谢指点!
    猜你喜欢
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多