手把手教你通过Quartz2D制作彩色涂鸦板和手势解锁

我们已经学习完了Quartz2D的一些基本的用法,在实际开发过程中,经常使用Quartz2D,可以帮助我们少使用苹果自带的控件,直接画图到上下文,对系统的性能是一个非常好的优化方式。Quartz2D的功能强大,绝逼不是画线,绘制图片那么easy,今天讲一下他在实际项目中的应用,顺便将思路理清楚,方便大家看涂鸦板demo,还有手势解锁


文章中的几个demo

  • 1.使用图形上下文制作涂鸦板
  • 2.使用贝塞尔路径制作涂鸦板
  • 3.手势解锁

下面详细的介绍一下项目的思路

一.使用图形上下文制作涂鸦板
111648725-2bf3d5c28304c04b
效果图
121648725-d65334c31b49ab34

点击保存,在相册中的图片

分析
1.涂鸦板实际上就是绘制很多的线条
2.保存线条,使用可变数组
3.使用上下文绘制图片,使用drawRect方法
4.和屏幕交互,应该使用touchesBegin方法

代码分析

1.自定义一个DBPainterView
2.在view中生成一个可变数组作为变量,懒加载处理,可以供程序使用

3.实现touchesBegin,touchesMoved,touchesEnd方法

代码分析,
3.1.touchesBegin就是开始绘制,现在没有拿到路径的具体的点,所以我们应该给每一个路劲用一个小数组保存所有点的数组 linePathArr(保存每一根line的数组),每一次调用都应该是创建一个新的路径(新的linePathArr),然后加到保存所有路径的数组中( pointArr保存了所有line的数组),然后调用setNeedsDisplay方法,绘制路径
3.2.touchesMoved方法是手指在屏幕移动的时候调用的,频率最高,就是一直在添加point,说白了,就是给最新添加的那个路径添加点,所以应当找到数组中最后一个路径,然后给这个路径添加point,let lastLineArr = pointArr.lastObject,lastLineArr!.addObject(NSValue.init(CGPoint: startPoint!))
3.3.touchEnd方法和2的事情是一样的,所以可以提炼一下代码,我就不写了

4.绘制图片 drawRect

4.1 首先遍历大数组A,获取每一条线(所有点)的数组B,遍历B中所有的点,但是B中的第一个b[0]应该是调用CGContextMoveToPoint,b[其他]应当调用CGContextAddLineToPoint方法,
4.2.可以设置一下图形上下文的属性,最后渲染就好了.
4.3 可以设置好多种颜色,使用图形上下文栈就可以实现

5.DBPainterView 对外实现的“上一步”,”清空”,“保存”功能

代码太简单,就不解释了哈

二.使用贝塞尔路径制作涂鸦板
131648725-d7472d94ae9b4b5f
彩色画板

刚才使用了图形上下文绘制路径,感觉还行,但是可以简化,刚才说的将一个路径的所有点放到路径的数组中,然后根据点来绘制,可以理解,但是会很麻烦,因为底层就是通过CGContextPathRef绘制路径的,因为CGContextPathRef是C语言,大数组不能添加它,所以我们放弃,然后选择贝塞尔路径,他是oc中对象,非常适合制作涂鸦板

使用贝塞尔路径制作涂鸦板的步骤(和图形上下文基本一致)

  • 1.懒加载一个用来橙装所有路径的数组pathArr
  • 2.touchesBegin的时候,生成一个路径,调用moveToPoint方法,添加起点,将path保存到数组中
  • 3.更改线宽和更改线的颜色,要个自定义的view设置lineWidth,和lineColor这个属性,最后要去给path设置这两个属性

  • 3.touchesMovedtouchesEnd方法功能一致,就合二为一了,就是获取大数组中最后一个路径,然后调用addLineToPoint方法

4.绘制路径

5.添加线宽和线颜色的属性

5.1 我们要将颜色和宽的的属性使用到以后的线上,不能影响到过去的,所以,应该在生成一个path的时候,直接设置他的这两个属性,因为path中没有lineColor这个属性,所以自定义一个DBBezierPath

5.2 重新修改一下touchesBegin方法

5.3 在渲染的时候,我们要将自定义的lineColor取出来,渲染

5.4 这样就可以制作出彩色的画板了,而且其他保存,上一步等功能都可以正常使用

使用了贝塞尔路径,远离了两个数组,运行和理解起来超级简单?


三.手势解锁
141648725-cd63c4592693515a

要做这样的手势解锁控件

思路和注意点

  • 1.创建基本的九宫格样式UI
  • 2.抽取方法类和自定义一个button(注意btn.userInteractionEnabled = false
  • 3.提出工具方法
    3.1 获取当前的触摸点
    3.2 判断当前点是不是在btn中
  • 4.保存选中的所有按钮
  • 5.通过选中的按钮连线
    5.1 防止数组中多次添加同一个button
  • 6.使用touchesEnd方法清空数组
    6.1 给drawRect方法添加判空的条件
    6.2 重新绘制状态
    6.3 使用makeObjectsSelect方法让所有的button的选中状态为NO
  • 7.绘制最后一个按钮和手指移动的地点的连线
    7.1 在touchesMoved方法中保存手指的所在的point
    7.2 在drawRect方法中链接最后一个按钮和point
    7.3 设置bezierPath的基本属性
    7.4 解决刚刚点击第一个按钮,但是连线到CGPointZore的bug(在TouchBegin中清空,在drawRect判断)
  • 8.减小触摸button的响应范围
  • 9.拼接用户的触摸路径
  • 10.添加代理方法,让外界知道用户的触摸路径(给代理添加IBOut)
  • 11.修改连线的具体颜色

代码讲解分析

1.创建基本的九宫格样式UI

151648725-c0efd63c52b8111c

基本目标
  • 1.1 自定义一个GULockView,然后使用经典九宫格算法实现

  • 1.2 布局UI

2.抽取方法类和自定义一个button

  • 2.1 自定义一个GUButton,设置内部的图片等样式,

  • 2.2btn.userInteractionEnabled = false 一定要写
161648725-51e98577d883a0d1

userInteractionEnabled = false
171648725-0bf5d00b652b3194

userInteractionEnabled = ture

这个涉及到了时间传递,我们马上要去实现触摸的三个方法,如果手势路过btn,恰巧userInteractionEnabled = ture,那么手势直接让btn截获,那么GULockView获取不到手势,造成了问题,所以一定要设置为no,(如果就是不想设置为no,其实也可以在自定义的CGButton中实现touches三个方法,调用super.touches三个方法往上传递,不推荐)

3.提出工具方法,设置btn被选中的条件

3.1 获取当前的触摸点

3.2 判断当前点是不是在btn中

3.2 设置btn被选中的状态

4.保存选中的所有按钮

可以通过一个数组来保存所有的按钮

touchesBegantouchesMoved方法中添加所选择的按钮

5.通过选中的按钮连线

5.1 防止数组中多次添加同一个button

181648725-bd0478eb4b025ce3

出现了问题,数组中添加了重复的btn

解决方法

6.使用touchesEnd方法清空数组

6.1 给drawRect方法添加判空的条件

6.2 重新绘制状态

7.绘制最后一个按钮和手指移动的地点的连线

7.1 在touchesMoved方法中保存手指的所在的point

7.2 在drawRect方法中链接最后一个按钮和point

7.3 设置bezierPath的基本属性

191648725-ff9700d015c0df51

currentPoint一直没有清空,所以touchesBegin的时候,链接点都是过去的那个,只要清空就好

7.4 解决刚刚点击第一个按钮,但是连线到CGPointZore的bug(在TouchBegin中清空,在drawRect判断)

8.减小触摸button的响应范围

现在的项目,你的鼠标刚刚到一个btn的边缘,就已经链接了线,这样的体验不好,我们想去设定当手势到了btn的圆心才连线(减小链接线的响应范围)

9.拼接用户的触摸路径

10.添加代理方法,让外界知道用户的触摸路径(给代理添加IBOut)

添加属性

11.修改连线的具体颜色

你随意吧~

1 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部