如何将方形图像蒙版为圆角图像?
8 回答
您可以使用 CoreGraphics 通过以下代码片段为圆角矩形创建路径:
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);
fw = CGRectGetWidth (rect) / ovalWidth;
fh = CGRectGetHeight (rect) / ovalHeight;
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
然后调用 CGContextClip(context); 将其剪辑到矩形路径。现在,任何完成的绘图,包括绘制图像,都将被剪裁为圆角矩形。
举个例子,假设“image”是一个 UIImage,它在一个 drawRect: 方法中:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
addRoundedRectToPath(context, self.frame, 10, 10);
CGContextClip(context);
[image drawInRect:self.frame];
CGContextRestoreGState(context);
这是在 iPhone 3.0 及更高版本中可用的更简单的方法。每个基于视图的对象都有一个关联的层。每个图层都可以设置一个角半径,这将为您提供您想要的:
UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * layer = [roundedView layer];
[layer setMasksToBounds:YES];
[layer setCornerRadius:10.0];
// You can even add a border
[layer setBorderWidth:4.0];
[layer setBorderColor:[[UIColor blueColor] CGColor]];
要使用这些方法,您可能需要添加:
#import <QuartzCore/QuartzCore.h>
我意识到这是旧消息,但只是将其简化一下:
这里有两个可能的问题:(1)如何将圆角应用到将显示在屏幕上的 UIView(例如 UIImageView),以及(2)如何屏蔽方形图像(即 UIImage ) 以生成带有圆角的新图像。
对于(1),最简单的当然是使用 CoreAnimation 并设置 view.layer.cornerRadius 属性
// Because we're using CoreAnimation, we must include QuartzCore.h
// and link QuartzCore.framework in a build phases
#import <QuartzCore/QuartzCore.h>
// start with an image
UIImage * fooImage = [UIImage imageNamed:@"foo.png"];
// put it in a UIImageView
UIView * view = [UIImageView alloc] initWithImage:fooImage];
// round its corners. This mask now applies to the view's layer's *background*
view.layer.cornerRadius = 10.f
// enable masksToBounds, so the mask applies to its foreground, the image
view.layer.masksToBounds = YES;
对于(2),最好的方法是使用 UIKit 的图形操作:
// start with an image
UIImage * fooImage = [UIImage imageNamed:@"foo.png"];
CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height);
// set the implicit graphics context ("canvas") to a bitmap context for images
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0);
// create a bezier path defining rounded corners
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f];
// use this path for clipping in the implicit context
[path addClip];
// draw the image into the implicit context
[fooImage drawInRect:imageRect];
// save the clipped image from the implicit context into an image
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
// cleanup
UIGraphicsEndImageContext();
问题 (2) 的棘手之处在于,您可能认为可以使用 CoreAnimation 中的 view.layer.mask 属性来完成整个操作。但是您不能,因为renderInContext:
用于从蒙版层生成 UIImage 的 CALayer 方法似乎忽略了蒙版。更糟糕的是, 的文档renderInContext:
没有提到这一点,只提到了 OSX 10.5 的行为。
一些进一步的背景:上述 (2) 的方法是使用 UIKit 的包装器围绕更基本的 CoreGraphics 功能。您可以直接使用 CoreGraphics 调用来做同样的事情——这就是选择的答案正在做的事情——但是你需要从曲线和直线手动构建圆角矩形贝塞尔路径,你还需要补偿 CoreGraphics 使用相对于 UIKit 翻转的绘图坐标系。
看到这篇文章 - 非常简单的答案
UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];
非常简单。self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width / 2; self.profileImageView.clipsToBounds = YES;
对于每个视图,都有一个捆绑的图层属性。所以上面第一行就是设置图层对象(即CALayer类的一个实例)的圆角半径。要从方形图像制作圆形图像,半径设置为 UIImageView 宽度的一半。例如,如果正方形图像的宽度为 100 像素。半径设置为 50 像素。其次,您必须将 clipsToBounds 属性设置为 YES 才能使图层正常工作。
这两种方法都有效,但差异取决于您使用它的位置。
例如:如果您有一个表格视图,其中的单元格显示图像以及其他标签等,并且您使用图层设置cornerRadius,则滚动将受到很大影响。它变得生涩。
当我在表格视图单元格中使用图层作为图像时,我遇到了这个问题,并试图找出这种抖动的原因,却发现 CALayer 是罪魁祸首。
使用 NilObject 解释的在 drawRect 中做这些事情的第一个解决方案。滚动就像丝绸一样光滑,这就像一种魅力。
另一方面,如果你想在弹出视图等静态视图中使用它,图层是最简单的方法。
正如我所说,这两种方法都运行良好,只是您需要根据要使用它的位置来决定。
我使用这种方法。
+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size;
{
UIImage *img = nil;
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context,
color.CGColor);
CGContextFillRect(context, rect);
img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
在algal的基础上,这里有一些方法可以很好地放在 UIImage 类别中:
- (UIImage *) roundedCornerImageWithRadius:(CGFloat)radius
{
CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); //scale 0 yields better results
//create a bezier path defining rounded corners and use it for clippping
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius];
[path addClip];
// draw the image into the implicit context
[self drawInRect:imageRect];
// get image and cleanup
UIImage *roundedCornerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return roundedCornerImage;
}
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andCornerRadius:(CGFloat)radius
{
UIImage *image = nil;
if (size.width == 0 || size.height == 0) {
size = CGSizeMake(1.0, 1.0);
}
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0); //yields sharper results than UIGraphicsBeginImageContext(rect.size)
CGContextRef context = UIGraphicsGetCurrentContext();
if (context)
{
CGContextSetFillColorWithColor(context, [color CGColor]);
if (radius > 0.0) {
//create a bezier path defining rounded corners and use it for clippping
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
[path addClip];
CGContextAddPath(context, path.CGPath);
}
CGContextFillRect(context, rect);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return image;
}