iOS开发之画图板(贝塞尔曲线)
贝塞尔曲线,听着挺牛气一词,不过下面我们在做画图板的时候就用到贝塞尔绘直线,没用到绘制曲线的功能。如果会点PS的小伙伴会对贝塞尔曲线有更直观的理解。这篇博文的重点不在于如何用使用贝塞尔曲线,而是利用贝塞尔划线的功能来封装一个画图板。
画图板的截图如下,上面的白板就是我们的画图板,是自己封装好的一个UIView,下面会详细的介绍如何封装这个画图板,下面的控件用来控制我们画图板的属性以及Undo,Redo和保存功能。点击保存时会把绘制的图片保存到手机的相册中。下面是具体的实现方案。
一.封装画图板
其实上面的白板就是一继承于UiView的一个子类,我们可以在这个子类中添加我们画图板相应的属性和方法,然后实例化成对象添加到ViewController中,当然为了省事添加白板的时候是通过storyboard来完成的,读者也可以自己实例化然后手动的添加到相应的ViewController中。
1.封装白板的第一步是新建一个UIView的子类MyView,然后添加相应的属性和方法。MyView.h中的代码如下,代码具体意思请参照注释
#import <UIKit/UIKit.h> @interface MyView : UIView
//用来设置线条的颜色
@property (nonatomic, strong) UIColor *color;
//用来设置线条的宽度
@property (nonatomic, assign) CGFloat lineWidth;
//用来记录已有线条
@property (nonatomic, strong) NSMutableArray *allLine; //初始化相关参数
-(void)initMyView;
//unDo操作
-(void)backImage;
//reDo操作
-(void)forwardImage; @end
2、上面的代码是对外的接口,有些属性我们是写在MyView.m的延展中以实现私有的目的,MyView延展部分如下:
@interface MyView()
//声明贝塞尔曲线
@property(nonatomic, strong) UIBezierPath *bezier;
//存储Undo出来的线条
@property(nonatomic, strong) NSMutableArray *cancleArray;
@end
3.下面的代码就是实现部分的代码了,会根据不同功能给出相应的说明
(1).初始化我们的白板,给线条指定默认颜色和宽度并且给相应的变量分配内存空间,初始化代码如下:
//进行一些初始化工作
-(void)initMyView
{
self.color = [UIColor redColor];
self.lineWidth = ;
self.allLine = [NSMutableArray arrayWithCapacity:];
self.cancleArray = [NSMutableArray arrayWithCapacity:];
}
(2)Undo功能的封装,相当于两个栈,把显示的线条出栈,进入为不显示的线条栈中,每执行一次此操作显示线条栈中的元素会少一条而不显示线条栈中会多一条,大致就这个意思吧,代码如下:
//UnDo操作
-(void)backImage
{
if (self.allLine.count > )
{
int index = self.allLine.count - ; [self.cancleArray addObject:self.allLine[index]]; [self.allLine removeObjectAtIndex:index]; [self setNeedsDisplay
];
}
}
(3)Redo操作和Undo操作相反,从未显示栈中取出元素放入显示的栈中,代码中的栈我们是用数组来表示的,代码如下:
//ReDo操作
-(void)forwardImage
{
if (self.cancleArray.count > )
{
int index = self.cancleArray.count - ; [self.allLine addObject:self.cancleArray[index]]; [self.cancleArray removeObjectAtIndex:index]; [self setNeedsDisplay];
}
}
(4)、当开始触摸时我们新建一个BezierPath,把触摸起点设置成BezierPath的起点,并把将要画出的线条以及线条对应的属性封装成字典添加到显示栈中,代码如下
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//新建贝塞斯曲线
self.bezier = [UIBezierPath bezierPath]; //获取触摸的点
UITouch *myTouche = [touches anyObject];
CGPoint point = [myTouche locationInView:self]; //把刚触摸的点设置为bezier的起点
[self.bezier moveToPoint:point]; //把每条线存入字典中
NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithCapacity:];
[tempDic setObject:self.color forKey:@"color"];
[tempDic setObject:[NSNumber numberWithFloat:self.lineWidth] forKey:@"lineWidth"];
[tempDic setObject:self.bezier forKey:@"line"]; //把线加入数组中
[self.allLine addObject:tempDic]; }
(5)当移动也就是划线的时候把点存储到BezierPath中,代码如下
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouche = [touches anyObject];
CGPoint point = [myTouche locationInView:self]; [self.bezier addLineToPoint:point]; //重绘界面
[self setNeedsDisplay]; }
(6)画出线条
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
//对之前的线的一个重绘过程
for (int i = ; i < self.allLine.count; i ++)
{
NSDictionary *tempDic = self.allLine[i];
UIColor *color = tempDic[@"color"];
CGFloat width = [tempDic[@"lineWidth"] floatValue];
UIBezierPath *path = tempDic[@"line"]; [color setStroke];
[path setLineWidth:width];
[path stroke];
} }
二.画图板的使用
上面是封装画图板要用到的全部代码,下面的代码就是如何在ViewController中使用我们的画图板了,如何实例化控件,以及控件的初始化,注册回调等在这就不做赘述了,下面给出了主要控件的回调方法
1、通过Slider来调节线条的宽度
//通过slider来设置线条的宽度
- (IBAction)sliderChange:(id)sender
{
self.myView.lineWidth = self.mySlider.value;
}
2、通过SegmentControl来设置线条的颜色
/通过segmentControl来设置线条的颜色
- (IBAction)tapSegment:(id)sender { switch (self.mySegment.selectedSegmentIndex) {
case :
self.myView.color = [UIColor redColor];
break;
case :
self.myView.color = [UIColor blackColor];
break;
case :
self.myView.color = [UIColor greenColor];
break; default:
break;
} }
3、undo和redo操作
//Undo
- (IBAction)tapBack:(id)sender {
[self.myView backImage];
} //Redo操作
- (IBAction)tapGo:(id)sender {
[self.myView forwardImage];
}
4.保存操作,也许下面的保存操作在处理方式上略显笨拙,如有更好的解决方案请留言。 保存的时候我是先截了个屏,然后把白板进行切割,把切割后图片存入到相册中,代码如下:
//把画的图保存到相册
- (IBAction)tapSave:(id)sender {
//截屏
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *uiImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); //截取画图版部分
CGImageRef sourceImageRef = [uiImage CGImage];
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, CGRectMake(, , , ));
UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; //把截的屏保存到相册
UIImageWriteToSavedPhotosAlbum(newImage , nil, nil, nil); //给个保存成功的反馈
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"存储照片成功"
message:@"您已将照片存储于图片库中,打开照片程序即可查看。"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show]; }
以上就是本画图板的主要代码了,有不足之处还望批评指正。转载请注明出处。在本文结束时在来几张截图吧(demo下载地址:http://www.pgyer.com/LTQ8):
iOS开发之画图板(贝塞尔曲线)的更多相关文章
- IOS开发之画图形
1 画线 2 画线第二个方法 相对方法1简洁 3 矩形 4 圆 5 弧线 6画文字(略) 7 画图片(略)
- 我的iOS开发系列博文
之前目录性的总结了发表过的关于OC方面的文章,今天在目录性的总结一下有关iOS开发的文章.走过路过不要错过哦,今天的博文也全都是干货.写技术博客与大家交流一下思想也是不错的. 下面是我的技术博客中有关 ...
- Android 贝塞尔曲线 折线图
1.贝塞尔曲线:http://baike.baidu.com/view/60154.htm,在这里理解什么是贝塞尔曲线 2.直接上图: 3.100多行代码就可以画出贝塞尔曲线,直接上代码 packag ...
- iOS开发 贝塞尔曲线
iOS开发 贝塞尔曲线UIBezierPath - 陌云 时间 2014-03-14 11:04:00 博客园-所有随笔区 原文 http://www.cnblogs.com/moyunmo/p/ ...
- iOS开发 贝塞尔曲线UIBezierPath
最近项目中需要用到用贝塞尔曲线去绘制路径 ,然后往路径里面填充图片,找到这篇文章挺好,记录下来 自己学习! 转至 http://blog.csdn.net/guo_hongjun1611/articl ...
- IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
... 首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Con ...
- (转) IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context ...
- [置顶] IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
首先了解一下CGContextRef: An opaque type that represents a Quartz 2D drawing environment. Graphics Context ...
- iOS开发 贝塞尔曲线UIBezierPath(2)
使用CAShapeLayer与UIBezierPath可以实现不在view的drawRect方法中就画出一些想要的图形 . 1:UIBezierPath: UIBezierPath是在 UIKit 中 ...
随机推荐
- log4net写入mysql完整例子
1,创建表log CREATE TABLE `log` ( `id` int(11) NOT NULL AUTO_INCREMENT , `log_datetime` timestamp NO ...
- MySQL流程函数
#如果value是真,返回t:否则返回f if(value,t f) #如果value1不为空,返回value1,否则返回value2 ifnull(value1,value2) #如果value1是 ...
- 【转】Android Studio-1.2版本设置教程
如果重新安装Android Studio的话要重新配置风格选项啥的,这篇是个很好的教程,原文链接:http://blog.csdn.net/skykingf/article/details/45485 ...
- mac svn命令使用
对mac不熟悉 ssd硬盘又小 不想装版本管理软件. #创建目录 svn mkdir svn://ip.xxx.xxx.xxx/client/ios/opengl/imageToll -m " ...
- 关于Delphi错误:Cannot make a visible window modal
Delphi的fsMDIChild类型的窗体是不能使用ShowModal的,否则会弹出"Cannot make a visible window modal"异常, 但是把fsMD ...
- Navsion二次开发_学习笔记
CodeUnit Note This feature is documented in the Navision Application Server Technical White Paper. ...
- Xamarin.Forms 免费电子书
Xamarin Evolve 正在举行,现在已经放出2本免费的Xamarin.Forms 免费电子书,据现场的同学说这两天还有Xamarin.Forms 重磅消息发布: Creating Mobile ...
- ABP理论学习之Swagger UI集成
返回总目录 本篇目录 介绍 安装 安装Nuget包 配置 测试 介绍 从官方网站上可以看到:"启用了Swagger API,就可以获得交互式文档,生成和发现客户端SDK". 安装 ...
- io.js入门(一)—— 初识io.js
io.js可以说是彻底从NodeJS里分离出来的一条分支,其事情始末可以查看这篇报道,此处便也不赘言.既然是分支,io.js便也基本兼容NodeJS的各种API,连执行指令也依旧兼容Node的 nod ...
- CI-持续集成(2)-软件工业“流水线”技术实现
1 概述 持续集成(Continuous Integration)是一种软件开发实践.在本系列文章的前一章节已经对其背景及理论体系进行了介绍.本小节则承接前面提出的理论构想进行具体的技术实现. & ...