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 中 ...
随机推荐
- js闭包-在你身边却不知
今天组里小伙很纳闷的问了我js绑事件带出的一个小问题,随便聊聊闭包那点事,背景如下: 当点击Button的时候给li绑定事件,事件的大概内容是获取li位置的index再做点事,据他描述代码看上去也没错 ...
- 简单C#、asp.net mvc验证码的实现
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Text;u ...
- ssh简化后之事务管理
为了能让大家更好的了解,所以今天跟大家分享整个项目.ps:ssh环境的搭建我就不一一讲解了,请大家参考 http://www.cnblogs.com/zczc1996/p/5842367.html. ...
- javascript模块化编程(三):require.js用法
本文来自阮一峰 这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require ...
- unison+inotify
hostnamectl --static set-hostname tCentos 1.下载文件到/usr/local/srcocamlunisoninotify-tools 2.安装inotify- ...
- Android应用性能优化(转)
人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...
- syntax error near unexpected token‘(
用虚拟机的时候出现这样的: 上网查了资料之后,在括号"( " 前加上"$"字符就暂时不会提示出错了.
- ffmpeg编译与移植问题
1.下载ffmpeg. 下载网址:http://www.ffmpeg.org/download.html 2.解压缩 tar -zxvf ffmpeg-2.0.1.tar.gz 3.配置,生成Make ...
- .net 下新版highcharts本地导出图片bug处理
最近公司要用到highcharts这个插件来生成图表,所以我花了点时间研究了下. 现在最新的版本是3.0.2,这js插件居多优点就不比多说了,demo官网上也很详细.但是优点不爽的地方是,导出图片这个 ...
- 第一篇博客 用笨办法学python-14 提示和传递
# 代码如下: usr_name = input("")script = input("")prompt = '> 'print("hi %s, ...