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

 更新时间:2020年09月07日 09:39:39   作者:邓轻舟  
这篇文章主要给大家介绍了关于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()

前 4 点的代码,见 github

后续需要整理,tbd

总结

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

相关文章

  • iOS10通知框架UserNotification理解与应用

    iOS10通知框架UserNotification理解与应用

    在iOS10系统中,通知被整合进了UserNotification框架,除了使通知的处理脱离了UIApplication,通知功能的相关开发更加结构化与模块化外,还新增开放了许多更加灵活的开发接口,现在,开发者可以为通知定义UI末班,添加媒体附件,需要的朋友可以参考下
    2016-09-09
  • iOS Swift 值类型与引用类型使用区别基础详解

    iOS Swift 值类型与引用类型使用区别基础详解

    这篇文章主要为大家介绍了iOS Swift 值类型与引用类型使用区别基础详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • iOS开发中以application/json上传文件实例详解

    iOS开发中以application/json上传文件实例详解

    在和sever后台交互的过程中、有时候、他们需要我们iOS开发者以“application/json”形式上传,具体实例代码大家参考下本文
    2017-07-07
  • IOS 获取APP 版本号的实例详解

    IOS 获取APP 版本号的实例详解

    这篇文章主要介绍了IOS 获取APP 版本号的实例详解的相关资料,需要的朋友可以参考下
    2017-07-07
  • iOS手势的实现方法

    iOS手势的实现方法

    这篇文章主要为大家详细介绍了iOS手势的实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • touchesBegan: withEvent: 不执行解决

    touchesBegan: withEvent: 不执行解决

    这篇文章主要介绍了touchesBegan: withEvent: 不执行解决的相关资料,需要的朋友可以参考下
    2016-12-12
  • iOS自带文本转语音技术(TTS)的实现即语音播报的实践

    iOS自带文本转语音技术(TTS)的实现即语音播报的实践

    这篇文章主要介绍了iOS自带文本转语音技术(TTS)的实现即语音播报的实践,本文介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • iOS AVPlayer切换播放源实现连续播放和全屏切换的方法

    iOS AVPlayer切换播放源实现连续播放和全屏切换的方法

    这篇文章主要给大家介绍了关于iOS中AVPlayer切换播放源实现连续播放和全屏切换的方法,文中给出了详细的示例代码供大家参考学习,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-05-05
  • iOS开发之视图切换

    iOS开发之视图切换

    在iOS开发中视图的切换是很频繁的,独立的视图应用在实际开发过程中并不常见,除非你的应用足够简单。在iOS开发中常用的视图切换有三种,今天我们将一一介绍,希望大家能够喜欢。
    2016-04-04
  • iOS开发中使用UIScrollView实现无限循环的图片浏览器

    iOS开发中使用UIScrollView实现无限循环的图片浏览器

    这篇文章主要介绍了iOS开发中使用UIScrollView实现无限循环的图片浏览器的方法,感兴趣的小伙伴们可以参考一下
    2016-03-03

最新评论