小画板demo
2016-03-22 21:54
316 查看
用storyBoard搭界面,最上面用到了一个toolBar ,中间用到了一个View,用来画东西,最下面在放一个View,用来存放三个按钮和一个UISlider
![](https://img-blog.csdn.net/20160322215805302?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
接下来就可以开始你的大作了,首先因为要在第二个拖的控件蓝色的View里画东西,所以要自定义一个类,
@property(nonatomic,strong)UIBezierPath *connectPath;
@end
@implementation LSdrawView
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
UIBezierPath *path = [UIBezierPath
bezierPath];
self.connectPath = path;
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[self.connectPath
addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
[self.connectPath
stroke];
}
这段代码是第一步的到触摸的点然后,接线,在这里两个注意点,首先我们要接线创建一个UIBezierpath的路径去接收接线,第二我们要在DrawRect方法里进行渲染,第三个,你在View里想要显示线条就必须进行重绘,这是单线的做法
@interface LSdrawView()
@property(nonatomic,strong)UIBezierPath *connectPath;
@property(nonatomic,strong)NSMutableArray *connectArray;
@end
@implementation LSdrawView
-(NSMutableArray *)connectArray{
if (!_connectArray) {
_connectArray = [NSMutableArray
array];
}
return
_connectArray;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
UIBezierPath *path = [UIBezierPath
bezierPath];
[self.connectArray
addObject:path];
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[[self.connectArray
lastObject] addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
for (UIBezierPath *path
in self.connectArray) {
[path stroke];
}
}
这是多线处理,与多线的区别舍弃使用connectPath,新创建一个可变数组去存放画好的线,有几个注意点 首先数组里得先存放刚接触屏幕的首路径,然后在移动屏幕的时候使用可变数组中最后一个元素去添加添加新的线条,最后在渲染中使用for循环可变数组中的路径进行渲染
接下来设置线宽。。。
@interface
ViewController ()
@property (weak,
nonatomic) IBOutlet
LSdrawView *myDrawView;
@property (weak,
nonatomic) IBOutlet
UISlider *mySlider;
@end
@implementation ViewController
- (IBAction)mySlider:(UISlider *)sender {
self.myDrawView.lineWidth = sender.value;
}
- (void)viewDidLoad {
[super
viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.myDrawView.lineWidth =
self.mySlider.value;
}
- (void)didReceiveMemoryWarning {
[super
didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
首先在控制器的.m文件中给Slider拖一根Action,我们要设置画板中的线宽,所以需要将故事板中的第二个View控件拖一根OutLet线,然后获取里面的线宽,可是线宽在View里是私有的,所以。。。下一步
#import
<UIKit/UIKit.h>
@interface LSdrawView :
UIView
@property(nonatomic,assign)CGFloat lineWidth;
@end
在自定义的类中设置一个线宽,因为.m中的属性是私有的
获取到线宽之后,然后进行设置,注意要改slider的类型,按钮不能传id不然没有value转换的,接下来在View中改变线宽
@interface LSdrawView()
@property(nonatomic,strong)UIBezierPath *connectPath;
@property(nonatomic,strong)NSMutableArray *connectArray;
@end
@implementation LSdrawView
-(NSMutableArray *)connectArray{
if (!_connectArray) {
_connectArray = [NSMutableArray
array];
}
return
_connectArray;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
UIBezierPath *path = [UIBezierPath
bezierPath];
path.lineWidth =self.lineWidth;//单独设置线宽
[self.connectArray
addObject:path];
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[[self.connectArray
lastObject] addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
for (UIBezierPath *path
in self.connectArray) {
// path.lineWidth = self.lineWidth;//不能统一设置线宽,会出现一条线改变多条线改变
[path stroke];
}
}
在这里设置线宽,首先不能直接在drawRect方法里直接在for循环中设置线宽,会导致一变都变的情况,我们要在toughBegan方法中,单独设置线宽,接下来虽然实现了功能可使没有设置默认线宽,所以我们拖一根Slider属性线,然后在ViewDidLoad里设置默认线宽
设置颜色和线宽一个道理,给三个颜色的Button都拖到同一个点击事件,拿不到View中的颜色,所以在View的.h中声明颜色的成员属性,注意在View中设置颜色的时候,path没有自身的颜色属性,我们需要创建一个继承自UIBezierPath的类,然后设置里面的成员属性线的颜色,然后在path中重新设置线的颜色
@implementation LSdrawView
-(NSMutableArray *)connectArray{
if (!_connectArray) {
_connectArray = [NSMutableArray
array];
}
return
_connectArray;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
LSlineColor *path = [LSlineColor
bezierPath];
path.lineColor =
self.lineColor;
path.lineWidth =self.lineWidth;//单独设置线宽
[self.connectArray
addObject:path];
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[[self.connectArray
lastObject] addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
for (LSlineColor *path
in self.connectArray) {
// path.lineWidth = self.lineWidth;//不能统一设置线宽,会出现一条线改变多条线改变
// [self.lineColor set];//不能统一设置颜色,会导致一变多变
[path.lineColor set];//设置线的颜色
[path stroke];
}
}
最后设置工具栏上的四个方法
- (IBAction)mySlider:(UISlider *)sender {
self.myDrawView.lineWidth = sender.value;
}
- (IBAction)colorButton:(UIButton *)sender {
self.myDrawView.lineColor = sender.backgroundColor;
}
- (IBAction)clearButton:(UIBarButtonItem *)sender {
[self.myDrawView.connectArray
removeAllObjects];
[self.myDrawView
setNeedsDisplay];
}
- (IBAction)backButton:(UIBarButtonItem *)sender {
[self.myDrawView.connectArray
removeLastObject];
[self.myDrawView
setNeedsDisplay];
}
- (IBAction)eraserButton:(UIBarButtonItem *)sender {
// LSlineColor *path = [LSlineColor bezierPath];
//// path.lineColor = self.myDrawView.backgroundColor;//这个方法不可以
// self.myDrawView.lineColor = self.myDrawView.backgroundColor;
// [self.myDrawView.connectArray addObject:path];
//还可以用下面的方法
self.myDrawView.lineColor =
self.myDrawView.backgroundColor;
[self.myDrawView
setNeedsDisplay];
}
- (IBAction)saveButton:(UIBarButtonItem *)sender {
UIGraphicsBeginImageContextWithOptions(self.myDrawView.frame.size,
YES,
0.0);
CGContextRef ctx =
UIGraphicsGetCurrentContext();
[self.myDrawView.layer
renderInContext:ctx];
UIImage *image =
UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(image,
nil,
nil, nil);
}
使用橡皮擦功能的时候,注意如果你用path绘制路径,设置背景色,在View的可变数组里添加这个绘制的路径会发生没有变化,是因为你要改的是self.lineColor的颜色,而不是path路径的颜色,之后还会有个小BUG,点击回退的时候有一条路径是,你之前添加的一条和背景色一样的路径,先回退的这个路径始终在我的集合里面,回退的时候这个集合也要回退一次,这个路径适合背景一模一样的颜色,是存在的,所以提供一个更加好的方式,如上面代码。
接下来就可以开始你的大作了,首先因为要在第二个拖的控件蓝色的View里画东西,所以要自定义一个类,
@property(nonatomic,strong)UIBezierPath *connectPath;
@end
@implementation LSdrawView
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
UIBezierPath *path = [UIBezierPath
bezierPath];
self.connectPath = path;
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[self.connectPath
addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
[self.connectPath
stroke];
}
这段代码是第一步的到触摸的点然后,接线,在这里两个注意点,首先我们要接线创建一个UIBezierpath的路径去接收接线,第二我们要在DrawRect方法里进行渲染,第三个,你在View里想要显示线条就必须进行重绘,这是单线的做法
@interface LSdrawView()
@property(nonatomic,strong)UIBezierPath *connectPath;
@property(nonatomic,strong)NSMutableArray *connectArray;
@end
@implementation LSdrawView
-(NSMutableArray *)connectArray{
if (!_connectArray) {
_connectArray = [NSMutableArray
array];
}
return
_connectArray;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
UIBezierPath *path = [UIBezierPath
bezierPath];
[self.connectArray
addObject:path];
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[[self.connectArray
lastObject] addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
for (UIBezierPath *path
in self.connectArray) {
[path stroke];
}
}
这是多线处理,与多线的区别舍弃使用connectPath,新创建一个可变数组去存放画好的线,有几个注意点 首先数组里得先存放刚接触屏幕的首路径,然后在移动屏幕的时候使用可变数组中最后一个元素去添加添加新的线条,最后在渲染中使用for循环可变数组中的路径进行渲染
接下来设置线宽。。。
@interface
ViewController ()
@property (weak,
nonatomic) IBOutlet
LSdrawView *myDrawView;
@property (weak,
nonatomic) IBOutlet
UISlider *mySlider;
@end
@implementation ViewController
- (IBAction)mySlider:(UISlider *)sender {
self.myDrawView.lineWidth = sender.value;
}
- (void)viewDidLoad {
[super
viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.myDrawView.lineWidth =
self.mySlider.value;
}
- (void)didReceiveMemoryWarning {
[super
didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
首先在控制器的.m文件中给Slider拖一根Action,我们要设置画板中的线宽,所以需要将故事板中的第二个View控件拖一根OutLet线,然后获取里面的线宽,可是线宽在View里是私有的,所以。。。下一步
#import
<UIKit/UIKit.h>
@interface LSdrawView :
UIView
@property(nonatomic,assign)CGFloat lineWidth;
@end
在自定义的类中设置一个线宽,因为.m中的属性是私有的
获取到线宽之后,然后进行设置,注意要改slider的类型,按钮不能传id不然没有value转换的,接下来在View中改变线宽
@interface LSdrawView()
@property(nonatomic,strong)UIBezierPath *connectPath;
@property(nonatomic,strong)NSMutableArray *connectArray;
@end
@implementation LSdrawView
-(NSMutableArray *)connectArray{
if (!_connectArray) {
_connectArray = [NSMutableArray
array];
}
return
_connectArray;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
UIBezierPath *path = [UIBezierPath
bezierPath];
path.lineWidth =self.lineWidth;//单独设置线宽
[self.connectArray
addObject:path];
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[[self.connectArray
lastObject] addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
for (UIBezierPath *path
in self.connectArray) {
// path.lineWidth = self.lineWidth;//不能统一设置线宽,会出现一条线改变多条线改变
[path stroke];
}
}
在这里设置线宽,首先不能直接在drawRect方法里直接在for循环中设置线宽,会导致一变都变的情况,我们要在toughBegan方法中,单独设置线宽,接下来虽然实现了功能可使没有设置默认线宽,所以我们拖一根Slider属性线,然后在ViewDidLoad里设置默认线宽
设置颜色和线宽一个道理,给三个颜色的Button都拖到同一个点击事件,拿不到View中的颜色,所以在View的.h中声明颜色的成员属性,注意在View中设置颜色的时候,path没有自身的颜色属性,我们需要创建一个继承自UIBezierPath的类,然后设置里面的成员属性线的颜色,然后在path中重新设置线的颜色
@implementation LSdrawView
-(NSMutableArray *)connectArray{
if (!_connectArray) {
_connectArray = [NSMutableArray
array];
}
return
_connectArray;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
LSlineColor *path = [LSlineColor
bezierPath];
path.lineColor =
self.lineColor;
path.lineWidth =self.lineWidth;//单独设置线宽
[self.connectArray
addObject:path];
[path moveToPoint:loc];
[self
setNeedsDisplay];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
CGPoint loc = [touch
locationInView:touch.view];
[[self.connectArray
lastObject] addLineToPoint:loc];
[self
setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect{
for (LSlineColor *path
in self.connectArray) {
// path.lineWidth = self.lineWidth;//不能统一设置线宽,会出现一条线改变多条线改变
// [self.lineColor set];//不能统一设置颜色,会导致一变多变
[path.lineColor set];//设置线的颜色
[path stroke];
}
}
最后设置工具栏上的四个方法
- (IBAction)mySlider:(UISlider *)sender {
self.myDrawView.lineWidth = sender.value;
}
- (IBAction)colorButton:(UIButton *)sender {
self.myDrawView.lineColor = sender.backgroundColor;
}
- (IBAction)clearButton:(UIBarButtonItem *)sender {
[self.myDrawView.connectArray
removeAllObjects];
[self.myDrawView
setNeedsDisplay];
}
- (IBAction)backButton:(UIBarButtonItem *)sender {
[self.myDrawView.connectArray
removeLastObject];
[self.myDrawView
setNeedsDisplay];
}
- (IBAction)eraserButton:(UIBarButtonItem *)sender {
// LSlineColor *path = [LSlineColor bezierPath];
//// path.lineColor = self.myDrawView.backgroundColor;//这个方法不可以
// self.myDrawView.lineColor = self.myDrawView.backgroundColor;
// [self.myDrawView.connectArray addObject:path];
//还可以用下面的方法
self.myDrawView.lineColor =
self.myDrawView.backgroundColor;
[self.myDrawView
setNeedsDisplay];
}
- (IBAction)saveButton:(UIBarButtonItem *)sender {
UIGraphicsBeginImageContextWithOptions(self.myDrawView.frame.size,
YES,
0.0);
CGContextRef ctx =
UIGraphicsGetCurrentContext();
[self.myDrawView.layer
renderInContext:ctx];
UIImage *image =
UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(image,
nil,
nil, nil);
}
使用橡皮擦功能的时候,注意如果你用path绘制路径,设置背景色,在View的可变数组里添加这个绘制的路径会发生没有变化,是因为你要改的是self.lineColor的颜色,而不是path路径的颜色,之后还会有个小BUG,点击回退的时候有一条路径是,你之前添加的一条和背景色一样的路径,先回退的这个路径始终在我的集合里面,回退的时候这个集合也要回退一次,这个路径适合背景一模一样的颜色,是存在的,所以提供一个更加好的方式,如上面代码。
相关文章推荐
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 不可修补的 iOS 漏洞可能导致 iPhone 4s 到 iPhone X 永久越狱
- iOS 12.4 系统遭黑客破解,漏洞危及数百万用户
- 每日安全资讯:NSO,一家专业入侵 iPhone 的神秘公司
- [转][源代码]Comex公布JailbreakMe 3.0源代码
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- js判断客户端是iOS还是Android等移动终端的方法
- iOS应用中UISearchDisplayController搜索效果的用法
- IOS开发环境windows化攻略
- iOS应用中UITableView左滑自定义选项及批量删除的实现
- 浅析iOS应用开发中线程间的通信与线程安全问题
- 检测iOS设备是否越狱的方法
- .net平台推送ios消息的实现方法
- 探讨Android与iOS,我们将何去何从?
- Android、iOS和Windows Phone中的推送技术详解
- iOS推送的那些事
- IOS 改变键盘颜色代码