IOS开发教程第一季之UI进阶day6合并IOS学习017--绘图2
1.矩阵操作
矩阵操作主要包括缩放、旋转、平移
1、缩放
CGContextScaleCTM(<CGContextRef _Nullable c#>, <CGFloat sx#>, <CGFloat sy#>)
2、旋转
CGContextRotateCTM(<#CGContextRef _Nullable c#>, <#CGFloat angle#>)
3、平移
CGContextTranslateCTM(<#CGContextRef _Nullable c#>, <#CGFloat tx#>, <#CGFloat ty#>)
矩阵操作一定要放在添加路径之前
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//1、获取上下文
CGContextRef ctx =UIGraphicsGetCurrentContext();
//旋转、缩放、平移,直接针对CGContextRef对象,即直接矩阵操作画布放在绘图之前
//CGContextRotateCTM(ctx, M_PI_4);
//CGContextScaleCTM(ctx, 0.5, 0.5);//后面连个参数是缩放系数
CGContextTranslateCTM(ctx, 150, 150);
//2、拼接路径,同时把路径添加到上下文中
CGContextAddArc(ctx, 150, 150, 100, 0, 2*M_PI, YES);
CGContextMoveToPoint(ctx, 0, 0);
CGContextAddLineToPoint(ctx, 300, 300);
//3、设置线宽
CGContextSetLineWidth(ctx, 10);
//3、渲染
CGContextStrokePath(ctx);
}
@end
2.图形上下文栈
图形的样式信息都是放置在上下文里的
将当前【图形上下文】中的“绘图状态”信息保存到“栈”中
CGContextSaveGState(CGContextRef ctx);
将栈顶的“绘图状态”出栈,替换掉当前的“图形上下文”中的“绘图状态”
CGContextRestoreGState(CGContextRef ctx);
范例:
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//1、获取上下文
CGContextRef ctx =UIGraphicsGetCurrentContext();
//备份一下上下文中的样式信息
CGContextSaveGState(ctx);
//旋转、缩放、平移,直接针对CGContextRef对象,即直接矩阵操作画布放在绘图之前
//CGContextRotateCTM(ctx, M_PI_4);
//CGContextScaleCTM(ctx, 0.5, 0.5);//后面连个参数是缩放系数
//CGContextTranslateCTM(ctx, 150, 150);
//2、拼接路径,同时把路径添加到上下文中
CGContextAddArc(ctx, 150, 150, 100, 0, 2*M_PI, YES);
CGContextMoveToPoint(ctx, 0, 0);
CGContextAddLineToPoint(ctx, 300, 300);
//3、设置线宽
CGContextSetLineWidth(ctx, 10);
[[UIColor redColor]set];
//3、渲染
CGContextStrokePath(ctx);
CGContextRestoreGState(ctx);
CGContextMoveToPoint(ctx, 20, 20);
CGContextAddLineToPoint(ctx, 250, 20);
CGContextStrokePath(ctx);
}
@end
横线是恢复的样式(默认,黑色,细线)
3.绘制文字
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//1、文字
NSString* str=@"终于等来疫情防控等级下调";
//2、绘制,通过字符串对象调用draw方 法
[str drawAtPoint:CGPointZero withAttributes:nil];
}
@end
在固定区域里绘制文字
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//1、文字
NSString* str=@"终于等来疫情防控等级下调于等来疫情防控等级下调于等来疫情防控等级下调于等来疫情防控等级下调于等来疫情防控等级下调于等来疫情防控等级下调于等来疫情防控等级下调于等来疫情防控等级下调";
//2、绘制,通过字符串对象调用draw方 法
//[str drawInRect:rect withAttributes:nil];//rect是画布尺寸
[str drawInRect:CGRectMake(0, 0, 150, 200) withAttributes:nil];
@end
绘制文字属性使用一个字典来存储
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//1、文字
NSString* str=@"终于等来疫情防控等级下调";
NSShadow* shadow= [[NSShadow alloc]init];
shadow.shadowOffset=CGSizeMake(9, 9);//阴影的偏移量
shadow.shadowBlurRadius=10;//模糊
shadow.shadowColor=[UIColor grayColor];//阴影色
//2、绘制,通过字符串对象调用draw方法
//如果希望有文字阴影则去掉背景色即可
[str drawAtPoint:CGPointZero withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:40],NSForegroundColorAttributeName:[UIColor redColor],NSBackgroundColorAttributeName:[UIColor greenColor],NSUnderlineStyleAttributeName:@(1),NSShadowAttributeName:shadow}];//设置字体,颜色,背景等最后一个参数传入一个字典
}
@end
4.绘制图片
1、绘制小图
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//绘制图片(小图)
UIImage* image=[UIImage imageNamed:@"me"];
//将图形绘制到画布上,这里并不用出现画布
//[image drawAtPoint:CGPointZero];//从零点位置绘制
//[image drawAtPoint:CGPointMake(15, 36)];
//绘制到某个区域
//[image drawInRect:rect];
//平铺到某个区域
[image drawAsPatternInRect:rect];//rect是整个视图view
}
@end
2、绘制大图
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//绘制图片(大图)大于view
UIImage* image=[UIImage imageNamed:@"dst2"];
//将图形绘制到画布上,这里并不用出现画布
[image drawAtPoint:CGPointZero];//从零点位置绘制
//[image drawAtPoint:CGPointMake(15, 36)];
//绘制到某个区域
//[image drawInRect:rect];
//平铺到某个区域
//[image drawAsPatternInRect:rect];//rect是整个视图view
}
@end
绘制大图,本身并没有特别的不同
5.模拟ImageView
只有默认init方法的时候
创建FRImageView类并继承自UIView(注意不是继承UIImageView)
FRImageView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRImageView : UIView
@property(nonatomic,strong)UIImage* image;
@end
NS_ASSUME_NONNULL_END
FRImageView.m
#import "FRImageView.h"
@implementation FRImageView
//重写image属性的set方法
-(void)setImage:(UIImage *)image{
_image=image;
//重绘图片
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
//把传过来的图片绘制到屏幕上
[self.image drawInRect:rect];
}
@end
ViewController.m
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//绘制图片(大图)大于view
FRImageView* imageview=[[FRImageView alloc]init];
imageview.frame=CGRectMake(50, 50, 200, 200);
imageview.image=[UIImage imageNamed:@"me"];
self.imageView=imageview;
[self.view addSubview:self.imageView];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.imageView.image=[UIImage imageNamed:@"Press"];
}
@end
使用自定义initWithImage方法的时候
FRImageView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRImageView : UIView
@property(nonatomic,strong)UIImage* image;
- (instancetype)initWithImage:(UIImage*)image;
@end
NS_ASSUME_NONNULL_END
FRImageView.m
#import "FRImageView.h"
@implementation FRImageView
//initwithIamge方法
- (instancetype)initWithImage:(UIImage*)image
{
self=[super initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
if (self) {
self.image=image;
}
return self;
}
//重写image属性的set方法
-(void)setImage:(UIImage *)image{
_image=image;
//重绘图片
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
//把传过来的图片绘制到屏幕上
[self.image drawInRect:rect];
}
@end
ViewController.m
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//绘制图片(大图)大于view
FRImageView* imageview=[[FRImageView alloc]initWithImage:[UIImage imageNamed:@"me"]];
self.imageView=imageview;
[self.view addSubview:self.imageView];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.imageView.image=[UIImage imageNamed:@"Press"];
}
@end
6.裁减上下文渲染的区域
使用CGContextClip(CGContexRef*)
思路:
1、在上下文中绘制一个要裁减的图形(裁减画布的显示区域)
2、调用CGContextClip进行裁减
3、在裁减好的上下文中再把图片绘制上去(注意绘制图片的时候,必须绘制到已经裁减出来的上下文中
)
#import "DrawView.h"
@implementation DrawView
- (void)drawRect:(CGRect)rect{
//获取图片对象
UIImage* image=[UIImage imageNamed:@"me"];
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//先绘制出显示的区域
CGContextAddArc(ctx, 150, 150, 150, 0, 2*M_PI, YES);
//裁减
CGContextClip(ctx);//因为图形重叠到了ctx上下文上,所以按照图形的尺寸进行裁减
//拉伸显示到view上
[image drawInRect:rect];
}
@end
效果:
7.图片类型的上下文
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContext(CGSizeMake(300, 300));
//获取当前的上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//拼接路径
CGContextMoveToPoint(ctx, 50, 50);
CGContextAddLineToPoint(ctx, 100, 100);
//渲染路径
CGContextStrokePath(ctx);
//通过图片类型的上下文,获取图片对象
UIImage* image=UIGraphicsGetImageFromCurrentImageContext();
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
//把获取到的图片放到图片框上
self.imageView.image=image;
}
@end
8.把图形保存到沙盒
思路:
1、把image对象转化成nsdata
2、通过data的write to file写入到沙盒中
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContext(CGSizeMake(300, 300));
//获取当前的上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//拼接路径
CGContextMoveToPoint(ctx, 50, 50);
CGContextAddLineToPoint(ctx, 100, 100);
//渲染路径
CGContextStrokePath(ctx);
//通过图片类型的上下文,获取图片对象
UIImage* image=UIGraphicsGetImageFromCurrentImageContext();
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
//把获取到的图片放到图片框上
self.imageView.image=image;
//1、把image对象转化成nsdata
NSData* data= UIImagePNGRepresentation(image);
//2、通过data的write to file 写入到沙盒中
NSString* docpath= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString* filepath=[docpath stringByAppendingPathComponent:@"my.png"];
[data writeToFile:filepath atomically:YES];
NSLog(@"%@",docpath);
}
@end
9.开启图文类型的上下文with options
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//开启一个图片类型的图形上下文
//UIGraphicsBeginImageContext(CGSizeMake(300, 300));
UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, [UIScreen mainScreen].scale);
//获取当前的上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//拼接路径
CGContextMoveToPoint(ctx, 50, 50);
CGContextAddLineToPoint(ctx, 100, 100);
//渲染路径
CGContextStrokePath(ctx);
//通过图片类型的上下文,获取图片对象
UIImage* image=UIGraphicsGetImageFromCurrentImageContext();
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
//把获取到的图片放到图片框上
self.imageView.image=image;
//1、把image对象转化成nsdata
NSData* data= UIImagePNGRepresentation(image);
//2、通过data的write to file 写入到沙盒中
NSString* docpath= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString* filepath=[docpath stringByAppendingPathComponent:@"my.png"];
[data writeToFile:filepath atomically:YES];
NSLog(@"%@",docpath);
}
@end
10.获取裁减后的图片并将其保存到相册中
需要在info.plist中设置允许相册权限
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取图片
UIImage* image=[UIImage imageNamed:@"me"];
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//绘制一个裁减的图片
CGContextAddArc(ctx, image.size.width*0.5, image.size.height*0.5, image.size.width*0.5, 0, 2*M_PI, YES);
//裁减
CGContextClip(ctx);
//把图片画上去
[image drawAtPoint:CGPointZero];
//把图片在取出来
UIImage* newImage=UIGraphicsGetImageFromCurrentImageContext();
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
//输出到imageview控件上
self.imageView.image=newImage;
//保存到相册
UIImageWriteToSavedPhotosAlbum(newImage, self,@selector(image:), NULL);
}
//必须调用这个方法而不是自定义的方法
-(void)image:(UIImage*)image diFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo{
NSLog(@"已经保存到相册了");
}
@end
11.开启图文类型的上下文with options
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取图片
UIImage* image=[UIImage imageNamed:@"me"];
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//绘制一个裁减的图片
CGContextAddArc(ctx, image.size.width*0.5, image.size.height*0.5, image.size.width*0.5, 0, 2*M_PI, YES);
//裁减
CGContextClip(ctx);
//把图片画上去
[image drawAtPoint:CGPointZero];
//把图片在取出来
UIImage* newImage=UIGraphicsGetImageFromCurrentImageContext();
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
//输出到imageview控件上
self.imageView.image=newImage;
//保存到相册
UIImageWriteToSavedPhotosAlbum(newImage, self,@selector(image:), NULL);
}
//必须调用这个方法而不是自定义的方法
-(void)image:(UIImage*)image diFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo{
NSLog(@"已经保存到相册了");
}
@end
12.带圆环的图片
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取图片
UIImage* image=[UIImage imageNamed:@"me"];
//margin边距
CGFloat margin=10;
//计算图片类型的图形上下文的大小
CGSize ctxSize=CGSizeMake(image.size.width+2*margin, image.size.height+2*margin);
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContextWithOptions(ctxSize, NO, 0);
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//绘制圆环
//计算圆心、半径
CGPoint arcCenter=CGPointMake(ctxSize.width*0.5, ctxSize.height*0.5);
CGFloat radius=(image.size.width+margin)*0.5;
//绘制圆环
CGContextAddArc(ctx, arcCenter.x, arcCenter.y, radius, 0, 2*M_PI, YES);
//设置宽度
CGContextSetLineWidth(ctx, margin);
//渲染圆环
CGContextStrokePath(ctx);
//画显示的区域
CGContextAddArc(ctx, arcCenter.x, arcCenter.y, image.size.width*0.5, 0, 2*M_PI, YES);
//裁减显示区域
CGContextClip(ctx);
//画图片
[image drawAtPoint:CGPointMake(margin, margin)];
//获取图片
image=UIGraphicsGetImageFromCurrentImageContext();
self.imageView.image=image;
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
}
//必须调用这个方法而不是自定义的方法
-(void)image:(UIImage*)image diFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo{
NSLog(@"已经保存到相册了");
}
@end
效果:
13.绘制水印
用oc方法,因此无需获取上下文
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取图片
UIImage* image=[UIImage imageNamed:@"scene"];
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//画大图
[image drawAtPoint:CGPointZero];
//创建文字
NSString* str=@"IOS学习笔记";
//画文字水印
[str drawAtPoint:CGPointMake(5, 5) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:5]}];
//获得绘制的图片
image=UIGraphicsGetImageFromCurrentImageContext();
//获得图片水印的图片
UIImage* logo=[UIImage imageNamed:@"logo"];
//画出图片水印
[logo drawAtPoint:CGPointMake(image.size.width*0.5, image.size.height*0.5)];
//取图片
image=UIGraphicsGetImageFromCurrentImageContext();
self.imageView.image=image;
//关闭一个图形类型的图形上下文
UIGraphicsEndImageContext();
}
//必须调用这个方法而不是自定义的方法
-(void)image:(UIImage*)image diFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo{
}
@end
右下角水印素材图片大了,我也没办法
14.屏幕截图
// 把当前的view放到上下文中并渲染到图片上
self.view.layer renderInContext:<#(nonnull CGContextRef)#>
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//开启一个图片类型的图形上下文
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
//获取当前的上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//截图并将view的内容放到上下文中并渲染
[self.view.layer renderInContext:ctx];
//取出照片
UIImage* image=UIGraphicsGetImageFromCurrentImageContext();
//写入到imageview
self.imageView.image=image;
//关闭上下文
UIGraphicsEndImageContext();
}
@end
效果
本文地址:https://blog.csdn.net/weixin_43745804/article/details/107476860
推荐阅读
-
IOS开发教程第一季之UI进阶day6合并IOS学习017--绘图2
-
IOS开发教程第一季之UI基础day9合并IOS学习009仿QQ界面(UITableView静态单元格)、仿QQ好友列表
-
IOS开发教程第一季之UI进阶day2合并IOS学习013--App启动过程、多控制器管理
-
IOS开发教程第一季之UI进阶day8合并IOS学习019--敲击、长按、轻扫、旋转,CALayer、锚点,CADisolayLink刷新,核心动画,关键帧动画,组动画,转场动画,画板案例
-
IOS开发教程第一季之UI基础day9合并IOS学习009仿QQ界面(UITableView静态单元格)、仿QQ好友列表
-
IOS开发教程第一季之UI进阶day2合并IOS学习013--App启动过程、多控制器管理
-
IOS开发教程第一季之UI进阶day8合并IOS学习019--敲击、长按、轻扫、旋转,CALayer、锚点,CADisolayLink刷新,核心动画,关键帧动画,组动画,转场动画,画板案例
-
IOS开发教程第一季之UI进阶day6合并IOS学习017--绘图2