一、使用Quartaz2d的画图功能裁剪。
1.例如截取图片上的一个圆:
- (UIImage *)cutCircleBg
{
UIImage *baseImage = [UIImage imageNamed:@"LuckyBaseBackground"];
// Quartz2D
// 核心对象:上下文(保存图片)
// 1.开始上下文(NO == 透明, 0.0 == 默认做法)
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
// 2.获得当前上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 3.绘图裁剪
// 3.1.画圆
CGFloat innerCircleXY = 9;
CGFloat innerCircleWH = ILCircleWH - innerCircleXY * 2;
CGRect innerCircleRect = CGRectMake(innerCircleXY, innerCircleXY, innerCircleWH, innerCircleWH);
CGContextAddEllipseInRect(ctx, innerCircleRect);
// 3.2.裁剪(CGContextClip会把之前所画的剪下来)
CGContextClip(ctx);
// 3.3.画图片(这句代替后面的两句,可以免去坐标系转换的操作)
[baseImage drawInRect:self.bounds];
// CGContextDrawImage(ctx, self.bounds, baseImage.CGImage);
// CGContextTranslateCTM(<#CGContextRef c#>, <#CGFloat tx#>, <#CGFloat ty#>)
// 4.获得上下文中最终的图片
UIImage *newBaseBg = UIGraphicsGetImageFromCurrentImageContext();
// 5.结束上下文
UIGraphicsEndImageContext();
return newBaseBg;
}
2.通过重写继承于UIView的类的drawRect:方法获取当前Quartz2d的上下文来截取图片并且设置为背景
- (void)drawRect:(CGRect)rect
{
// 1.画最底部的背景图
// [[self cutCircleBg] drawInRect:rect];
CGContextRef ctx = UIGraphicsGetCurrentContext();
// copy一个ctx对象到栈中
CGContextSaveGState(ctx);
// 2.绘图裁剪
// 2.1.画圆
CGFloat innerCircleXY = 9;
CGFloat innerCircleWH = ILCircleWH - innerCircleXY * 2;
CGRect innerCircleRect = CGRectMake(innerCircleXY, innerCircleXY, innerCircleWH, innerCircleWH);
CGContextAddEllipseInRect(ctx, innerCircleRect);
// 3.2.裁剪(CGContextClip会把之前所画的剪下来)
CGContextClip(ctx);
[[UIImage imageNamed:@"LuckyBaseBackground"] drawInRect:rect];
//取出栈中的ctx
CGContextRestoreGState(ctx);
// 4.画中间的转盘图
[[UIImage imageNamed:@"LuckyRotateWheel"] drawInRect:rect];
// [[UIColor redColor] set];
// NSString *str = @"这是一个转盘";
// [str drawAtPoint:CGPointZero withFont:[UIFont systemFontOfSize:30]];
}
这个方法中需要特别注意的是copy一个ctx对象到栈中这个操作,如果不执行这一步而是直接使用同一个ctx来画图,会因为这个ctx有裁剪功能的而使第二张图片也会裁剪后才画在这个view上,从而形成下面这种状态:
显然上面那张图片的尖角被裁剪了,而先将一个上下文ctx保存到栈中,之后再取出画第二张图片,则能达到想要的效果:
二、利用CGImageCreateWithImageInRect:方法裁剪,他返回一个CGImageRef对象
例如下面这个方法是将这张大图片
裁剪成12张同等大小的矩形图片
- (void)setBg:(NSString *)normal selected:(NSString *)selected
{
for (int i = 0; i<12; i++) {
ILCircleItemView *btn = self.subviews[i];
// 加载大图片
UIImage *normalBig = [UIImage imageNamed:normal];
// 裁剪小图片
CGFloat miniW = normalBig.size.width / 12 * [UIScreen mainScreen].scale;
CGFloat miniH = normalBig.size.height * [UIScreen mainScreen].scale;
CGRect miniRect = CGRectMake(i * miniW, 0, miniW, miniH);
CGImageRef miniNormalCG = CGImageCreateWithImageInRect(normalBig.CGImage, miniRect);
[btn setImage:[UIImage imageWithCGImage:miniNormalCG] forState:UIControlStateNormal];
UIImage *selectedBig = [UIImage imageNamed:selected];
CGImageRef miniSelectedCG = CGImageCreateWithImageInRect(selectedBig.CGImage, miniRect);
[btn setImage:[UIImage imageWithCGImage:miniSelectedCG] forState:UIControlStateSelected];
}
}
,
这里需要特别说明的是,在IOS中,所有的UI开头的类使用的都是点坐标系,例如点{480,46}在非视网膜屏幕下的像数是480*46,而在视网膜屏(retina)下的像数是960*92,所以CGFloat miniW = normalBig.size.width / 12 * [UIScreen mainScreen].scale;的作用就是区分视网膜屏([UIScreen mainScreen].scale的值是2.0)和非视网膜屏([UIScreen mainScreen].scale的值是1.0)的状况,