IOS开发教程第一季之UI进阶day8合并IOS学习019--敲击、长按、轻扫、旋转,CALayer、锚点,CADisolayLink刷新,核心动画,关键帧动画,组动画,转场动画,画板案例
程序员文章站
2022-07-05 21:12:39
1.创建并实现手势的基本步骤点击手势#import "ViewController.h"@interface ViewController ()@property (weak, nonatomic) IBOutlet UIImageView *imageview;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; //1.创建点击手势 UITapGestureRecogni...
1.创建并实现手势的基本步骤
点击手势
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建点击手势
UITapGestureRecognizer* tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
//更改点击的次数
tap.numberOfTapsRequired=2;//点击两次才会触发方法
tap.numberOfTouchesRequired=2;//几根手指点几次
//2、对某一个view添加收拾
[self.imageview addGestureRecognizer:tap];
}
//3、实现手势放方法
-(void)tap:(UITapGestureRecognizer*) sender{
NSLog(@"你点击手势了");
}
@end
长按手势
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建点击手势
UILongPressGestureRecognizer* longpress=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longpress:)];
//更改长按的时间
longpress.minimumPressDuration=3;//长按多少时间
longpress.allowableMovement=10;//手指误差范围10个点
//2、对某一个view添加收拾
[self.imageview addGestureRecognizer:longpress];
}
//3、实现手势放方法
-(void)longpress:(UILongPressGestureRecognizer*) sender{
//如果是第一次长按
if (sender.state==UIGestureRecognizerStateBegan) {
NSLog(@"你长按了");
}
}
@end
轻扫手势(默认从左往右扫)
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建点击手势
UISwipeGestureRecognizer* swipe1=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
UISwipeGestureRecognizer* swipe2=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
//更改轻扫方向
swipe1.direction=UISwipeGestureRecognizerDirectionLeft;//从右往左
swipe2.direction=UISwipeGestureRecognizerDirectionRight;//从左往右
//2、对某一个view添加收拾
[self.imageview addGestureRecognizer:swipe1];
[self.imageview addGestureRecognizer:swipe2];
}
//3、实现手势放方法
-(void)swipe:(UISwipeGestureRecognizer*) sender{
//判断轻扫方向
if (sender.direction==UISwipeGestureRecognizerDirectionLeft) {
NSLog(@"你从右往左轻扫了");
}else{
NSLog(@"你从左往右轻扫了");
}
}
@end
旋转手势
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建旋转手势
UIRotationGestureRecognizer* rotation=[[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
//更改轻扫方向
//swipe1.direction=UISwipeGestureRecognizerDirectionLeft;//从右往左
//2、对某一个view添加收拾
[self.imageview addGestureRecognizer:rotation];
}
//3、实现手势放方法
-(void)rotation:(UIRotationGestureRecognizer*) sender{
//判断轻扫方向
self.imageview.transform=CGAffineTransformRotate(self.imageview.transform, sender.rotation);
NSLog(@"%f",sender.rotation);
//使得sender每次穿过来的rotation是一个夹角
sender.rotation=0;
}
@end
捏合手势
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建捏合手势(缩放)
UIPinchGestureRecognizer* pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
//2、对某一个view添加手势
[self.imageview addGestureRecognizer:pinch];
}
//3、实现手势放方法
-(void)pinch:(UIPinchGestureRecognizer*) sender{
self.imageview.transform=CGAffineTransformScale(self.imageview.transform, sender.scale, sender.scale);
NSLog(@"%f",sender.scale);
sender.scale=1;
}
@end
拖拽手势
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建拓转手势(平移)
UIPanGestureRecognizer* pan=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
//2、对某一个view添加手势
[self.imageview addGestureRecognizer:pan];
}
//3、实现手势放方法
-(void)pan:(UIPanGestureRecognizer*) sender{
CGPoint point=[sender translationInView:sender.view];//sender.view是做手势的那个view
self.imageview.transform=CGAffineTransformTranslate(self.imageview.transform, point.x, point.y);
[sender setTranslation:CGPointZero inView:sender.view];
}
@end
多手势共用,使用代理
#import "ViewController.h"
@interface ViewController ()<UIGestureRecognizerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建旋转手势
UIRotationGestureRecognizer* rotation=[[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
//2、对某一个view添加收拾
[self.imageview addGestureRecognizer:rotation];
//创建旋转的代理方法解决手势冲突的问题
rotation.delegate=self;
//1.创建捏合手势(缩放)
UIPinchGestureRecognizer* pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
pinch.delegate=self;
//2、对某一个view添加手势
[self.imageview addGestureRecognizer:pinch];
}
//实现代理方法,解决手势冲突
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
//3、实现手势放方法
//旋转方法
-(void)rotation:(UIRotationGestureRecognizer*) sender{
//判断轻扫方向
self.imageview.transform=CGAffineTransformRotate(self.imageview.transform, sender.rotation);
NSLog(@"%f",sender.rotation);
//使得sender每次穿过来的rotation是一个夹角
sender.rotation=0;
}
//捏合方法
-(void)pinch:(UIPinchGestureRecognizer*) sender{
self.imageview.transform=CGAffineTransformScale(self.imageview.transform, sender.scale, sender.scale);
NSLog(@"%f",sender.scale);
sender.scale=1;
}
@end
2.CALayer的基本属性
view内部以图层形式(CAlayer)显示内容,实际上view负责监听,calayer负责显示
通过calayer可以调整许多view的效果,比如,边框、阴影、大小
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个view
UIView* redview=[[UIView alloc]init];
redview.frame=CGRectMake(150, 150, 100, 100);
redview.backgroundColor=[UIColor greenColor];
//设置边框
redview.layer.borderWidth=5;//边框宽度,同时内容部分要减去10个点
redview.layer.borderColor=[UIColor blueColor].CGColor;//边框阴影,颜色要转化为cg颜色
//设置阴影
redview.layer.shadowOffset=CGSizeMake(5, 5);//阴影偏移量
redview.layer.shadowColor=[UIColor grayColor].CGColor;//阴影颜色
redview.layer.shadowOpacity=1;//阴影透明度,1为不透明
redview.layer.shadowRadius=5;//阴影的半径
//设置圆角
redview.layer.cornerRadius=15;//圆角半径
//redview.layer.masksToBounds=YES;//超出layer的范围就不显示,实际上消除阴影
//redview.layer.frame=CGRectMake(0, 0, 300, 300);//慎用,易出问题
//bounds大小
redview.layer.bounds=CGRectMake(50, 60, 200, 200);
//position位置属性和view.center的关系
//redview.layer.position=CGPointMake(0, 0);//实际是view.center中心点跑到point的位置上
//设置内容图片
redview.layer.contents=(__bridge id)([UIImage imageNamed:@"33"].CGImage);//将c的对象转换成oc对象
[self.view addSubview:redview];
}
@end
效果
3.手动创建Layer
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个layer对象
CALayer* mylayer=[[CALayer alloc]init];
mylayer.backgroundColor=[UIColor greenColor].CGColor;
mylayer.position=CGPointMake(200, 200);
mylayer.bounds=CGRectMake(0, 0, 100,100);
//将layer添加到控制器的layer上
[self.view.layer addSublayer:mylayer];
//给全局说行赋值
self.layer=mylayer;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸对象
UITouch* touch=touches.anyObject;
//获取手指当前的位置
CGPoint point=[touch locationInView:touch.view];
//禁用隐式动画(类似于数据库的事务,需要开启之后再提交)
[CATransaction begin];//开启事务
[CATransaction setDisableActions:YES];//禁用隐式动画
//让layer跑到手指的位置,这里会产生一个隐式动画,而根layer没有隐式动画
self.layer.position=point;//位置
self.layer.opacity*=0.9;//透明度
[CATransaction commit];//提交事务
}
@end
4.锚点(anchorPoint)示意图
anchor的取值范围在0-1。实质anchorPoint就是这个对象的定位点,用来取代原先中心点,实质就是将中心点替换为anchorPoint锚点。
5.时钟案例—添加一个表盘
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 用calayer创建一个表盘
CALayer* clock=[[CALayer alloc]init];
//设置layer尺寸
clock.bounds=CGRectMake(0, 0, 200, 200);
//设置layer大小
clock.position=CGPointMake(200, 200);
//设置图片
clock.contents=(__bridge id)([UIImage imageNamed:@"clock"].CGImage);
//设置圆角
clock.cornerRadius=100;
clock.masksToBounds=YES;//切角
//添加创建秒钟
CALayer* second=[[CALayer alloc]init];
second.bounds=CGRectMake(0, 0, 2, 60);//大小
second.position=clock.position;//与时钟的位置相等
second.backgroundColor=[UIColor redColor].CGColor;
//设置指针的锚点(anchorPoint定位点)
second.anchorPoint=CGPointMake(0.5, 0.8);
//注意下添加的顺序,免得被遮挡
[self.view.layer addSublayer:clock];
[self.view.layer addSublayer:second];
}
@end
6.时钟案例—设置事件间隔
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* second;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 用calayer创建一个表盘
CALayer* clock=[[CALayer alloc]init];
//设置layer尺寸
clock.bounds=CGRectMake(0, 0, 200, 200);
//设置layer大小
clock.position=CGPointMake(200, 200);
//设置图片
clock.contents=(__bridge id)([UIImage imageNamed:@"clock"].CGImage);
//设置圆角
clock.cornerRadius=100;
clock.masksToBounds=YES;//切角
//添加创建秒钟
CALayer* second=[[CALayer alloc]init];
second.bounds=CGRectMake(0, 0, 2, 60);//大小
second.position=clock.position;//与时钟的位置相等
second.backgroundColor=[UIColor redColor].CGColor;
//设置指针的锚点(anchorPoint定位点)
second.anchorPoint=CGPointMake(0.5, 0.8);
//注意下添加的顺序,免得被遮挡
//添加表盘
[self.view.layer addSublayer:clock];
//添加秒针
[self.view.layer addSublayer:second];
self.second=second;
//创建一个定时器
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
[self timeChange];//让第一秒钟就跟随系统时间
}
//旋转方法
-(void)timeChange{
//一秒钟旋转的角度
CGFloat angle=2*M_PI/60;
//获取当前时间的秒数
NSDate* date=[NSDate date];
//创建一个时间格式化对象
/*第一种取时间的方法
NSDateFormatter* formatter=[[NSDateFormatter alloc]init];
formatter.dateFormat=@"ss";
CGFloat time=[[formatter stringFromDate:date]floatValue];
//秒针旋转到某个角度
self.second.affineTransform=CGAffineTransformMakeRotation(time*angle);
*/
//日历对象来获取时间
NSCalendar* cal=[NSCalendar currentCalendar];//获取当前日期
CGFloat time=[cal component:NSCalendarUnitSecond fromDate:date];//拿到日期的秒数
//秒针旋转到某个角度
self.second.affineTransform=CGAffineTransformMakeRotation(time*angle);
}
@end
7.时钟案例—设置屏幕刷新(CADisplayLink)
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* second;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 用calayer创建一个表盘
CALayer* clock=[[CALayer alloc]init];
//设置layer尺寸
clock.bounds=CGRectMake(0, 0, 200, 200);
//设置layer大小
clock.position=CGPointMake(200, 200);
//设置图片
clock.contents=(__bridge id)([UIImage imageNamed:@"clock"].CGImage);
//设置圆角
clock.cornerRadius=100;
clock.masksToBounds=YES;//切角
//添加创建秒钟
CALayer* second=[[CALayer alloc]init];
second.bounds=CGRectMake(0, 0, 2, 60);//大小
second.position=clock.position;//与时钟的位置相等
second.backgroundColor=[UIColor redColor].CGColor;
//设置指针的锚点(anchorPoint定位点)
second.anchorPoint=CGPointMake(0.5, 0.8);
//注意下添加的顺序,免得被遮挡
//添加表盘
[self.view.layer addSublayer:clock];
//添加秒针
[self.view.layer addSublayer:second];
self.second=second;
//显示连接(CADisplayLink)
CADisplayLink* link=[CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)];
//把连接添加到主运行循环
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[self timeChange];//让第一秒钟就跟随系统时间
}
//旋转方法
-(void)timeChange{
//一秒钟旋转的角度
CGFloat angle=2*M_PI/60;
//获取当前时间的秒数
NSDate* date=[NSDate date];
//日历对象来获取时间
NSCalendar* cal=[NSCalendar currentCalendar];//获取当前日期
CGFloat time=[cal component:NSCalendarUnitSecond fromDate:date];//拿到日期的秒数
//秒针旋转到某个角度
self.second.affineTransform=CGAffineTransformMakeRotation(time*angle);
}
@end
7.核心动画简介
CoreAnitmation的动画执行过程都在后台操作,不会阻塞主线程
core Antimation是直接作用在CALayer上的,并非UIView
CAAnimation继承结构
8.基本动画
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个视图
UIView* redview=[[UIView alloc]init];
redview.frame=CGRectMake(100, 100, 100, 100);
redview.backgroundColor=[UIColor greenColor];
self.layer=redview.layer;
[self.view addSubview:redview];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//基本动画
//创建动画
CABasicAnimation* animation=[[CABasicAnimation alloc]init];
//怎么做动画
//基本动画都是修改属性获得的动画
animation.keyPath=@"position.y";//动画更改的某个属性
//animation.fromValue=@(10);//动画的某个属性值变动范围终点
//animation.toValue=@(300);//动画的某个属性值变动范围终点
animation.byValue=@(10);//自身的基础上+一定地址
//不希望动画播放完后回到起始位置
animation.fillMode=kCAFillModeForwards;
animation.removedOnCompletion=NO;
//添加动画(对谁做动画)
[self.layer addAnimation:animation forKey:nil];
}
@end
9.关键帧动画
设置关键节点运动
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个视图
UIView* redview=[[UIView alloc]init];
redview.frame=CGRectMake(100, 100, 20, 20);
redview.backgroundColor=[UIColor greenColor];
self.layer=redview.layer;
[self.view addSubview:redview];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//关键帧动画
//创建动画
CAKeyframeAnimation* animation=[[CAKeyframeAnimation alloc]init];
//怎么做动画
//基本动画都是修改属性获得的动画
animation.keyPath=@"position";//动画更改的某个属性,这个keypath是一个cgPoint对象
NSValue* value1=[NSValue valueWithCGPoint:CGPointMake(100, 100)];//关键帧的位置
NSValue* value2=[NSValue valueWithCGPoint:CGPointMake(150, 100)];
NSValue* value3=[NSValue valueWithCGPoint:CGPointMake(100, 150)];
NSValue* value4=[NSValue valueWithCGPoint:CGPointMake(150, 150)];
//设置若干个关键点(帧)
animation.values=@[value1,value2,value3,value4];
//设置动画完成的时间
animation.duration=2;//4秒完成时间
//设置动画实现次数
animation.repeatCount=INT_MAX;
//添加动画(对谁做动画)
[self.layer addAnimation:animation forKey:nil];
}
@end
围绕圆圈运动
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个视图
UIView* redview=[[UIView alloc]init];
redview.frame=CGRectMake(100, 100, 20, 20);
redview.backgroundColor=[UIColor greenColor];
self.layer=redview.layer;
[self.view addSubview:redview];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//关键帧动画
//创建关键帧动画,绕着圆的路径走
CAKeyframeAnimation* animationRatation=[[CAKeyframeAnimation alloc]init];
//怎么做动画
//常见引导路径
animationRatation.keyPath=@"position";
UIBezierPath* path=[UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2*M_PI clockwise:YES];
//将自定义路径设置给动画的路径(关键点路径)
animationRatation.path=path.CGPath;
//设置动画完成的时间
animation.duration=2;//4秒完成时间
//设置动画实现次数
animation.repeatCount=INT_MAX;
//添加动画(对谁做动画)
[self.layer addAnimation:animation forKey:nil];
}
@end
10.组动画(多个动画共同执行)
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,weak)CALayer* layer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个视图
UIView* redview=[[UIView alloc]init];
redview.frame=CGRectMake(100, 100, 20, 20);
redview.backgroundColor=[UIColor greenColor];
self.layer=redview.layer;
[self.view addSubview:redview];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//组动画
//创建动画
CAAnimationGroup* group=[[CAAnimationGroup alloc]init];
//创建基本动画----------------------------
CABasicAnimation* animationTransform=[[CABasicAnimation alloc]init];
//基本动画都是修改属性获得的动画
animationTransform.keyPath=@"transform.rotation";//动画更改的旋转属性
animationTransform.byValue=@(2*M_PI);//自身的基础上旋转
//创建关键帧动画,绕着圆的路径走----------------------
CAKeyframeAnimation* animationRatation=[[CAKeyframeAnimation alloc]init];
//常见引导路径
animationRatation.keyPath=@"position";
UIBezierPath* path=[UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2*M_PI clockwise:YES];
//设置关键帧动画的关键路径
animationRatation.path=path.CGPath;
//-------------------------------
//组动画怎么做动画
group.animations=@[animationTransform,animationRatation];//放入一个关键帧动画和一个基本动画,其实就是符合动画,
//设置组动画完成的时间
group.duration=2;//4秒完成时间
//设置组动画实现次数
group.repeatCount=INT_MAX;
//添加动画(对谁做动画)
[self.layer addAnimation:group forKey:nil];
}
@end
11.转场动画(类似ppt幻灯片转场)
在故事板stroyboard上添加手势的步骤
1、storyboard中添加一个imageView
2、将手势拖拽到imageview上
3、将刚才添加的手势拖线到ViewController上
转场动画过渡效果
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property(nonatomic,assign)NSInteger imageName;
@end
@implementation ViewController
//轻扫手势执行的方法
- (IBAction)imageChage:(UISwipeGestureRecognizer*)sender {
self.imageName++;//图片名++,因为图片的名字为1,2,3,4,5
//让图片名循环起来
if (self.imageName==5) {
self.imageName=0;
}
self.imageView.image=[UIImage imageNamed:[NSString stringWithFormat:@"%ld",self.imageName+1] ];
//1创建一个动画
CATransition* animation=[[CATransition alloc]init];
//2、操作动画某个属性
animation.type=@"cube";//立方体变幻属性
if (sender.direction==UISwipeGestureRecognizerDirectionLeft) {
//如果方向往左
animation.subtype=kCATransitionFromRight;//设置变化属性的次样式,这里是立方变幻的想做变化
}else{
animation.subtype=kCATransitionFromLeft;//设置变化属性的次样式,这里是立方变幻的想做变化
}
//3添加动画
[self.imageView.layer addAnimation:animation forKey:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.imageName=0;
}
@end
12.画板案例–绘制界面及实现绘图,
绘图区域为一个view设置FRView类与之对应
#import "FRView.h"
@interface FRView()
@property(nonatomic,strong)UIBezierPath* path;
@end
@implementation FRView
#define mark ------懒加载数据--------
//重新path的get方法
-(UIBezierPath*)path{
if (!_path) {
_path=[[UIBezierPath alloc]init];
}
return _path;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸对象
UITouch* touch=touches.anyObject;
//创建起点
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//获取起点,手指移动到起点上
[self.path moveToPoint:point];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//添加到点
//获取触摸对象
UITouch* touch=touches.anyObject;
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//绘制的终点
[self.path addLineToPoint:point];
//重绘路径
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
[self.path stroke];
}
@end
13.画板案例–增加线宽
FRView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRView : UIView
@property(nonatomic,assign)CGFloat lineWidth;
@end
NS_ASSUME_NONNULL_END
FRView.m
#import "FRView.h"
@interface FRView()
//管理路径的数组
@property(nonatomic,strong)NSMutableArray* paths;
@end
@implementation FRView
#define mark -------懒加载----------
//重写paths的get方法
-(NSMutableArray*)paths{
if (!_paths) {
_paths=[NSMutableArray array];
}
return _paths;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸对象
UITouch* touch=touches.anyObject;
//创建起点
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//创建路径
UIBezierPath* path=[[UIBezierPath alloc]init];
//设置线宽
[path setLineWidth:self.lineWidth];
//获取起点,手指移动到起点上
[path moveToPoint:point];
//将每一次创建的路径加载到路径数组上
[self.paths addObject:path];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//添加到点
//获取触摸对象
UITouch* touch=touches.anyObject;
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//创建路径
UIBezierPath* path=[[UIBezierPath alloc]init];
//绘制的终点
[[self.paths lastObject] addLineToPoint:point];
//重绘路径
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
//渲染路径
for (UIBezierPath* path in self.paths) {
//设置头尾和连接处的样式
[path setLineJoinStyle:kCGLineJoinRound];
[path setLineCapStyle:kCGLineCapRound];
//渲染路径
[path stroke];
}
}
@end
ViewController.m
#import "ViewController.h"
#import "FRView.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UISlider *lineWidthProgress;
@property (weak, nonatomic) IBOutlet FRView *frview;
//监听线宽改变
- (IBAction)lineWithChange:(UISlider*)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置初始线宽
self.frview.lineWidth=self.lineWidthProgress.value;
}
//监听线宽改变
- (IBAction)lineWithChange:(UISlider*)sender {
//把最新的数值(线宽)给了frview
self.frview.lineWidth =sender.value;
}
@end
14.画板案例–设置画笔颜色
- 需要专门为路径颜色写一个类FRBezierPath,继承UIBezierPath,并新增一个lineColor1属性,以后创建路径时使用FRFRBezierPath进行创建,这样创建的路径就具备了setLinerColor的写方法。
- 实际使用时可以将按钮的背景色传递个这个自定义path的setLinerColor方法。
- 最后在drawrect方法中为路径设置颜色 [path.lineColor set]
FRBezierpath.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRBezierpath : UIBezierPath
@property(nonatomic,strong)UIColor* lineColor1;
@end
NS_ASSUME_NONNULL_END
FRBezierpath.m
#import "FRBezierpath.h"
@implementation FRBezierpath
@end
FRView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRView : UIView
@property(nonatomic,assign)CGFloat lineWidth;
@property(nonatomic,strong)UIColor* lineColor;
@end
NS_ASSUME_NONNULL_END
FRView.m
#import "FRView.h"
#import "FRBezierpath.h"
@interface FRView()
//管理路径的数组
@property(nonatomic,strong)NSMutableArray* paths;
@end
@implementation FRView
#define mark -------懒加载----------
//重写paths的get方法
-(NSMutableArray*)paths{
if (!_paths) {
_paths=[NSMutableArray array];
}
return _paths;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸对象
UITouch* touch=touches.anyObject;
//创建起点
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//创建路径
FRBezierpath* path=[[FRBezierpath alloc]init];
//设置线宽
[path setLineWidth:self.lineWidth];
[path setLineColor1:self.lineColor];//设置自定义的颜色
//获取起点,手指移动到起点上
[path moveToPoint:point];
//将每一次创建的路径加载到路径数组上
[self.paths addObject:path];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//添加到点
//获取触摸对象
UITouch* touch=touches.anyObject;
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//创建路径
FRBezierpath* path=[[FRBezierpath alloc]init];
//绘制的终点
[[self.paths lastObject] addLineToPoint:point];
//重绘路径
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
//渲染路径
for (FRBezierpath* path in self.paths) {
//设置头尾和连接处的样式
[path setLineJoinStyle:kCGLineJoinRound];
[path setLineCapStyle:kCGLineCapRound];
//在这里绘制颜色
[path.lineColor1 set];
//渲染路径
[path stroke];
}
}
@end
ViewController.m
#import "ViewController.h"
#import "FRView.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UISlider *lineWidthProgress;
@property (weak, nonatomic) IBOutlet FRView *frview;
- (IBAction)lineColorChange:(UIButton*)sender;
//监听线宽改变
- (IBAction)lineWithChange:(UISlider*)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置初始线宽
self.frview.lineWidth=self.lineWidthProgress.value;
}
//监听线宽改变
- (IBAction)lineWithChange:(UISlider*)sender {
//把最新的数值(线宽)给了frview
self.frview.lineWidth =sender.value;
}
//监听颜色的改变
- (IBAction)lineColorChange:(UIButton*)sender {
self.frview.lineColor=sender.backgroundColor;
}
@end
15.画板案例–画板工具条
FRBezierpath.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRBezierpath : UIBezierPath
@property(nonatomic,strong)UIColor* lineColor1;
@end
NS_ASSUME_NONNULL_END
FRBezierpath.m
#import "FRBezierpath.h"
@implementation FRBezierpath
@end
FRView.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FRView : UIView
@property(nonatomic,assign)CGFloat lineWidth;
@property(nonatomic,strong)UIColor* lineColor;
//橡皮擦除
- (void)erase;
//回退
- (void)back;
//清屏
- (void)clear;
@end
NS_ASSUME_NONNULL_END
FRView.m
#import "FRView.h"
#import "FRBezierpath.h"
@interface FRView()
//管理路径的数组
@property(nonatomic,strong)NSMutableArray* paths;
@end
@implementation FRView
#define mark -------懒加载----------
//重写paths的get方法
-(NSMutableArray*)paths{
if (!_paths) {
_paths=[NSMutableArray array];
}
return _paths;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//获取触摸对象
UITouch* touch=touches.anyObject;
//创建起点
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//创建路径
FRBezierpath* path=[[FRBezierpath alloc]init];
//设置线宽
[path setLineWidth:self.lineWidth];
[path setLineColor1:self.lineColor];//设置自定义的颜色
//获取起点,手指移动到起点上
[path moveToPoint:point];
//将每一次创建的路径加载到路径数组上
[self.paths addObject:path];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//添加到点
//获取触摸对象
UITouch* touch=touches.anyObject;
//获取手指的位置
CGPoint point=[touch locationInView:touch.view];
//创建路径
FRBezierpath* path=[[FRBezierpath alloc]init];
//绘制的终点
[[self.paths lastObject] addLineToPoint:point];
//重绘路径
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
//渲染路径
for (FRBezierpath* path in self.paths) {
//设置头尾和连接处的样式
[path setLineJoinStyle:kCGLineJoinRound];
[path setLineCapStyle:kCGLineCapRound];
//在这里绘制颜色
[path.lineColor1 set];
//渲染路径
[path stroke];
}
}
//橡皮擦除
- (void)erase{
self.lineColor=self.backgroundColor;
}
//回退
- (void)back{
//删除路径数组里面的最后一个路径
[self.paths removeLastObject];
[self setNeedsDisplay];
}
//清屏
- (void)clear{
//删除路径数组里面的所有路径
[self.paths removeAllObjects];
[self setNeedsDisplay];
}
@end
ViewController.m
#import "ViewController.h"
#import "FRView.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UISlider *lineWidthProgress;
@property (weak, nonatomic) IBOutlet FRView *frview;
- (IBAction)save:(id)sender;
- (IBAction)lineColorChange:(UIButton*)sender;
- (IBAction)clear:(id)sender;
- (IBAction)back:(id)sender;
- (IBAction)erase:(id)sender;
//监听线宽改变
- (IBAction)lineWithChange:(UISlider*)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//设置初始线宽
self.frview.lineWidth=self.lineWidthProgress.value;
}
//监听线宽改变
- (IBAction)lineWithChange:(UISlider*)sender {
//把最新的数值(线宽)给了frview
self.frview.lineWidth =sender.value;
}
//橡皮擦除
- (IBAction)erase:(id)sender {
[self.frview erase];
}
//回退
- (IBAction)back:(id)sender {
[self.frview back];
}
//清屏
- (IBAction)clear:(id)sender {
[self.frview clear];
}
//监听颜色的改变
- (IBAction)lineColorChange:(UIButton*)sender {
self.frview.lineColor=sender.backgroundColor;
}
//保存到相册
- (IBAction)save:(id)sender {
//开启图片类型的上下文
UIGraphicsBeginImageContextWithOptions(self.frview.bounds.size, NO,0);
//获取上下文
CGContextRef ctx=UIGraphicsGetCurrentContext();
//截图
[self.frview.layer renderInContext:ctx];
//取图片
UIImage * image=UIGraphicsGetImageFromCurrentImageContext();
//保存到相册
UIImageWriteToSavedPhotosAlbum(image, NULL, NULL, NULL);//IOS的高版本会要求隐私权限,所以这个步骤并不能真的保存
}
@end
本文地址:https://blog.csdn.net/weixin_43745804/article/details/107547736