Quartz2D复习(一)--- 基础知识 / 绘制线段圆弧 / 图片水印 / 截图

时间:2022-03-20 20:17:53

1、Quartz 2D是一个二维绘图引擎,同时支持ios和Mac系统; Quart2D的API是纯C语言的,API来自于Core  Graphics框架:

2、Quartz 2D可以绘制图形(线段/三角形/矩形/圆和弧)、绘制文字、绘制和生成图片、读取/生成pdf、截图/裁剪图片、自定义UI控件等

3、对于界面复杂且个性化的UI,普通的UI控件无法实现,而Quartz2D技术却可以通过自定义UI控件来实现。其实,ios中大部分控件的内容都是通过Quart2D画出来的

4、图形上下文(GraphicsContext): 是一个CGContextRef类型的数据

图形上下文的作用:1)保存绘制信息、绘图状态;

2)决定绘制的输出目标(绘制到什么地方去:可以是pdf文件、图片或显示器的窗口上)

相同的一套绘图序列,指定不同的GraphicsContext, 就可将相同的图像绘制到不同的目标上,

Quartz2D提供了以下几种类型的Graphics Context :

1)Bitmap  Graphics  Context

2)PDF  Graphics Context

3)Window Graphics  Context

4)Layer  Graphics  Context

5)Printer  Graphics  Context

5、自定义控件

如何利用Quartz2D自定义UI控件,然后绘制东西到View上?

-->需要图形上下文,保存绘图信息; 然后图形上下文必须跟view相关联,才能将内容绘制到View上面

自定义UI控件的步骤:

1)新建一个类,继承自UIView

2)实现  - (void) drawRect: (CGRect)rect;  方法,然后在这个方法中,可以去的跟当前view相关联的图形上下文; 绘制相应的图形内容(绘制时产生的线条称为路径,路径由一个或多个线段或曲线段组成);利用图形上下文将绘制的所有内容渲染显示到view上面

为什么要实现drawRect: 方法才能绘图到view上?

--》 因为在drawRect: 方法中才能取得跟view相关联的图形上下文

drawRect: 方法在什么时候被调用?

--》当view第一次显示到屏幕上时(被加到UIWindow上现实出来)

--》调用view的setNeedsDisplay或者setNeedsDisplayInRect: 时

6、view内部有个layer(图层)属性,drawRect: 方法中取得的是一个Layer  Graphics  Context, 因此,绘制的东西其实是绘制到view的layer上去了。  view之所以能现实东西,完全是因为它内部的layer

7、Quartz2D绘图的代码步骤(举例):

1)活的图形上下文: CGContextRef  ctx =  UIGraphicsGetCurrentContext();

2)  拼接路径(假如一条线段):

CGContextMoveToPoint(ctx, 10, 10);   //线段起点坐标(10, 10)

CGContextAddLineToPoint(ctx,  100, 100);  //线段绘制到坐标(100, 100)

3)绘制路径(渲染): CGContextStrokePath(ctx);   //CGContextFillPath(ctx);

8、常用拼接路径函数

1)新建一个起点:void  CGContextMoveToPoint(CGContextRef c, CGFloat x, CGFloat y)

2)添加新的线段到某个点:void  CGContextAddLineToPoint(CGContextRef c, CGFloat x, CGFloat y)

3)添加一个矩形: void  CGContextAddRect(CGContextRef c, CGRect rect)

4)添加一个椭圆:void  CGContextAddEllipseInRect(CGContextRef context, CGRect rect)

5)添加一个圆弧:void  CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)

6)Mode参数决定绘制的模式: void  CGContextDrawPath(CGContextRef c, CGPathDrawingMode mode)

7)绘制空心路径: void  CGContextStrokePath(CGContextRef c)

8)绘制实心路径: void  CGContextFillPath(CGContextRef c)

一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

9)将当前的上下文 Copy一份,保存到栈顶(那个栈叫做图形上下文栈):  void  CGContextSaveGState(CGContextRef c)

10)将栈顶的上下文出栈,替换掉当前的上下文: void  CGContextRestoreGState(CGContextRef c)

9 、 示例代码

效果截图

Quartz2D复习(一)---  基础知识 / 绘制线段圆弧 / 图片水印 / 截图

自定义UIView代码, 自定义View名称为:Quarz2DView

Quarz2DView.h:

#import <UIKit/UIKit.h>

@interface Quarz2DView : UIView

@end

Quarz2DView.m文件代码:

 #import "Quarz2DView.h"

 @interface Quarz2DView()

 @property (nonatomic, retain) UILabel *lblProgress;
@property (nonatomic, retain) UISlider *slider; //进度条
@property (nonatomic, assign) CGFloat snowHeight; //雪花的高度 @end @implementation Quarz2DView - (instancetype)init{
if (self = [super init]){
UISlider *slider = [[UISlider alloc] init];
self.slider = slider;
self.slider.frame = CGRectMake(, , , );
[self.slider addTarget:self action:@selector(changeProgress:) forControlEvents:UIControlEventValueChanged];
[self addSubview: slider]; CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)];
link.frameInterval = ; //默认是1,表示一秒中刷新屏幕60次,60hz; 设为2,则每秒刷新30次
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
NSLog(@"init");
return self;
} /*layoutSubviews在以下情况下会被调用:
1、init初始化不会触发layoutSubviews
2、addSubview会触发layoutSubviews
3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化
4、滚动一个UIScrollView会触发layoutSubviews
5、旋转Screen会触发父UIView上的layoutSubviews事件
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
*/
- (void)layoutSubviews{
//NSLog(@"layoutSubviews...");
} //利用xlb创建的时候会调用这个方法
- (void)awakeFromNib{
NSLog(@"利用xlb创建控件");
} // Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
[self drawOne]; //绘制多根线段
[self drawTwo]; //绘制带宽度的线段
[self drawThree]; //绘制实体三角形
[self drawFour]; //绘制方形、圆形、圆弧形
[self drawFive]; //画分布率圆,由几部分扇形组成
[self drawSix]; //画进度条
[self drawSeven]; //画文字和图片, 椭圆
[self drawEight]; //画雪花
[self drawNine]; //演示图形上下文栈
//[self drawTen]; //演示画图旋转、缩放、偏移
} //绘制多个线段
- (void)drawOne{
//1、获得上下文对象
CGContextRef ctr = UIGraphicsGetCurrentContext();
//2、拼接路径
UIBezierPath *path = [UIBezierPath bezierPath];
//3、开始画起点
[path moveToPoint:CGPointMake(, )];
//4、画线段
[path addLineToPoint:CGPointMake(, )];
[path addLineToPoint:CGPointMake(, )];
[path closePath]; //关闭路径,相当于:[path addLineToPoint:CGPointMake(10, 10)];
//5、将路径添加到图形上下文中
CGContextAddPath(ctr, path.CGPath);
//6、将图形上下文渲染到视图上
CGContextStrokePath(ctr); //绘制线段的三种方式
// // //第一种方式
// // //1.1、获取图形上下文
// // CGContextRef crf = UIGraphicsGetCurrentContext();
// // //1.2、画起点和终点
// // CGContextMoveToPoint(crf, 0, 0);
// // CGContextAddLineToPoint(crf, 100, 100);
// // //1.3、渲染
// // CGContextStrokePath(crf);
//
// //第二种方式
// //2.1、获取图形上下文
// CGContextRef crf2 = UIGraphicsGetCurrentContext();
// //2.2、起点和终点
// CGMutablePathRef pathRef = CGPathCreateMutable();
// CGPathMoveToPoint(pathRef, nil, 0, 0);
// CGPathAddLineToPoint(pathRef, nil, 100, 100);
// CGContextAddPath(crf2, pathRef);
// //2.3、渲染
// CGContextStrokePath(crf2);
// //2.4、释放
// CGPathRelease(pathRef);
//
// // //第三种方式:使用OC对象,前面两种方式是用C语言函数
// // UIBezierPath *bezi = [UIBezierPath bezierPath];
// // [bezi moveToPoint:CGPointMake(0, 0)]; //起点
// // [bezi addLineToPoint:CGPointMake(100, 100)]; //终点
// // [bezi stroke]; //渲染
} //绘制一根带宽度和颜色的线段
- (void)drawTwo{
//1、获得上下文对象
CGContextRef ctr = UIGraphicsGetCurrentContext();
/*enum CGLineCap { //线段帽子,单点
kCGLineCapButt,
kCGLineCapRound, //圆形
kCGLineCapSquare //方形
};*/
CGContextSetLineCap(ctr, kCGLineCapRound); //设置线段结束点:帽子
/*enum CGLineJoin { //线段转折点
kCGLineJoinMiter, //斜街,转折点很尖
kCGLineJoinRound, //转折圆角
kCGLineJoinBevel //转折点线段
};*/
CGContextSetLineJoin(ctr, kCGLineJoinRound); //设置线段转折点
CGContextSetLineWidth(ctr, ); //设置路径的宽度
CGContextSetRGBStrokeColor(ctr, 1.0f, 0.8f, 0.1f, ); //设置颜色
//2、拼接路径
UIBezierPath *path = [UIBezierPath bezierPath];
//3、开始画起点
[path moveToPoint:CGPointMake(, )];
//4、画线段
[path addLineToPoint:CGPointMake(, )];
[path addLineToPoint:CGPointMake(, )];
//5、将路径添加到图形上下文中
CGContextAddPath(ctr, path.CGPath);
//6、将图形上下文渲染到视图上
CGContextStrokePath(ctr);
} //绘制一个实体三角形
- (void)drawThree{
//1、图形上下文
CGContextRef ctr = UIGraphicsGetCurrentContext();
[[UIColor purpleColor] setFill]; //设置实体颜色
[[UIColor redColor] setStroke]; //设置边框颜色
CGContextSetLineWidth(ctr, ); //设置边框宽度 //2、拼接路径对象
UIBezierPath *path = [UIBezierPath bezierPath];
//3、绘制路径
[path moveToPoint:CGPointMake(, )];
[path addLineToPoint:CGPointMake(, )];
[path addLineToPoint:CGPointMake(, )];
[path closePath];
//4、把路径添加到上下文对象中
CGContextAddPath(ctr, path.CGPath); //5、将图形上下文渲染到视图上
// CGContextFillPath(ctr); //既填充又描边,不能用这个
CGContextDrawPath(ctr, kCGPathEOFillStroke);
/*
enum CGPathDrawingMode {
kCGPathFill, //非零绕数规则
kCGPathEOFill, //奇偶规则
kCGPathStroke, //描边
kCGPathFillStroke,//填充又描边
kCGPathEOFillStroke //填充描边
};*/
} //绘制正方形、圆形、圆角方形
- (void)drawFour{
CGContextRef ctr = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctr, );
[[UIColor greenColor] set]; //方形 左上角(10, 90) ,宽高都是60
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(, , , )];
CGContextAddPath(ctr, path.CGPath); //圆形,左上角(10, 90) 圆心(40, 120) 半径30 cornerRadius < 30则是圆角方形,>=30 则是圆形
UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(, , , ) cornerRadius:];
CGContextAddPath(ctr, path2.CGPath);
//圆角方形
UIBezierPath *path3 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(, , , ) cornerRadius:];
CGContextAddPath(ctr, path3.CGPath);
//圆角矩形
UIBezierPath *path4 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(, , , ) cornerRadius:];
CGContextAddPath(ctr, path4.CGPath);
//设置某一个角圆形
UIBezierPath *path5 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(, , , ) byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(, )];
CGContextAddPath(ctr, path5.CGPath);
/*typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
UIRectCornerTopLeft = 1 << 0, //顶部左边
UIRectCornerTopRight = 1 << 1,//顶部右边圆角,其他直角
UIRectCornerBottomLeft = 1 << 2,//地步左边圆角
UIRectCornerBottomRight = 1 << 3,//底部右边圆角
UIRectCornerAllCorners = ~0UL //圆形
};*/ //画圆弧 clockwise: 顺时针还是逆时针
UIBezierPath *path6 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(, ) radius: startAngle: endAngle:M_PI clockwise:YES];//顺时针从2π到π,圆心(160,100)
CGContextAddPath(ctr, path6.CGPath); CGContextStrokePath(ctr); //画一段圆弧实体
UIBezierPath *path7 = [UIBezierPath bezierPathWithArcCenter:CGPointMake(, ) radius: startAngle:2.8f endAngle: clockwise:NO]; //逆时针从0到2.8,圆心(160,100)
CGContextAddPath(ctr, path7.CGPath);
CGContextFillPath(ctr);
} //y:150 画一个圆,有几个扇形组成,比如由四个百分比组成:55 + 30 + 12 + 3
- (void)drawFive{
CGContextRef ctr = UIGraphicsGetCurrentContext();
//半径50, 圆心(240, 210), 左上角(190, 160), 右上角(290, 210), 左下角(190, 260), 右下角(290, 260) CGPoint center = CGPointMake(, ); //圆心
CGFloat radius = ; //1、先画55%扇形
[[UIColor purpleColor] setFill];
CGFloat endAngle = M_PI * * / ;
UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle: endAngle:endAngle clockwise:YES];
[path1 addLineToPoint:center]; //原来扇形是这样画的
CGContextAddPath(ctr, path1.CGPath);
//渲染
CGContextFillPath(ctr);
//加个文字说明
UILabel *lbl1 = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
lbl1.textAlignment = NSTextAlignmentCenter;
lbl1.font = [UIFont systemFontOfSize:];
lbl1.text = @"55.00%";
[self addSubview:lbl1]; //2、再画第二个扇形:30%
[[UIColor greenColor] setFill];
CGFloat endAngle2 = M_PI * * / + endAngle;
UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:endAngle endAngle:endAngle2 clockwise:YES];
[path2 addLineToPoint:center]; //原来扇形是这样画的
CGContextAddPath(ctr, path2.CGPath);
//渲染
CGContextFillPath(ctr);
//加个文字说明
UILabel *lbl2 = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
lbl2.textAlignment = NSTextAlignmentCenter;
lbl2.font = [UIFont systemFontOfSize:];
lbl2.text = @"30.00%";
[self addSubview:lbl2]; //3、再画第三个扇形:12%
[[UIColor yellowColor] setFill];
CGFloat endAngle3 = M_PI * * / + endAngle2;
UIBezierPath *path3 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:endAngle2 endAngle:endAngle3 clockwise:YES];
[path3 addLineToPoint:center];
CGContextAddPath(ctr, path3.CGPath);
//渲染
CGContextFillPath(ctr);
//加个文字说明
UILabel *lbl3 = [[UILabel alloc] initWithFrame:CGRectMake(, , , )];
lbl3.textAlignment = NSTextAlignmentCenter;
lbl3.font = [UIFont systemFontOfSize:];
lbl3.text = @"12.00%";
[self addSubview:lbl3]; //4、再画第四个扇形:3%
[[UIColor blueColor] setFill];
UIBezierPath *path4 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:endAngle3 endAngle: clockwise:YES];
[path4 addLineToPoint:center];
CGContextAddPath(ctr, path4.CGPath);
//渲染
CGContextFillPath(ctr); //第二种方式画一个扇形组合圆
NSArray *arr = @[@, @, @, @, @];
CGFloat startA =, endA = ;
center = CGPointMake(, );
radius = ; for (int i = ; i < arr.count; i++) {
startA = endA;
endA = startA + M_PI * * [[arr objectAtIndex:i] floatValue] / ;
[[self randomColor] setFill];
UIBezierPath *p = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
[p addLineToPoint:center];
CGContextAddPath(ctr, p.CGPath);
CGContextFillPath(ctr); //渲染
}
} //进度条演示
- (UILabel *)lblProgress{
if (_lblProgress == nil){
_lblProgress = [[UILabel alloc] init];
_lblProgress.frame = CGRectMake(, , , );
_lblProgress.textAlignment = NSTextAlignmentCenter;
_lblProgress.font = [UIFont systemFontOfSize:];
_lblProgress.text = @"00.00%";
[self addSubview:_lblProgress];
}
return _lblProgress;
}
//可拖拽进度条
- (void)drawSix{
CGContextRef ctr = UIGraphicsGetCurrentContext();
[self lblProgress]; //3π/2顺时针走 2π走一个圈360度 2π : 100进度
CGFloat startAngle = M_PI * 1.5; //开始角度
CGFloat endAngle = M_PI * 1.5 + M_PI * * self.slider.value;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(, ) radius: startAngle:startAngle endAngle:endAngle clockwise:YES];
CGContextAddPath(ctr, path.CGPath);
CGContextStrokePath(ctr);
} //进度条事件
- (void)changeProgress:(UISlider *)sender{
self.lblProgress.text = [NSString stringWithFormat:@"%.2f%%", sender.value * ];
//调用方法重绘
[self setNeedsDisplay];
} //生成一个随机颜色
- (UIColor *)randomColor{
/*
颜色有两种表示方法:RGB RGBA
RGB 24
R、G、B每个颜色通道8位
8的二进制255
R、G、B每个颜色的取值范围0-255
120/255.0
*/
CGFloat r = arc4random_uniform() / 255.0;
CGFloat g = arc4random_uniform() / 255.0;
CGFloat b = arc4random_uniform() / 255.0;
return [UIColor colorWithRed:r green:g blue:b alpha:];
} //画文字和图片Y: 280 画一个椭圆
- (void)drawSeven{
CGContextRef ctr = UIGraphicsGetCurrentContext();
[[UIColor greenColor] set];
//先画一根分割线
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(, , , )];
CGContextAddPath(ctr, path.CGPath);
CGContextFillPath(ctr); //画文字
NSString *str = @"君不见黄河之水天上来, 奔流到海不复回;君不见高堂明镜悲白发,朝如青丝暮成雪";
NSDictionary *dicts = @{UITextAttributeFont: [UIFont systemFontOfSize:],
UITextAttributeTextColor: [UIColor purpleColor]};
[str drawInRect:CGRectMake(, , , ) withAttributes:dicts]; //画图片 : 可以想象UIImageView是如何展示图片的
UIImage *img = [UIImage imageNamed:@"paddle"];
[img drawAtPoint:CGPointMake(, )]; //画椭圆
UIBezierPath *path2 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, path2.CGPath);
UIBezierPath *path3 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, path3.CGPath);
UIBezierPath *path4 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, path4.CGPath);
UIBezierPath *path5 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, path5.CGPath);
CGContextStrokePath(ctr);
} //画一个雪花飘落
- (void)drawEight{
self.snowHeight += ;
UIImage *img = [UIImage imageNamed:@"雪花"];
[img drawAtPoint:CGPointMake(, self.snowHeight)]; UIImage *img2 = [UIImage imageNamed:@"雪花"];
[img2 drawAtPoint:CGPointMake(, self.snowHeight + )]; UIImage *img3 = [UIImage imageNamed:@"雪花"];
[img3 drawAtPoint:CGPointMake(, self.snowHeight + )]; if (self.snowHeight > ){
self.snowHeight = ;
}
} //图形上下文栈:可以把图形上下文保存到栈里,到了需要的时候再取出来
- (void)drawNine{
CGContextRef ctr = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctr); //将此时的图形上下文存入栈里 //原图形上下文画图是这样的
UIBezierPath *oldPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, oldPath.CGPath);
CGContextStrokePath(ctr); //渲染 //变化图形上下文
CGContextSetLineWidth(ctr, );
[[UIColor redColor] set];
UIBezierPath *newPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, newPath.CGPath);
CGContextStrokePath(ctr); //渲染 //取出原图形上下文覆盖当前图形上下文
CGContextRestoreGState(ctr); //原图形上下文画图
UIBezierPath *oldPath2 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , , )];
CGContextAddPath(ctr, oldPath2.CGPath);
CGContextStrokePath(ctr); //渲染
} //画图形偏移、放大、旋转
- (void)drawTen{
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext(); // 注意:你的路径一定放在上下文矩阵操作之后
// 平移上下文
CGContextTranslateCTM(ctx, , ); // 旋转上下文
CGContextRotateCTM(ctx, M_PI_4); // 缩放上下文
CGContextScaleCTM(ctx, 0.5, 1.2); // 2.拼接路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-, -, , )]; // 3.把路径添加到上下文
CGContextAddPath(ctx, path.CGPath); [[UIColor yellowColor] set]; // 4.渲染
CGContextFillPath(ctx);
} /*
字符属性 字符属性可以应用于 attributed string 的文本中。 NSString *const NSFontAttributeName;(字体) NSString *const NSParagraphStyleAttributeName;(段落) NSString *const NSForegroundColorAttributeName;(字体颜色) NSString *const NSBackgroundColorAttributeName;(字体背景色) NSString *const NSLigatureAttributeName;(连字符) NSString *const NSKernAttributeName;(字间距) NSString *const NSStrikethroughStyleAttributeName;(删除线) NSString *const NSUnderlineStyleAttributeName;(下划线) NSString *const NSStrokeColorAttributeName;(边线颜色) NSString *const NSStrokeWidthAttributeName;(边线宽度) NSString *const NSShadowAttributeName;(阴影)(横竖排版) NSString *const NSVerticalGlyphFormAttributeName; 常量 1> NSFontAttributeName(字体) 该属性所对应的值是一个 UIFont 对象。该属性用于改变一段文本的字体。如果不指定该属性,则默认为12-point Helvetica(Neue)。 2> NSParagraphStyleAttributeName(段落) 该属性所对应的值是一个 NSParagraphStyle 对象。该属性在一段文本上应用多个属性。如果不指定该属性,则默认为 NSParagraphStyle 的defaultParagraphStyle 方法返回的默认段落属性。 3> NSForegroundColorAttributeName(字体颜色) 该属性所对应的值是一个 UIColor 对象。该属性用于指定一段文本的字体颜色。如果不指定该属性,则默认为黑色。 4> NSBackgroundColorAttributeName(字体背景色) 该属性所对应的值是一个 UIColor 对象。该属性用于指定一段文本的背景颜色。如果不指定该属性,则默认无背景色。 5> NSLigatureAttributeName(连字符) 该属性所对应的值是一个 NSNumber 对象(整数)。连体字符是指某些连在一起的字符,它们采用单个的图元符号。0 表示没有连体字符。1 表示使用默认的连体字符。2表示使用所有连体符号。默认值为 1(注意,iOS 不支持值为 2)。 6> NSKernAttributeName(字间距) 该属性所对应的值是一个 NSNumber 对象(整数)。字母紧排指定了用于调整字距的像素点数。字母紧排的效果依赖于字体。值为 0 表示不使用字母紧排。默认值为0。 7> NSStrikethroughStyleAttributeName(删除线) 该属性所对应的值是一个 NSNumber 对象(整数)。该值指定是否在文字上加上删除线,该值参考“Underline Style Attributes”。默认值是NSUnderlineStyleNone。 8> NSUnderlineStyleAttributeName(下划线) 该属性所对应的值是一个 NSNumber 对象(整数)。该值指定是否在文字上加上下划线,该值参考“Underline Style Attributes”。默认值是NSUnderlineStyleNone。 9> NSStrokeColorAttributeName(边线颜色) 该属性所对应的值是一个 UIColor 对象。如果该属性不指定(默认),则等同于 NSForegroundColorAttributeName。否则,指定为删除线或下划线颜色。更多细节见“Drawing attributedstrings that are both filled and stroked”。 10> NSStrokeWidthAttributeName(边线宽度) 该属性所对应的值是一个 NSNumber 对象(小数)。该值改变描边宽度(相对于字体size 的百分比)。默认为 0,即不改变。正数只改变描边宽度。负数同时改变文字的描边和填充宽度。例如,对于常见的空心字,这个值通常为3.0。 11> NSShadowAttributeName(阴影) 该属性所对应的值是一个 NSShadow 对象。默认为 nil。 12> NSVerticalGlyphFormAttributeName(横竖排版) 该属性所对应的值是一个 NSNumber 对象(整数)。0 表示横排文本。1 表示竖排文本。在 iOS 中,总是使用横排文本,0 以外的值都未定义。 */ @end

自定义控制器展示自定义Quarz2DView

Quartz2DViewController.h 文件:

#import <UIKit/UIKit.h>

@interface Quartz2DViewController : UIViewController

@end

Quartz2DViewController.m文件代码:

 #import "Quartz2DViewController.h"
#import "Quarz2DView.h"
#import "Quartz2DControllerTwo.h" @interface Quartz2DViewController () @end @implementation Quartz2DViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]]; //设置白色背景 Quarz2DView *view = [Quarz2DView new];
view.frame = CGRectMake(, , , );
[view setBackgroundColor:[UIColor grayColor]];
view.alpha = 0.9; //默认时1,不透明
[self.view addSubview:view]; //增加两个按钮: 上一页按钮
UIButton *returnBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[returnBtn setTitle:@"上一页" forState:UIControlStateNormal];
returnBtn.frame = CGRectMake(, , , );
[returnBtn addTarget:self action:@selector(returnLastPage) forControlEvents:UIControlEventTouchUpInside];
[returnBtn setBackgroundColor:[UIColor purpleColor]];
[self.view addSubview:returnBtn]; //下一页按钮
UIButton *nextBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[nextBtn setTitle:@"下一页" forState:UIControlStateNormal];
nextBtn.frame = CGRectMake(, , , );
[nextBtn addTarget:self action:@selector(nextController) forControlEvents:UIControlEventTouchUpInside];
[nextBtn setBackgroundColor:[UIColor purpleColor]];
[self.view addSubview:nextBtn];
} //返回上一页
- (void)returnLastPage{
[self dismissViewControllerAnimated:YES completion:nil];
} //进入下一个控制器
- (void)nextController{
Quartz2DControllerTwo *control = [[Quartz2DControllerTwo alloc] init];
[self presentViewController:control animated:YES completion:nil];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /*
#pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/ @end

---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------

给图片添加水印,裁剪图片,效果截图:

Quartz2D复习(一)---  基础知识 / 绘制线段圆弧 / 图片水印 / 截图

自定义控制器Quartz2DControllerTwo.h 文件:

#import <UIKit/UIKit.h>

@interface Quartz2DControllerTwo : UIViewController

@end

Quartz2DControllerTwo.m文件代码:

 #import "Quartz2DControllerTwo.h"
#import "Quartz2DControllerThree.h" @interface Quartz2DControllerTwo () @end @implementation Quartz2DControllerTwo - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]]; [self testImageContext]; //测试图形上下文的用法
[self clipImage]; //裁剪图片 //添加上一页和下一页按钮
UIButton *preBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[preBtn setTitle:@"上一页" forState:UIControlStateNormal];
preBtn.frame = CGRectMake(, , , );
[preBtn setBackgroundColor:[UIColor purpleColor]];
[preBtn addTarget:self action:@selector(prePage) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:preBtn]; UIButton *nextBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[nextBtn setTitle:@"下一页" forState:UIControlStateNormal];
nextBtn.frame = CGRectMake(, , , );
[nextBtn setBackgroundColor:[UIColor purpleColor]];
[nextBtn addTarget:self action:@selector(nextPage) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:nextBtn];
} //图片上下文应用:将图片缓存到图片上下文,然后合成新的图片,并保存下来,关闭图片上下文,也可以把图片保存在本地
- (void)testImageContext{
//1、创建图片
UIImage *img = [UIImage imageNamed:@"first"];
//2、打开图片上下文 opaque:YES表示透明, NO表示不透明 设置图形上下文的尺寸
UIGraphicsBeginImageContextWithOptions(img.size, NO, 0.0);
//3、将图片写入到图片上下文中
[img drawAtPoint:CGPointZero];
//4、将文字写入到图片上下文中
NSString *str = @"给图片加水印";
NSDictionary *dicts = @{NSFontAttributeName: [UIFont systemFontOfSize:],
NSForegroundColorAttributeName: [UIColor purpleColor]}; //设置字体属性
[str drawAtPoint:CGPointMake(img.size.width - , img.size.height - ) withAttributes:dicts];
//5、从图形上下文中获取新的图片
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
//6、关闭图形上下文
UIGraphicsEndImageContext(); //将新图片显示出来
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(, , img.size.width, img.size.height)];
imgView.image = newImg;
[self.view addSubview:imgView];
//将新图片保存到指定路径
// NSData *data = UIImagePNGRepresentation(newImg);
// [data writeToFile:@"/Users/tanxiaoming/Desktop/tan.png" atomically:YES];
} //裁剪图片
- (void)clipImage{
UIImage *img = [UIImage imageNamed:@"first"];
UIGraphicsBeginImageContextWithOptions(img.size, YES, 0.0); //画圆弧
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , img.size.width, img.size.height)];
[path addClip]; //裁剪
//将图片画在上下文中
[img drawAtPoint:CGPointZero]; //从当前图片上下文中获取新图片
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
//关闭图形上下文
UIGraphicsEndImageContext(); //现实图片
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(, + img.size.height, newImg.size.width, newImg.size.height)];
imgView.image = newImg;
[self.view addSubview:imgView];
} //返回上一页
- (void)prePage{
[self dismissViewControllerAnimated:YES completion:nil];
} //下一页
- (void)nextPage{
Quartz2DControllerThree *controller = [[Quartz2DControllerThree alloc] init];
[self presentViewController:controller animated:YES completion:nil];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /*
#pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/ @end

---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------

屏幕截图,效果截图:

Quartz2D复习(一)---  基础知识 / 绘制线段圆弧 / 图片水印 / 截图

Quartz2DControllerThree.h文件:

#import <UIKit/UIKit.h>

@interface Quartz2DControllerThree : UIViewController

@end

Quartz2DControllerThree.m文件代码:

 #import "Quartz2DControllerThree.h"

 @interface Quartz2DControllerThree ()

 @property (nonatomic, retain) UIImageView *imgView;

 @end

 @implementation Quartz2DControllerThree

 - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor whiteColor]]; //设置背景颜色 [self clipImage]; //裁剪图片 UIButton *preBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[preBtn setTitle:@"上一页" forState:UIControlStateNormal];
[preBtn setBackgroundColor:[UIColor purpleColor]];
[preBtn setFrame:CGRectMake(, , , )];
[preBtn addTarget:self action:@selector(prePage) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:preBtn]; //屏幕截图按钮
UIButton *screenBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[screenBtn setFrame:CGRectMake(, , , )];
[screenBtn setTitle:@"屏幕截图" forState:UIControlStateNormal];
[screenBtn setBackgroundColor:[UIColor grayColor]];
[screenBtn addTarget:self action:@selector(screenImg) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:screenBtn]; } - (UIImageView *)imgView{
if (_imgView == nil){
_imgView = [[UIImageView alloc] initWithFrame:CGRectMake(, , , )];
_imgView.contentMode = UIViewContentModeScaleAspectFit; //自适应图片大小
[self.view addSubview:_imgView];
}
return _imgView;
} //裁剪图片
- (void)clipImage{
UIImage *img = [UIImage imageNamed:@"first"];
CGFloat border = ;
CGFloat radius = * border + (img.size.width > img.size.height ? img.size.height : img.size.width); //先画大圆
//开启图形上下文
UIGraphicsBeginImageContextWithOptions(CGSizeMake(radius, radius), NO, 0.0);
CGContextRef ctr = UIGraphicsGetCurrentContext();//获取上下文
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(, , radius, radius)];
CGContextAddPath(ctr, path.CGPath); //添加到上下文
[[UIColor purpleColor] set]; //设置颜色
CGContextFillPath(ctr); //渲染 //设置小圆
UIBezierPath *smallPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(border, border, radius - * border, radius - * border)]; [smallPath addClip]; //裁剪 [img drawAtPoint:CGPointMake(border, border)]; //把图画到图形上下文中
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext(); //获取新图片 UIGraphicsEndImageContext(); //关闭图形上下文 UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(, , radius, radius)];
imgView.image = newImg;
[self.view addSubview:imgView];
} //屏幕截图
- (void)screenImg{
//1、开启图形上下文
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
//2、获取上下文
CGContextRef ctr = UIGraphicsGetCurrentContext();
//3、将self.view的图层渲染到上下文,图层只能渲染不能draw
[self.view.layer renderInContext:ctr];
//4、从图形上下文获取新图片
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
//5、关闭图形上下文
UIGraphicsEndImageContext();
//6、显示或保存 // NSData *data = UIImagePNGRepresentation(img);
// [data writeToFile:@"/Users/tanxiaoming/Desktop/xiao.png" atomically:YES]; self.imgView.image = img;
} - (void)prePage{
[self dismissViewControllerAnimated:YES completion:nil];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /*
#pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/ @end