iOS如何开发简单的手绘应用实例详解

 更新时间:2020年12月8日 11:31  点击:1384

开发一款简单的 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()

前 4 点的代码,见 github

后续需要整理,tbd

总结

到此这篇关于iOS如何开发简单的手绘应用的文章就介绍到这了,更多相关iOS开发手绘应用内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • MySQL性能监控软件Nagios的安装及配置教程

    这篇文章主要介绍了MySQL性能监控软件Nagios的安装及配置教程,这里以CentOS操作系统为环境进行演示,需要的朋友可以参考下...2015-12-14
  • iOS APP h5快捷程序 .mobileconfig的生成

    1.从APP Store 下载Apple Configurator 2从一个管理点管理所有iOS设备应用程序,文档和配置文件。想要确保您的所有家庭成员在其每台iOS设备上都有类似的应用和文档,管理日益增...2021-12-23
  • iOS设置UIButton文字显示位置和字体大小、颜色的方法

    这篇文章给大家分享了iOS如何设置UIButton的文字显示位置和字体的大小、颜色,文中给出了示例代码,相信对大家的学习和理解很有帮助,有需要的朋友们下面来一起看看吧。...2020-06-30
  • iOS如何将图片裁剪成圆形

    这篇文章主要为大家详细介绍了iOS如何将图片裁剪成圆形,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-30
  • iOS给border设置渐变色的方法实例

    这篇文章主要给大家介绍了关于iOS给border设置渐变色的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-09
  • iOS新版微信底部返回横条问题的解决

    这篇文章主要介绍了iOS新版微信底部返回横条问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
  • vscode搭建STM32开发环境的详细过程

    这篇文章主要介绍了vscode搭建STM32开发环境的详细过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-05-02
  • vue+axios全局添加请求头和参数操作

    这篇文章主要介绍了vue+axios全局添加请求头和参数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-24
  • iOS蓝牙设备名称缓存问题的解决方法

    这篇文章主要给大家介绍了关于iOS蓝牙设备名称缓存问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08
  • 安卓开发之Intent传递Object与List教程

    下面我们一起来看一篇关于 安卓开发之Intent传递Object与List的例子,希望这个例子能够为各位同学带来帮助。 Intent 不仅可以传单个的值,也可以传对象与数据集合...2016-09-20
  • iOS新版微信底部工具栏遮挡问题完美解决

    这篇文章主要介绍了iOS新版微信底部工具栏遮挡问题完美解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
  • php微信公众账号开发之五个坑(二)

    这篇文章主要为大家详细介绍了php微信公众账号开发之五个坑,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-02
  • 如何设计一个安全的API接口详解

    在日常开发中,总会接触到各种接口,前后端数据传输接口,第三方业务平台接口,下面这篇文章主要给大家介绍了关于如何设计一个安全的API接口的相关资料,需要的朋友可以参考下...2021-08-12
  • iOS新增绘制圆的方法实例代码

    这篇文章主要给大家介绍了关于iOS新增绘制圆的方法,文中通过示例代码介绍的非常详细,对各位iOS开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-30
  • iOS UIBezierPath实现饼状图

    这篇文章主要为大家详细介绍了iOS UIBezierPath实现饼状图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-03-20
  • 封装 axios+promise通用请求函数操作

    这篇文章主要介绍了封装 axios+promise通用请求函数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-12
  • 微信开发生成带参数的二维码的讲解

    在微信公众号平台开发者那里,在“账号管理”那里,有一项功能是“生成带参数的二维码”,通过这儿生成的二维码,只要通过微信扫一扫之后,会把事件自动推送到微...2016-05-19
  • IOS获取各种文件目录路径的方法

    ios获取文件路径的方法,iphone沙箱模型的四个文件夹,通过documents,tmp,app,Library得到模拟器路径的简单方式,下面小编整理相关资料,把IOS获取各种文件目录路径的方式总结如下,需要的朋友可以参考下...2020-06-30
  • iOS UICollectionView实现卡片效果

    这篇文章主要为大家详细介绍了iOS UICollectionView实现卡片效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-30
  • Vue中 axios delete请求参数操作

    这篇文章主要介绍了Vue中 axios delete请求参数操作,具有很好的参考价值,希望对大家有所 帮助。一起跟随小编过来看看吧...2020-08-26