【问题标题】:Draw rounded linear gradient (or extended radial gradient) with CoreGraphics使用 CoreGraphics 绘制圆形线性渐变(或扩展径向渐变)
【发布时间】:2012-05-01 11:51:52
【问题描述】:

我想用 CoreGraphics 做一些自定义绘图。我的视图需要一个线性渐变,但问题是这个视图是一个圆角矩形,所以我希望我的渐变也以角度圆角。您可以在下图中看到我想要实现的目标:

那么这是否可以在 CoreGraphics 或其他一些编程和简单的方式中实现? 谢谢。

【问题讨论】:

    标签: objective-c cocoa core-graphics gradient


    【解决方案1】:

    我不认为有一个 API 可以做到这一点,但是如果您首先绘制径向渐变,例如在 (N+1)x(N+1) 大小的位图上下文中,然后将图像从上下文转换为可调整大小的图像,左右大写设置为N

    伪代码:

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(N+1,N+1), NO, 0.0f);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // <draw the gradient into 'context'>
    
    UIImage* gradientBase = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    UIImage* gradientImage = [gradientBase resizableImageWithCapInsets:UIEdgeInsetsMake(0,N,0,N)];
    

    如果您还希望图像垂直缩放,您只需将大写设置为UIEdgeInsetsMake(N,N,N,N)

    【讨论】:

    • 感谢您的想法。如果我们将径向渐变转换为图像并拉伸它,那么渐​​变的边也会被拉伸(会变成椭圆而不是圆形),对吗?
    • 如果您使用 resizableImage API 执行此操作,则它不会失真,因为只有帽外的像素被调整大小/平铺。
    • 好的。那就谢谢了。我会试试的。
    • 我已经尝试实现这一点,它看起来应该很好用,但我有一个问题。我得到了定义了插图的径向渐变的可调整大小的图像,当我使用[gradientImage drawAtPoint: point] 在某个点绘制它时,它会绘制我的径向渐变。但是当我想用[gradientImage drawInRect:myRect] 方法在我的矩形中绘制它时,它并没有被拉伸,而是被平铺了几次。但是当我不申请resizableImageWithCapInsets 时,它就会被拉伸。这是正常行为吗?我想绘制一个拉伸的图像,而不是平铺的。
    • 嗯,这是预期的行为。如果要拉伸中间部分(帽外的部分),请按上述方式设置帽,以获得 1 像素宽的非封顶区域,平铺相当于拉伸。任何比这更宽的东西都不可避免地会被平铺。
    【解决方案2】:

    我只是想为这项技术添加更多示例代码,因为有些事情并不明显。也许它对某人有用:

    所以,假设我们有我们的自定义视图类,在它的 drawRect: 方法中我们放了这个:

    // Defining the rect in which to draw
    CGRect drawRect=self.bounds;
    Float32 gradientSize=drawRect.size.height;   // The size of original radial gradient
    CGPoint center=CGPointMake(0.5f*gradientSize,0.5f*gradientSize);  // Center of gradient
    
    // Creating the gradient
    Float32 colors[4]={0.f,1.f,1.f,0.2f};  // From opaque white to transparent black
    CGGradientRef gradient=CGGradientCreateWithColorComponents(CGColorSpaceCreateDeviceGray(), colors, nil, 2);
    
    // Starting image and drawing gradient into it
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(gradientSize, gradientSize), NO, 1.f);
    CGContextRef context=UIGraphicsGetCurrentContext();
    CGContextDrawRadialGradient(context, gradient, center, 0.f, center, center.x, 0);  // Drawing gradient
    UIImage* gradientImage=UIGraphicsGetImageFromCurrentImageContext();  // Retrieving image from context
    UIGraphicsEndImageContext();  // Ending process
    gradientImage=[gradientImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, center.x-1.f, 0.f, center.x-1.f)];  // Leaving 2 pixels wide area in center which will be tiled to fill whole area
    
    // Drawing image into view frame
    [gradientImage drawInRect:drawRect];
    

    就是这样。此外,如果您不打算在应用程序运行时更改渐变,您可能希望将除最后一行之外的所有内容都放在 awakeFromNib 方法中,然后在 drawRect: 中将 gradientImage 绘制到视图的框架中。在这种情况下也不要忘记保留gradientImage

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多