绘制一个简单的圆形UIImage

41

我尝试使用一个简单的蓝色圆来制作一个 20x20 的 UIImage 图片。 我使用了这个函数,但结果是一个带有黑色正方形背景的蓝色圆。 如何去掉圆周围的黑色正方形背景?

函数:

+ (UIImage *)blueCircle {
    static UIImage *blueCircle = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(20.f, 20.f), YES, 0.0f);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSaveGState(ctx);

        CGRect rect = CGRectMake(0, 0, 20, 20);
        CGContextSetFillColorWithColor(ctx, [UIColor cyanColor].CGColor);
        CGContextFillEllipseInRect(ctx, rect);

        CGContextRestoreGState(ctx);
        blueCircle = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

    });
    return blueCircle;
}

实际结果: 在此输入图片描述


1
潜在地,你应该使用一个视图而不是一个ImageView。https://dev59.com/qWw15IYBdhLWcg3weLoF - Woodstock
8个回答

38

谢谢你的问答!以下是 Swift 代码:

extension UIImage {
    class func circle(diameter: CGFloat, color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), false, 0)
        let ctx = UIGraphicsGetCurrentContext()
        CGContextSaveGState(ctx)

        let rect = CGRectMake(0, 0, diameter, diameter)
        CGContextSetFillColorWithColor(ctx, color.CGColor)
        CGContextFillEllipseInRect(ctx, rect)

        CGContextRestoreGState(ctx)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return img
    }
}

Schemetrical提供的Swift 3版本:

extension UIImage {
    class func circle(diameter: CGFloat, color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: diameter, height: diameter), false, 0)
        let ctx = UIGraphicsGetCurrentContext()!
        ctx.saveGState()

        let rect = CGRect(x: 0, y: 0, width: diameter, height: diameter)
        ctx.setFillColor(color.cgColor)
        ctx.fillEllipse(in: rect)

        ctx.restoreGState()
        let img = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return img
    }
}

以下是Swift 3代码,供其他人参考。顺便感谢您提供的解决方案。 - Schemetrical

34

如果您想看到角落后面的内容,您需要在位图中包含 alpha 通道:UIGraphicsBeginImageContextWithOptions(..., NO, ...)


20

Swift 3 & 4:

extension UIImage {
    class func circle(diameter: CGFloat, color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: diameter, height: diameter), false, 0)
        let ctx = UIGraphicsGetCurrentContext()!
        ctx.saveGState()

        let rect = CGRect(x: 0, y: 0, width: diameter, height: diameter)
        ctx.setFillColor(color.cgColor)
        ctx.fillEllipse(in: rect)

        ctx.restoreGState()
        let img = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return img
    }
}

Swift的自动更正功能非常神奇。感谢Valentin。


4
我想补充一点,在IT技术领域,我发现最简单、最性感的绘制图形并将其作为栅格化图像(带有透明背景)的方法是Paul Hudson在他的hackingwithswift.com网站上使用的方法。 从该网站中摘取的代码片段: https://www.hackingwithswift.com/example-code/core-graphics/how-to-draw-a-circle-using-core-graphics-addellipsein
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 512, height: 512))
let img = renderer.image { ctx in
    ctx.cgContext.setFillColor(UIColor.red.cgColor)
    ctx.cgContext.setStrokeColor(UIColor.green.cgColor)
    ctx.cgContext.setLineWidth(10)

    let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
    ctx.cgContext.addEllipse(in: rectangle)
    ctx.cgContext.drawPath(using: .fillStroke)
}

2

Xamarin.iOS示例:

    public static UIImage CircleImage(nfloat diameter, UIColor color, bool opaque = false)
    {
        var rect = new CGRect(0, 0, diameter, diameter);

        UIGraphics.BeginImageContextWithOptions(rect.Size, opaque, 0);
        var ctx = UIGraphics.GetCurrentContext();
        ctx.SaveState();

        ctx.SetFillColor(color.CGColor);
        ctx.FillEllipseInRect(rect);

        ctx.RestoreState();
        var img = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();

        return img;
    }

1
使用自定义初始化器创建指定直径和颜色的圆形:
extension UIImage {
    convenience init?(diameter: CGFloat, color: UIColor) {
        let size = CGSize(width: diameter, height: diameter)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        guard let contex = UIGraphicsGetCurrentContext() else {
            return nil
        }

        contex.saveGState()
        let rect = CGRect(origin: .zero, size: size)
        contex.setFillColor(color.cgColor)
        contex.fillEllipse(in: rect)
        contex.restoreGState()

        guard let image = UIGraphicsGetImageFromCurrentImageContext(),
        let cgImage = image.cgImage else {
            return nil
        }
        UIGraphicsEndImageContext()

        self.init(cgImage: cgImage)
    }
}

1
尝试这个。
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);

0

我认为使用方便的初始化方法和UIGraphicsImageRenderer会更好一些

public extension UIImage {
        
        convenience init?(circleDiameter: CGFloat, color: UIColor) {
            
            let size = CGSize(width: circleDiameter, height: circleDiameter)
            
            let renderer = UIGraphicsImageRenderer(size: size)
            
            let image = renderer.image { (ctx) in
                color.setFill()
                ctx.cgContext.fillEllipse(in: CGRect(origin: .zero, size: size))
            }
            
            guard let cgImage = image.cgImage else {
                return nil
            }
            
            self.init(cgImage: cgImage)
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接