Skip to content
基于 Quartz2D 实现的画板。
Swift
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
MFPaintView
MFPaintViewDemo.xcodeproj 兼容iOS8.0 Oct 31, 2017
MFPaintViewDemo
MFPaintViewDemoTests 初始化 Oct 21, 2017
MFPaintViewDemoUITests 初始化 Oct 21, 2017
.gitignore 初始化 Oct 21, 2017
README.md Update README.md Jan 4, 2020
exhibition.gif 添加展示图片 Nov 23, 2017
image1.jpg 添加展示图片 Nov 23, 2017
image2.jpg 添加展示图片 Nov 23, 2017

README.md

MFPaintView

一个基于Quartz2D实现的画板,适用于Swift3.0以上版本。

如果你正在寻找一个 OpenGL ES 实现的版本,或许可以参考一下我的 另一个项目

如何导入

手动导入

将MFPaintView文件夹拖入工程中。

如何使用

1. 引入与布局

支持通过纯代码的方式xib的方式引入,支持AutoLayout布局方式Frame布局方式

2. 实现代理(可选)

实现代理MFPaintViewDelegate,可在单次绘画开始和结束时做对应的操作。
绘画即将开始时会调用:

func paintViewWillBeginDrawLine(_ paintView: MFPaintView)

绘画已经结束时会调用:

func paintViewDidFinishDrawLine(_ paintView: MFPaintView)

功能介绍

1. 调整笔触大小

实现方式:

通过设置Path的lineWidth来实现。

接口方法:
public func setPaintLineWidth(lineWidth width: CGFloat)

2. 调整笔触颜色

实现方式:

在func draw(_ rect: CGRect)中,调用path.stroke()之前,先调用color.set(),可进行笔触颜色设置。

接口方法:
public func setPaintLineColor(lineColor color: UIColor)

3. 橡皮擦功能

实现方式:

将当前颜色设置为UIColor.clear,并将BlendMode设置为CGBlendMode.clear来实现。关键代码如下:

UIColor.clear.set()
path.stroke(with: CGBlendMode.clear, alpha: 1.0)
接口方法:
public func setBrushMode(brushMode mode: MFPaintViewBrushMode)

4. 撤销和重做

实现方式:

将每一次绘画保存为一个路径,并将所有路径用栈来保存,撤销和重做只是一个出栈和入栈的过程。

接口方法:
public func undo()
public func redo()

5. 结果保存

实现方式:

对UIGraphicsGetCurrentContext()做一个render,并通过UIGraphicsGetImageFromCurrentImageContext()来获取一个UIImage对象。

接口方法:
public func snapshot() -> UIImage?

6. 清除画板

实现方式:

将保存在栈中的所有路径清空,此操作不可恢复。

接口方法:
public func cleanup()

性能优化

1. 使用贝塞尔曲线解决连接点不平滑问题

一般画线功能的实现,是通过将上次触摸点坐标与当前触摸点坐标相连。但如果在性能较差的机器上,当手指的移动速度过快时,触摸点之间的距离较大时,线条会出现明显的转折点,如下图所示。这里采用了贝塞尔曲线进行优化,以曲线的上个结束点作为起点,上次的触摸点作为控制点,上次触摸点与本次触摸点的中点作为结束点,来绘制贝塞尔曲线,从而使线条更加平滑。

2. 当夹角过小时,贝塞尔曲线转角不平滑

使用贝塞尔曲线来绘制线条会带来额外的问题,即当起始点、控制点、结束点三点构成的角度过小时,在曲线的转角处会出现平角,如下图所示。此时path的JoinStyle并不起作用,因此在连线时进行角度判定,若角度过小,则直接采取线段连接的方式,这样能保证拐角的平滑。

3. 有效减少CPU和内存的占用

1. 将全局刷新改为局部刷新

每当手指移动,产生新的触摸点时,画布需要进行重绘。若此时画布很大,而需要刷新的区域很小,则会造成不必要的浪费。因此在刷新前先计算出需要刷新的区域,然后只刷新对应区域。

2. 每次绘画避免重新绘制所有路径

为了实现撤销和重做功能,必须将每一条路径的信息都记录下来。随着绘画的进行,路径的数目会越来越多。若每次重绘,都将路径一条条重新绘制,则到最后,CPU的占用率肯定会到达100%,绘画肯定会产生卡顿。这里的做法是每次画完一条路径,都生成当前结果的image,下次重绘时,则先绘制image,再绘画路径。则保证在绘画时,最多只会重新绘制一个image和一条路径,这样能大大减少CPU的消耗。

You can’t perform that action at this time.