转载自:http://blog.csdn.net/sinat_27706697/article/details/46041769

这一节,我将介绍使用Quartz 2D实现的一个实例 -- 涂鸦。在介绍直接,先介绍一下贝塞尔曲线的基本概念。

Bezier Path 基础

UIBezierPath对象是CGPathRef数据类型的封装。path如果是基于矢量形状的,都用直线和曲线段去创建。我们使用直线段去创建矩形和多边形,使用曲线段去创建弧(arc),圆或者其他复杂的曲线形状。每一段都包括一个或者多个点,绘图命令定义如何去诠释这些点。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。每一个连接的直线或者曲线段的集合成为subpath。一个UIBezierPath对象定义一个完整的路径包括一个或者多个subpaths。

创建和使用一个path对象的过程是分开的。创建path是第一步,包含一下步骤:

(1)创建一个Bezier path对象。

(2)使用方法moveToPoint:去设置初始线段的起点。

(3)添加line或者curve去定义一个或者多个subpaths。

(4)改变UIBezierPath对象跟绘图相关的属性。

例如,我们可以设置stroked path的属性lineWidth和lineJoinStyle。也可以设置filled path的属性usesEvenOddFillRule。

我这里绘制的涂鸦效果,就是使用的UIBezierPath。效果图如下(字写的有点难看,莫怪~~~):

需求说明:

本demo支持,曲线随意画。

1. 通过点击“红绿蓝”,可以拾取自己想要的绘制颜色。

2. 通过拖拽UISlider,可以改变曲线的粗细。

3. 支持撤销、清屏、保存到相册的功能。

设计分析:

1. 每一条曲线,都有线宽,颜色,及路径信息,所以我们可以定义一个模型,用于存储这些信息。

2. 涂鸦效果是由很多条曲线构成的,所以我们可以定义一个可变数组,用于存放上面的很多模型数据。

3. 在执行撤销,清屏操作的时候,我们只需要对数组进行删除最后一条记录或者清空操作,然后调用[self  setNeedsDisplay] 方法,实时绘制。

大致代码:

自定义的模型 DrawModel.h:

@interface DrawModel : NSObject
@property (nonatomic, assign) CGFloat lineNewWidth;
@property (nonatomic, strong) UIColor *lineNewColor;
@property (nonatomic, strong) UIBezierPath *path;
@end

绘制界面的头文件 DrawView.h:

@interface DrawView : UIView@property (nonatomic, assign) CGFloat lineNewWidth;
@property (nonatomic, strong) UIColor *lineNewColor;- (void)back;
- (void)clear;@end

可变数组的定义及懒加载

@property (nonatomic,strong) NSMutableArray *infos;- (NSMutableArray *)infos {if (!_infos) {_infos = [NSMutableArray array];}return _infos;
}

点击颜色按钮和滑动UISlider应该改变对应的值

- (void)setLineNewWidth:(CGFloat)lineNewWidth {
  _lineNewWidth = lineNewWidth;
}
- (void)setLineNewColor:(UIColor *)lineColor {
  if (lineColor == nil) {
    _lineNewColor = [UIColor blackColor];
  } else {
    _lineNewColor = lineColor;
  }
}

撤销及清屏操作

- (void)back {
  [self.infos removeLastObject];
  [self setNeedsDisplay];
}
- (void)clear {
  [self.infos removeAllObjects];
  [self setNeedsDisplay];
}

保存到相册大致代码

UIImage *newImage = [UIImage imageWithView:self.paintView];
UIImageWriteToSavedPhotosAlbum(newImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

贝塞尔曲线保存路径及模型创建代码如下

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  UITouch *touch = [touches anyObject];
  CGPoint startPoint = [touch locationInView:touch.view];
  UIBezierPath *path = [UIBezierPath bezierPath];
  [path moveToPoint:startPoint];
  DrawModel *model = [[DrawModel alloc] init];
  model.lineNewWidth = self.lineNewWidth == 0 ? 1: self.lineNewWidth;
  model.lineNewColor = self.lineNewColor;
  model.path = path;
  [self.infos addObject:model];
  [self setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  UITouch *touch = [touches anyObject];
  CGPoint movePoint = [touch locationInView:touch.view];
  DrawModel *model = [self.infos lastObject];
  UIBezierPath *path = model.path;
  [path addLineToPoint:movePoint];
  [self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  [self touchesMoved:touches withEvent:event];
}

对代码进行大致说明:

1.每次手指按下时,会触发touchesBegan方法,每次创建一个UIBezierPath路径及创建数据模型DrawModel,并且将模型数据放到数组infos中。

2.手指拖动的时候,会触发touchesMoved方法,立刻从数组infos中取出拖拽前创建的UIBezierPath,并且将绘制所有的点的集合保存在贝塞尔曲线中。

3.手指抬起的时候,会触发touchesEnded方法,理论上只有一个点,但也应该完成最终的绘制,由于他所做得工作和touchesMoved一致,所以直接调用touchesMoved方法即可。

关键绘制代码如下:

- (void)drawRect:(CGRect)rect {
  for (DrawModel *model in self.infos) {
    UIBezierPath *path = model.path;
    path.lineWidth = model.lineNewWidth;
    path.lineCapStyle = kCGLineCapRound;
    path.lineJoinStyle = kCGLineJoinRound;
    [model.lineNewColor set];
    [path stroke];
  }
}

每次调用 [self  setNeedsDisplay] 方法就会触发drawRect方法。在这个方法中,我们只需要遍历infos数组,获取到每个模型数据信息,然后设置绘制相关信息就可以了。

Quartz 2D 涂鸦相关推荐

  1. Quartz 2D 屏幕解锁

    本人录制技术视频地址:https://edu.csdn.net/lecturer/1899 欢迎观看. 上一节中,我讲解了利用Quartz 2D完成的涂鸦功能,其实主要是利用了贝塞尔曲线来完成的.可以 ...

  2. Quartz 2D Programming Guide笔记

    ###Graphics Contexts图形上下文### 图形上下文(graphics context)是绘制目标,可以理解为画布,包含着绘图时的参数和设备信息.类型为CGContextRef.获取g ...

  3. iOS 2D绘图详解(Quartz 2D)之路径(点,直线,虚线,曲线,圆弧,椭圆,矩形)

    前言:一个路径可以包含由一个或者多个shape以及子路径subpath,quartz提供了很多方便的shape可以直接调用.例如:point,line,Arc(圆弧),Curves(曲线),Ellip ...

  4. iOS 2D绘图详解(Quartz 2D)之概述

    原创Blog,转载请注明出处  http://blog.csdn.net/hello_hwc?viewmode=list 前言:最近在研究自定义控件,由于想要彻底的定制控件的视图还是要继承UIView ...

  5. Quartz 2d绘图

    今天看了一下Quartz 2D绘图,我只想说:不要把绘图和动画那些东西当做一个很复杂的东西,其实只要你认真看还是可以理解的.他们并不难.啰嗦了几句,现在直接进入正题: 前提是我们必须新建一个singl ...

  6. iOS开发之Quartz 2D绘图

    2019独角兽企业重金招聘Python工程师标准>>> Quartz 2D是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境 Quartz 2D API可以实现许多功能,如 ...

  7. iPhone开发笔记[1/50]:初学iPhone上用Quartz 2D画图

    参考了An iOS 4 iPhone Graphics Drawing Tutorial using Quartz 2D这篇文章,用了30分钟在iPhone上画出了一条直线,核心代码全在drawRec ...

  8. 绘图与滤镜全面解析--Quartz 2D 、Core Image

    绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果,一方面得益于成功系统的设计,另一方面得益于它强大的开发框架.今天我们将围绕iOS中两大图形.图像绘图框架进行介绍:Quartz 2 ...

  9. quartz c语言,IOS学习之—— Quartz 2D (C语言的框架)

    //************************************************************************************************** ...

最新文章

  1. exfat最佳单元大小_047|仓储物流自动化系统中的物料单元
  2. c++局部对象是什么_小白学Web前端难点是什么 JS进阶知识点有哪些
  3. 【开源项目】基于FFmpeg的封装格式转换
  4. 树莓派Pico的一些有趣的基本实验
  5. php网站开发项目实战,PHP动态网站开发项目实战
  6. linux 命令mysql5.6,linux下mysql5.5mysql5.6的tar包安装
  7. python 配置文件返回的两种方式,写法不一样而已
  8. understanding the Euler Lagrange equation
  9. Android进阶--android自动化测试python+uiautomator
  10. Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议
  11. 神奇宝贝HTML游戏代码,方舟生存进化神奇宝贝代码资料大全
  12. 高德地图3D离线定位
  13. Chrome浏览器书签手动同步
  14. html调查问卷页面,html+js 问卷调查页面的展示以及form提交
  15. 很荣幸,和各位一起创造了历史
  16. OVM免费混合虚拟化系列教程之一:关于配置要求!
  17. PC版微信,公众号文章图片无法加载,解决方法
  18. android 换肤 字体颜色,Android换肤
  19. CENTOS上的网络安全工具(五)CODE来打个酱油
  20. [Linux] 读书笔记之:Linux程序设计(第4版)(ch1-7) [ 学如逆水行舟,不进则退 ]...

热门文章

  1. vba不能提取服务器上文件名,从全路径文件名中获取文件名(不含路径)
  2. 【托福考场考点1】山东大学托福考点详情及考友评价
  3. 如何为PPT加上页码/总页码
  4. AE TypeMonkey
  5. java switch finally_java switch语句详解
  6. NX二次开发 UFUN创建倒角特征 UF_MODL_create_chamfer
  7. 64位win7系统中vb工程显示加载MSCOMCTL.OCX失败
  8. 关于“发现在互联网状态下的生活时间流逝很快的分析”
  9. 猫和老鼠手游的python代码_猫和老鼠手游猫鼠通用技巧讲解 赶紧进来好好向大佬们学习学习...
  10. 在k8s上部署cerebro访问集群外部署的es