iOS如何开发简单的手绘应用实例详解
开发一款简单的 iOS 手绘应用,
收集点,绘制形状,给形状着色,呈现给用户,好像就完了
框架是 Quartz2D
1, 收集点
首先需要有一个界面 UIView, 用这个界面监听用户的手势,收集点
- 用户按下手指
location(in, 从触摸事件中,获得在画板中的坐标
var lastPoint = CGPoint.zero override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first else { return } // ... lastPoint = touch.location(in: view) }
- 用户移动手指
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { // ... }
- 用户抬起手指
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { // ... }
2, 绘制形状,给形状着色
开辟一块绘图上下文 UIGraphicsGetCurrentContext,
使用采集的点连线
用户手绘的不是一段连续的曲线,是很多个线段拼接起来的
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) { UIGraphicsBeginImageContext(view.frame.size) guard let context = UIGraphicsGetCurrentContext() else { return } // ... // 绘制 context.move(to: fromPoint) context.addLine(to: toPoint) context.setLineCap(.round) context.setBlendMode(.normal) context.setLineWidth(brushWidth) context.setStrokeColor(color.cgColor) context.strokePath() // ... UIGraphicsEndImageContext() }
3, 呈现给用户
第一步使用的 UIView 是 UIImageView,
- 绘制就是画一小段,取出画好的图片,赋给 UIImageView,我们就看到了
- 连续的绘制,是画一小段,取出画好的图片,赋给 UIImageView,并用变量保存下最新的图片
接着画,先把刚才的图片变量绘制一遍,再画一小段,取出画好的图片,赋给 UIImageView,并用变量保存下最新的图片
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) { UIGraphicsBeginImageContext(view.frame.size) guard let context = UIGraphicsGetCurrentContext() else { return } tempImageView.image?.draw(in: view.bounds) // 绘制 ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() }
4, 画笔设置
修改画笔颜色和粗细
func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) { UIGraphicsBeginImageContext(view.frame.size) guard let context = UIGraphicsGetCurrentContext() else { return } // ... context.setBlendMode(.normal) // 调颜色 context.setLineWidth(brushWidth) // 调粗细 context.setStrokeColor(color.cgColor) // ... }
画笔变橡皮擦
- 方法一,把画笔的颜色,调成画板的颜色,就成了橡皮擦
- 方法 2 ,
把画笔的颜色,调成透明,
把绘图上下文的混色模式改掉
就成了橡皮擦
switch type { case .pencil, .none: context.setBlendMode(.color) case .eraser: context.setLineWidth(15) context.setStrokeColor(UIColor.clear.cgColor) context.setBlendMode(.clear) }
5,后续
更多功能:
加入文本输入功能,
需要一个文本框控件 UITextField、 UITextView
文本框控件一般可以拖动,
文本框放在画布上,拖出画布了,有些问题。
这时候要做一个边界检测
性能优化:
一般性能优化,就是打印函数的执行时间
当画布的大小为 1366 X 7700 ( iPad Pro + UIScrollView ) 的时候,画布很大,
全部绘制一遍,并取出图片,性能消耗很大
tempImageView.image?.draw(in: view.bounds) // ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
绘制一次,需要约 0.07 秒,
let t = Date() self.drawingImage() if #available(iOS 13.0, *) { let span = t.distance(to: Date()) print(span) }
我们期望 60 的 FPS, 每一帧计算时间 0.016, 所以频繁调用该方法,卡得厉害
之前的方法是一个点,一个点的绘制
移动一下,绘制一次
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first else { return } swiped = true let currentPoint = touch.location(in: view) drawLine(from: lastPoint, to: currentPoint) lastPoint = currentPoint }
画一段线, func touchesMoved() ,一般可以触发 30 ~ 60 次,收集的点比较多,线条柔和
此时频繁调用该消耗性能方法,
只能触发 6 次,画一段只能采集 6 个点,正常手速,就画出来一个多边形
可以这样优化,点的收集与绘制分离
使用一个 Timer ,每隔 0.15 秒,绘制一次
原本收集点,是一个 CGPoint, 现在收集点,是一个 [CGPoint]
- 原本画一次之前的 image, 连一根线,更新图片变量并呈现
n 个点, 来 n 次全画板绘制
- 现在画一次之前的 image, 连接多根线,更新图片变量并呈现
n 个点, 来 1 次全画板绘制
消耗性能的方法,少调用,就对了
tempImageView.image?.draw(in: view.bounds) // ... tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
后续需要整理,tbd
总结
到此这篇关于iOS如何开发简单的手绘应用的文章就介绍到这了,更多相关iOS开发手绘应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
iOS10通知框架UserNotification理解与应用
在iOS10系统中,通知被整合进了UserNotification框架,除了使通知的处理脱离了UIApplication,通知功能的相关开发更加结构化与模块化外,还新增开放了许多更加灵活的开发接口,现在,开发者可以为通知定义UI末班,添加媒体附件,需要的朋友可以参考下2016-09-09iOS开发中以application/json上传文件实例详解
在和sever后台交互的过程中、有时候、他们需要我们iOS开发者以“application/json”形式上传,具体实例代码大家参考下本文2017-07-07touchesBegan: withEvent: 不执行解决
这篇文章主要介绍了touchesBegan: withEvent: 不执行解决的相关资料,需要的朋友可以参考下2016-12-12iOS AVPlayer切换播放源实现连续播放和全屏切换的方法
这篇文章主要给大家介绍了关于iOS中AVPlayer切换播放源实现连续播放和全屏切换的方法,文中给出了详细的示例代码供大家参考学习,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。2017-05-05iOS开发中使用UIScrollView实现无限循环的图片浏览器
这篇文章主要介绍了iOS开发中使用UIScrollView实现无限循环的图片浏览器的方法,感兴趣的小伙伴们可以参考一下2016-03-03
最新评论