iOS 画板、涂鸦
来源:互联网 发布:知乎一句话个人介绍 编辑:程序博客网 时间:2024/05/17 17:14
Demo下载地址:http://download.csdn.net/download/u010981736/9950247
功能:iOS画板涂鸦,支持横竖屏适配,涂鸦的内容可以保存为图片,也可以把已有的图片添加到画板去修改,然后再保存为新的图片到相册。
效果图:
竖屏:
横屏:
核心代码:
界面使用XIB脱线完成的,做了横竖屏的适配;
ViewController文件
//// HandleImageView.h// 画板涂鸦//// Created by llkj on 2017/8/25.// Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@class HandleImageView;@protocol HandleImageViewDelegate <NSObject>- (void)handleImageView:(HandleImageView *)handleImageView newImage:(UIImage *)newImage;@end@interface HandleImageView : UIView@property (nonatomic, weak) UIImage *image;@property (nonatomic, weak) id<HandleImageViewDelegate> delegate;@end
//// ViewController.m// 画板涂鸦//// Created by llkj on 2017/8/24.// Copyright © 2017年 LayneCheung. All rights reserved.//#import "ViewController.h"#import "DrawView.h"#import "HandleImageView.h"@interface ViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate, HandleImageViewDelegate>@property (weak, nonatomic) IBOutlet DrawView *drawView;@end@implementation ViewController//清屏- (IBAction)clear:(id)sender { [self.drawView clear];}// 撤销- (IBAction)undo:(id)sender { [self.drawView undo];}//橡皮擦- (IBAction)eraser:(id)sender { [self.drawView erase];}//设置线的宽度- (IBAction)setLineWidth:(UISlider *)sender { [self.drawView setLineWith:sender.value];}//设置线的颜色- (IBAction)setLineColor:(UIButton *)sender { [self.drawView setLineColor:sender.backgroundColor];}//照片- (IBAction)photo:(id)sender {// 从系统相册中选择图片// 1.弹出相册 UIImagePickerController *vc = [[UIImagePickerController alloc] init];// 设置照片来源 vc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; vc.delegate = self;// modal出来相册 [self presentViewController:vc animated:YES completion:nil];}//保存- (IBAction)save:(id)sender { //生成图片保存到系统相册 //1.绘制上下文 UIGraphicsBeginImageContextWithOptions(self.drawView.bounds.size, NO, 1); //2.把画板上的内容渲染到上下文中 CGContextRef ref = UIGraphicsGetCurrentContext(); [self.drawView.layer renderInContext:ref]; //3.从上下文中取出一张图片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //4.关闭上下文 UIGraphicsEndImageContext(); //图片写入到系统相册 UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);}//当选择某一个照片会调用-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ UIImage *image = info[UIImagePickerControllerOriginalImage]; HandleImageView *handleImgV = [[HandleImageView alloc] initWithFrame:self.drawView.frame]; handleImgV.backgroundColor = [UIColor clearColor]; handleImgV.delegate = self; dispatch_async(dispatch_get_main_queue(), ^{ handleImgV.image = image; });// handleImgV.image = image; [self.view addSubview:handleImgV]; [self dismissViewControllerAnimated:YES completion:nil];}- (void)handleImageView:(HandleImageView *)handleImageView newImage:(UIImage *)newImage{ self.drawView.image = newImage;}- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ NSLog(@"保存成功");}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.}- (BOOL)prefersStatusBarHidden{ return YES;}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end
HandleImageView文件
//// HandleImageView.h// 画板涂鸦//// Created by llkj on 2017/8/25.// Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@class HandleImageView;@protocol HandleImageViewDelegate <NSObject>- (void)handleImageView:(HandleImageView *)handleImageView newImage:(UIImage *)newImage;@end@interface HandleImageView : UIView@property (nonatomic, weak) UIImage *image;@property (nonatomic, weak) id<HandleImageViewDelegate> delegate;@end
//// HandleImageView.m// 画板涂鸦//// Created by llkj on 2017/8/25.// Copyright © 2017年 LayneCheung. All rights reserved.//#import "HandleImageView.h"@interface HandleImageView ()<UIGestureRecognizerDelegate>@property (nonatomic, strong) UIImageView *imageV;@end@implementation HandleImageView-(UIImageView *)imageV { if (_imageV == nil) { UIImageView *imageV = [[UIImageView alloc] init]; imageV.frame = self.bounds; imageV.userInteractionEnabled = YES; [self addSubview:imageV]; _imageV = imageV; //添加手势 [self addGes]; } return _imageV;}-(void)setImage:(UIImage *)image { _image = image; NSLog(@"%@",self.imageV); self.imageV.image = image;}//添加手势-(void)addGes{ // pan // 拖拽手势 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [self.imageV addGestureRecognizer:pan]; // pinch // 捏合 UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)]; pinch.delegate = self; [self.imageV addGestureRecognizer:pinch]; //添加旋转 UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)]; rotation.delegate = self; [self.imageV addGestureRecognizer:rotation]; // 长按手势 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; [self.imageV addGestureRecognizer:longPress];}//捏合的时候调用.- (void)pinch:(UIPinchGestureRecognizer *)pinch{ pinch.view.transform = CGAffineTransformScale( pinch.view.transform, pinch.scale, pinch.scale); // 复位 pinch.scale = 1;}//旋转的时候调用- (void)rotation:(UIRotationGestureRecognizer *)rotation{ // 旋转图片 rotation.view.transform = CGAffineTransformRotate(rotation.view.transform, rotation.rotation); // 复位,只要想相对于上一次旋转就复位 rotation.rotation = 0;}//长按的时候调用// 什么时候调用:长按的时候调用,而且只要手指不离开,拖动的时候会一直调用,手指抬起的时候也会调用- (void)longPress:(UILongPressGestureRecognizer *)longPress{ if (longPress.state == UIGestureRecognizerStateBegan) { [UIView animateWithDuration:0.25 animations:^{ //设置为透明 self.imageV.alpha = 0; }completion:^(BOOL finished) { [UIView animateWithDuration:0.25 animations:^{ self.imageV.alpha = 1; //把当前的View做一个截屏 UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0); //获取上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); [self.layer renderInContext:ctx]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); //关闭上下文. UIGraphicsEndImageContext(); //调用代理方法 if([self.delegate respondsToSelector:@selector(handleImageView:newImage:)]) { [self.delegate handleImageView:self newImage:newImage]; } //从父控件当中移除 [self removeFromSuperview]; }]; }]; }}//拖动的时候调用- (void)pan:(UIPanGestureRecognizer *)pan{ CGPoint transP = [pan translationInView:pan.view]; pan.view.transform = CGAffineTransformTranslate(pan.view.transform, transP.x, transP.y); //复位 [pan setTranslation:CGPointZero inView:pan.view];}//能够同时支持多个手势-(BOOL)gestureRecognizer:(nonnull UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(nonnull UIGestureRecognizer *)otherGestureRecognizer{ return YES;}@end
DrawView文件
//// DrawView.h// 画板涂鸦//// Created by llkj on 2017/8/24.// Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@interface DrawView : UIView//清屏- (void)clear;//撤销- (void)undo;//橡皮擦- (void)erase;//设置线的宽度- (void)setLineWith:(CGFloat)lineWidth;//设置线的颜色- (void)setLineColor:(UIColor *)color;/** 要绘制的图片 */@property (nonatomic, strong) UIImage * image;@end
//// DrawView.m// 画板涂鸦//// Created by llkj on 2017/8/24.// Copyright © 2017年 LayneCheung. All rights reserved.//#import "DrawView.h"#import "MyBezierPath.h"@interface DrawView()/** 当前绘制的路径 */@property (nonatomic, strong) UIBezierPath *path;//保存当前绘制的所有路径@property (nonatomic, strong) NSMutableArray *allPathArray;//当前路径的线宽@property (nonatomic, assign) CGFloat width;//当前路径的颜色@property (nonatomic, strong) UIColor *color;@end@implementation DrawView- (NSMutableArray *)allPathArray { if (_allPathArray == nil) { _allPathArray = [NSMutableArray array]; } return _allPathArray;}- (void)awakeFromNib { [super awakeFromNib]; //添加手势 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [self addGestureRecognizer:pan]; self.width = 1; self.color = [UIColor blackColor];}-(void)setImage:(UIImage *)image { _image = image; //添加图片添加到数组当中 [self.allPathArray addObject:image]; //重绘 [self setNeedsDisplay];}//清屏- (void)clear { //清空所有的路径 [self.allPathArray removeAllObjects]; //重绘 [self setNeedsDisplay];}//撤销- (void)undo { //删除最后一个路径 [self.allPathArray removeLastObject]; //重绘 [self setNeedsDisplay];}//橡皮擦- (void)erase { [self setLineColor:[UIColor whiteColor]];}//设置线的宽度- (void)setLineWith:(CGFloat)lineWidth { self.width = lineWidth;}//设置线的颜色- (void)setLineColor:(UIColor *)color { self.color = color;}- (void)pan:(UIPanGestureRecognizer *)pan { //获取的当前手指的点 CGPoint curP = [pan locationInView:self]; //判断手势的状态 if(pan.state == UIGestureRecognizerStateBegan) { //创建路径 //UIBezierPath *path = [UIBezierPath bezierPath]; MyBezierPath *path = [[MyBezierPath alloc] init]; self.path = path; //设置起点 [path moveToPoint:curP]; //设置线的宽度 [path setLineWidth:self.width]; //设置线的颜色 //什么情况下自定义类:当发现系统原始的功能,没有办法瞒足自己需求时,这个时候,要自定义类.继承系统原来的东西.再去添加属性自己的东西. path.color = self.color; [self.allPathArray addObject:path]; } else if(pan.state == UIGestureRecognizerStateChanged) { //绘制一根线到当前手指所在的点 [self.path addLineToPoint:curP]; //重绘 [self setNeedsDisplay]; }}-(void)drawRect:(CGRect)rect { //绘制保存的所有路径 for (MyBezierPath *path in self.allPathArray) { //判断取出的路径真实类型 if([path isKindOfClass:[UIImage class]]) { UIImage *image = (UIImage *)path; [image drawInRect:rect]; }else { [path.color set]; [path stroke]; } }}@end
MyBezierPath文件
//// MyBezierPath.h// 画板涂鸦//// Created by llkj on 2017/8/24.// Copyright © 2017年 LayneCheung. All rights reserved.//#import <UIKit/UIKit.h>@interface MyBezierPath : UIBezierPath//当前路径的颜色@property (nonatomic, strong) UIColor *color;@end
#import "MyBezierPath.h"@implementation MyBezierPath@end
阅读全文
0 0
- iOS OC 涂鸦、画板
- iOS 画板、涂鸦
- IOS开发:手势画板涂鸦
- iOS涂鸦画板 主要自定义UIView
- IOS学习之——画板 涂鸦
- 涂鸦画板
- 自定义画板涂鸦
- swift4.0 涂鸦画板
- Android涂鸦画板源码
- 利用CGMutablePathRef制作画板涂鸦
- ios 涂鸦
- ios 画板
- 画板 ios
- 贴吧涂鸦–毕加索的画板
- Html5 canvas 简单画布画板涂鸦例子
- 画板涂鸦和时钟(Quartz2D,核心动画)
- Android趣味小实例—涂鸦画板
- 自定义view实现涂鸦(画板)功能
- 线段树知识点理解及其模板代码
- 正则表达式详解
- centos7查看操作系统信息
- CSS3的calc()
- Python学习
- iOS 画板、涂鸦
- D08 MapReduce编程思想
- 多进程写入文件
- javaee学习日记之java基础之初识java
- 【C#】C# 扩展方法
- C语言函数的简单说明
- eclipse或者myelipse没有代码提示,即使已经设置二十个字母
- IntentFilter过滤小数点两位
- 计算机网络1-Socket编程